25
\$\begingroup\$

This is a rather common inquiry in contests that require computing elements of a sequence.

For example, consider the following recursive implementation of the factorial function (Python):

f = lambda n:n<1or n*f(n-1)

This works well for all positive n; f(n) returns the required result as an int.

However, f(0) will return the result of the comparison n<1, which is the the bool True.

Fixing this is easy enough, but it costs a few bytes:

f = lambda n:0**n or n*f(n-1)

While it is possible to think of the Booleans True and False as numbers (usually 1 and 0) and use them as such in languages such as Python, languages such as Java or Ruby do not even allow casting a Boolean to a numeric type.

Since this is such a common scenario, I think we would benefit from a default. If a challenge doesn't contemplate returning Booleans instead of numbers, should it be allowed or forbidden?

\$\endgroup\$
10
  • 2
    \$\begingroup\$ Python says True's an integer: >>> isinstance(0 < 1, int) True When has it ever lied to us? \$\endgroup\$
    – feersum
    Apr 29, 2016 at 4:45
  • 1
    \$\begingroup\$ @feersum or more simply; >>> True == 1 True \$\endgroup\$
    – Cyoce
    Apr 29, 2016 at 7:16
  • 1
    \$\begingroup\$ @feersum That's because in Python, bool is a trivial subclass of int \$\endgroup\$
    – cat
    Apr 29, 2016 at 16:15
  • 1
    \$\begingroup\$ @Cyoce == may cast 1 to True. \$\endgroup\$
    – Riker
    Apr 30, 2016 at 1:48
  • 1
    \$\begingroup\$ @EᴀsᴛᴇʀʟʏIʀᴋ Python does not have casts. the int(), bool() and etc functions are like casts, but they aren't actually casts. The fact is, True and False are numbers in Pyfon. \$\endgroup\$
    – cat
    Apr 30, 2016 at 16:13
  • \$\begingroup\$ @Riker feersum's comment shows that there's no type casting. \$\endgroup\$
    – mbomb007
    Mar 22, 2017 at 14:45
  • 1
    \$\begingroup\$ When you try 1 is True it returns false, in Python.... \$\endgroup\$
    – sporkl
    Mar 22, 2017 at 19:41
  • 1
    \$\begingroup\$ @SparklePony So does [] is []. \$\endgroup\$
    – Dennis
    Mar 22, 2017 at 23:24
  • \$\begingroup\$ @Dennis True is True returns True.... \$\endgroup\$
    – sporkl
    Mar 23, 2017 at 14:04
  • 1
    \$\begingroup\$ @ComradeSparklePony is tests for reference equality. Every instance of True is the same object, but this is not necessarily true for [], "", 1, etc. \$\endgroup\$ Oct 11, 2017 at 15:41

3 Answers 3

29
\$\begingroup\$

If it quacks like a number, it's a number

Let's look at some Python examples.

>>> 2 * 1
2

>>> 2 * 0
0

Cool, 2, 1, and 0 are all numbers. That's not being contested here.

>>> 2 * True
2

>>> 2 * False
0

True and False act just like 1 and 0 (respectively). In fact, 1 == True and 0 == False. The only difference is that 1 and 0 are instances of int, and True and False are instances of bool (which is itself a subclass of int). This is by design.

In C, they are exactly the same: true and false are preprocesser macros defined as 1 and 0, respectively.

In short: if you can use a boolean just like a number, then booleans are acceptable substitutes for numbers, since they're functionally identical.

More general: Data types can be substituted so long as the alternate data type is functionally identical to the intended/original data type. For C, this means using uint_8 instead of char is acceptable. For Python, this means that bool and int are interchangeable.

However, this does not apply to challenges where an exact string output is required. For example, in Ninety-Nine Bottles of Beer, the second-to-last verse must be "1 bottle of beer on the wall...", not "True bottle of beer on the wall...".

