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 ;)