C, 56 bytes
c=1;f(char*a){c=-c;*a&16?c+=1-*a-1[a],c&=2,c/=2:f(a+1);}
Hint: only the last two bits count.
The basic idea was to use least significant bit for storing result of factorial, and next bit for storing the negation, then xoring the two.
c=0;
for(;*a<34;a++)c^=2; // invert the 2nd bit at each negation
while(*a)c|=*a++; // '0' ends with bits 00, '1' and '!' ends with bits 01, so this OR will let the first bit to resut of factorial (LSB) and leave the 2nd bit unchanged
c=((c>>1)^c)&1; // apply the negation (2nd bit) on the factorial (1st bit)
But it makes our intentions too clear. First, we don't need a loop for the factorial, and we can allways take 2 char, the 2nd being eventually a NULL terminator will have neutral 00 end bits. This is much like the answer Mathematics is fact. Programming is not from Ahemone, but longer and less elegant so far.
c=0;
while(*a++<34)c^=2; // invert the 2nd bit at each negation
c|=*a,c|=*--a; // '0' and NULL ends with bits 00, '1' and '!' ends with bits 01, so this OR will let the first bit to resut of factorial (LSB) and leave the 2nd bit unchanged
c=((c>>1)^c)&1; // apply the negation (2nd bit) on the factorial (1st bit)
C isn't going to win anyway, so let's trade some golf for some obfuscation: replace the last expression with something else, assuming 2-complement: -x == (~x+1)
and observe how the last two bits evolve
- ...00 -> ...11+1 -> ...00
- ...01 -> ...10+1 -> ...11
- ...10 -> ...01+1 -> ...10
- ...11 -> ...00+1 -> ...01
We see that the LSB is unchanged via c=-c
, and the 2nd bit becomes the xor of last two bits. So we can just pick this second bit with c>>=1,c&=1
or c&=2,c/=2;
Of course, the bit inversion ~x
is useless, just adding+1 has the same effect.
But there is a reason behind it:
what if we would replace the XOR flip/flop with negated op?
at each neg -...01 becomes ...11 et vice et versa
If we then subtract 1, we have either ...00 or ...10 at the end of the loop.
We are back to our original solution.
c=1;
while(*a++<34)c=-c;
c-=1;
c|=*a,c|=*--a;
c=-c;
c&=2,c/=2;
And let's see what happens if we add the factorial bit instead of ORing:
...00 becomes 00 or 01 or 10 in case of '0'
, '0!'||'1'
, '1!'
.
...10 becomes 10 or 11 or 00.
So using +
gives the same parity than |
on last two bits, even if we accidentally add a bit twice du to '1!'
case.
Now we just have to roll the final c-=c inside the loop, and replace the + by - for getting our obfuscated solution.
Ah and also use recursion to take a functional style disguise, but of course with non reentrant, ugly static variable assignment side effect, else there would be no "advantage" to code in C ;)
18But 0!=1!, so what's the point of handling multiple factorials? – boboquack – 2017-02-06T09:22:54.217
31@boboquack Because that's the challenge. – Calvin's Hobbies – 2017-02-06T09:24:17.793
1What type can the output have? (String, char, integer, boolean, float...) – Zgarb – 2017-02-06T12:47:36.920
11<?='1'; ... correct 75% of the time in php. – aslum – 2017-02-06T17:17:03.383
1@Zgarb The type doesn't matter as long as it would be represented as plain 0 or 1 (not 0.0, not True, etc.) – Calvin's Hobbies – 2017-02-06T19:57:50.000
10I may be wrong here but can't any number with any factorials after it simply be removed and replaced with 1? Like 0!!!! = 1!! = 0!!!!!!!! = 1!!! = 1! = 0! = 1 etc – Albert Renshaw – 2017-02-06T22:33:17.057
2@AlbertRenshaw That is correct. – Calvin's Hobbies – 2017-02-06T22:54:58.433
1@AlbertRenshaw - my answer is just one (humble) example of how and why this works for this challenge. – ElPedro – 2017-02-06T23:09:51.033
Do we have to handle invalid inputs in any way? – theonlygusti – 2017-02-07T12:10:24.650
@theonlygusti since he didn't say anything about invalid inputs, you don't have to worry about them (that's the standart rules of codegolf). – Dada – 2017-02-07T15:04:36.787
You need to talk to Alan Turing about the title. – Craig Hicks – 2017-02-09T19:21:32.617
You could take this one step further and require !! to mean the double factorial etc.
– Tobias Kienzler – 2017-02-10T07:06:29.793I finally get it. – djechlin – 2017-02-12T02:15:26.183
@TobiasKienzler That wouldn't change the results. – Martin Ender – 2017-02-14T12:11:49.277
@MartinEnder It sure would:
5!! = 5•3•1 = 15
while(5!)! = 120! > 6.6e198
. – Tobias Kienzler – 2017-02-14T13:17:10.663@TobiasKienzler You don't ever get a value other than
0
or1
as an argument to the (multi-)factorial though. – Martin Ender – 2017-02-14T13:25:46.687@MartinEnder Ah yes, of course. The difference only matters when any integer is permitted. And in contrast to the recursive factorial the double, triple etc. factorial would not overflow so quickly :) – Tobias Kienzler – 2017-02-14T13:51:46.647
Can we output
True
for1
andFalse
for0
? – caird coinheringaahing – 2018-01-14T18:05:47.163