\$\endgroup\$
20
  • \$\begingroup\$ This makes sense to me. Duck-typing FTW! \$\endgroup\$
    – Cyoce
    Apr 29, 2016 at 7:16
  • 5
    \$\begingroup\$ While we're at it, does the same logic apply to chars? For example, if I'm golfing in C and I output '*' where the correct answer is 42, is that acceptable? (I assume the answer is yes, but it would be nice to have this explicitly stated, and it's relevant to the current question) \$\endgroup\$
    – DJMcMayhem
    Apr 29, 2016 at 16:38
  • 4
    \$\begingroup\$ @DrGreenEggsandHamDJ In C, there is no difference between char c = '*'; and char c = 42; (since char is an integral type), so I'd say that's valid. \$\endgroup\$
    – user45941
    Apr 29, 2016 at 18:49
  • \$\begingroup\$ Does just like a number mean you have to be able to replace numbers with the associated Booleans in all arithmetic operations? \$\endgroup\$
    – Dennis
    Apr 29, 2016 at 18:58
  • \$\begingroup\$ @Dennis In all operations relevant to the submission. So, for your example (f = lambda n:n<1or n*f(n-1)), you can use any data type for n, so long as <, *, and - work the same as they do for integers. \$\endgroup\$
    – user45941
    Apr 29, 2016 at 19:05
  • 5
    \$\begingroup\$ That seems a bit weak. It would allow "\n \v\f\r" (in JavaScript) and "abc" (in Perl) as valid representations of 0. \$\endgroup\$
    – Dennis
    Apr 29, 2016 at 19:07
  • \$\begingroup\$ @Dennis Valid point. I'll change it to "all operations". \$\endgroup\$
    – user45941
    Apr 29, 2016 at 19:19
  • 3
    \$\begingroup\$ How does this extend to, say, True bottle of beer on the wall (amongst the other lines of the relevant song)? \$\endgroup\$
    – Sp3000
    May 1, 2016 at 14:02
  • 2
    \$\begingroup\$ @Sp3000 When a challenge has specific, strict output, it must match byte-for-byte. If the challenge just wants a value for an output (and is not strict on the format), then these looser rules apply. \$\endgroup\$
    – user45941
    May 1, 2016 at 18:01
  • \$\begingroup\$ @Mego Just to clarify - I don't necessarily mean Kolmogorov complexity problems, e.g. if there was a problem that required returning a certain number of integer dollars - would "$True" still be fine? \$\endgroup\$
    – Sp3000
    May 9, 2016 at 15:13
  • \$\begingroup\$ Data types can be substituted so long as they are functionally identical. I think this should rather be one-way: data type A can be used instead of data type B if doing so results in something functionally identical (even if the reverse substitution does not). For example, in Matlab false can be used instead of 0, but replacing a false by a 0 may produce different results \$\endgroup\$
    – Luis Mendo
    May 9, 2016 at 23:03
  • \$\begingroup\$ @LuisMendo I like that wording. I'll edit this post soon. \$\endgroup\$
    – user45941
    May 9, 2016 at 23:09
  • 7
    \$\begingroup\$ This answer seems to me to create more confusion than previously existed. What does "functionally identical" mean? It obviously doesn't mean that there's no function which distinguishes them, or the question wouldn't have arisen in the first place. To take the first example, of Python True vs 1, printing them gives different results. \$\endgroup\$ May 10, 2016 at 10:09
  • 3
    \$\begingroup\$ @Sp3000 I think that (assuming that $ just means $, not a eval operator like Julia) doesn't count as integer output anymore. That is a string, and True is not one. TL;DR: That isn't plain integer output, so True won't work \$\endgroup\$
    – Riker
    Jun 6, 2016 at 14:37
  • \$\begingroup\$ Does it need to be functionally equivalent in the language being used? Can I return true instead of 1 in a language where they are not equivalent, mimicking the output of a function in a language where they are equivalent? \$\endgroup\$
    – Sparr
    Dec 20, 2018 at 2:02
11
\$\begingroup\$

By default, answers should provide what the question asks for

If the question asks for a number, the answer should provide a number. We have various defaults partly to reduce boilerplate, but also to cover issues which a first-time poster wouldn't think about and where their failure to think about it would seriously affect question quality.

A first-time poster wouldn't think about allowing answers to their integer number sequence question to print True rather than 1, and it would be quite reasonable for their reaction when someone does that and then points at meta to be along the lines of "This is stupid. I'm going to edit my question."

So consider two scenarios:

Scenario 1: new user posts a question, making perfectly reasonable assumptions about what kind of answers would be permitted; someone posts an answer which prompts the new user to want to disqualify that answer. This runs up against our general distaste for question edits which disqualify existing answers.

Scenario 2: new user posts a question; experienced user requests them to edit it to allow Booleans. Either they don't want to, and make that clear; or they agree, and edit. In neither case is any existing answer disqualified.

The second scenario seems to me to be clearly preferable and the comparison seems to be sufficient reason in itself to require that by default this should not be allowed.

Of course, nothing prevents those who want from adding the following line to their questions:

If your language has a Boolean type for which true and false are each equal to exactly one integer value, you may return/output that type instead of an integer when the specified output would otherwise be that integer.

\$\endgroup\$
7
\$\begingroup\$

Not in Inputs/Outputs

Allowing booleans to be returned instead of numbers is completely against the whole point of booleans in languages.

Booleans are not necessary, but are implemented to make a distinction between the "simple" numbers 1 and 0 and the boolean values true and false.

The implementation of booleans in the language has no influence on this: the fact that it is implemented means that it is intended to be semantically different from numbers.

Note: If your boolean gets returned as a number, then that's obviously valid. Similarly you can use booleans however you want inside your program.

Note 2: I have the exact same view for chars. Arguing that an output of '*' is valid if the expected output is 42 is completely ridiculous. As before, if your '*' gets printed as 42 then it's fine.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ I agree with this for the most part, but in code-golfing requiring to cast to a separate type for code-golf where in code it would work as a number could be considered pointless. \$\endgroup\$
    – Downgoat
    May 1, 2016 at 5:23
  • 1
    \$\begingroup\$ * IS valid for 42 if we're using brainfuck... \$\endgroup\$
    – mbomb007
    Mar 22, 2017 at 14:41

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .