Given a number N, output the sign of N:
- If N is positive, output 1
- If N is negative, output -1
- If N is 0, output 0
N will be an integer within the representable range of integers in your chosen language.
This (ab)uses the fact that
dc keeps the stack as is, if you're trying to divide by 0 which really helps for this challenge:
[_1*]sa # store the macro in register a (macro negates the top) ? # push input to stack d # duplicate top d0>a # if top is negative, execute macro / # divides top two values p # print the top of the stack
L, - Create a lambda. Example argument: -8 d - Duplicate; STACK = [-8 -8] 0 - Push 0; STACK = [-8 -8 0] < - Less than; STACK = [-8 0] @ - Reverse; STACK = [ 0 -8] 0 - Push 0; STACK = [ 0 -8 0] > - Greater than; STACK = [ 0 1] _ - Subtract; STACK = [-1] Implicitly return -1
functoid there is no support for negative integers since numbers are handled as Church numerals. This solution redefines numbers in a way that supports negative numbers (please refer to the explanation):
<|12K0K$BbB r<@.1,"-" )<@.([
The definition of negative numbers extends the Church numerals by simply introducing another lambda abstraction that encodes the sign of a number (the first argument, ie.
x3). Here is how the numbers -2,-1,0,1,2 would look like in this notation:
Decimal number | extended Church numerals | absolute value as Church numeral ---------------+--------------------------+--------------------------------- -2 | λλλ(x3 (x2 (x2 x1))) | λλ(x2 (x2 x1)) -1 | λλλ(x3 (x2 x1)) | λλ(x2 x1) 0 | λλλ(x1) | λλ(x1) 1 | λλλ(x2 x1) | λλ(x2 x1) 2 | λλλ(x2 (x2 x1)) | λλ(x2 (x2 x1))
Now for the explanation of the above code: The characters
< will change the direction to left, this saves us four bytes but makes it more difficult to read.. Here's how the code would look like without doing this:
BbB$K0K21| @.1,"-"r< @.([)<
BbB ensures that
K2 get grouped as one expression each, here's the more verbose code:
$(K0)(K2)1| @.1,"-"r< @.([)<
Okay now it's quite readable: First
$ will apply the input so we'll have a sign-extended Church numeral as current expression. Applying
0) will evaluate to
KK0 (which will "swallow" the next two arguments) in the case of a negative number, in the case of a non-negative number it simply vanishes. In the case of a positive number we'll have
K2 which will swallow the argument
1 and else we'll finally get
Summing up the function
$(K0)(K2)1 gives the following numbers (regular Church numerals):
if input < 0: return 0 elif input > 0: return 2 else: return 1
| will set the direction down iff the current expression evaluates to
0 and up in the other case.
[which decrements it by 1, prints the expression (as a numeral) and terminates
It might look like the above extension was done just to make this task easier, however this is not the case. In fact most definitions in the untyped (or rather uni-typed) lambda calculus are made because they simplify a lot of operations that one could be interested (such as Booleans or the Church numerals themselves).
As an example the function
abs could be "implemented" by just applying the identity function to such an extended numeral which will get rid of one lambda abstraction (and in case of a negative number, keep the absolute value as is).
If you're interested, here is an article that talks more about this definition which is worth a read.
n=tonumber(...) print(n<0 and -1 or n>0 and 1 or 0)
... is the variable that represents arguments in lua, tonumber(...) converts the first argument to a number.
also in lua a and b or c is a structure that returns b if a is truthy or c if a is falsy, you can nest this structure as well
i flag for integer output. Input must be appended to the code on a separate line. This is equivalent to the C code
(n>0)-(n<0). Try it online!
Alternatives with the same bytecount:
I:0(qm$0)+h I Input as number : Duplicate top 0( Change top to "top < 0" q If top is true... m$ Push -1 and swap top two; the stack is [-1 x] Otherwise, skip two commands (m$); the stack is [x] 0) Change top to "top > 0" + Add top two h Print top as number and halt
open Checked let s n= if n=0 then 0 else try let mutable p=n while p<>0 do p<-p+1 -1 with| :? System.OverflowException->1
Basically, if the number is non-zero, keep adding
1 to it until you get either
0 (so the original value was negative) or an overflow (so the original value was positive).
That's all right, isn't it?