Posted by Weasel on 1999-06-11
Matthew Pratt wrote:
>
> >
> main(i){putchar(354603184>>(i-1)*5&31|!!(i<6)<<6)&&main(++i);}
>
> Hey I saw a guy on slashdot with something similar in
> his sig (his spelt DAVE), is that where you got it
> from? How do you work out the magic number?
Ok, you got me. I simply stole it. *grin* At least I understood it :)
It is not that hard to get the magic number. I'll expain:
1 main(i)
2 {
3 putchar(354603184>>(i-1)*5&31|!!(i<6)<<6)
4 &&
5 main(++i);
6 }
Ok, lets start at line one; the i actually is the param_count variable.
So if someone would start this program with <prg> <parameter1>
<parameter2> i would be 2. but since noone does it start with parameters
i always equals zero.
line 2 is quiet simply. 'nuff said.
line 4 (the and operator) simply asks to also evaluate line 5. a simply
semicolon (;) would have done too but it would not have looked that
nice.
line 5 now calls main() recursivly with an i that is one greater.
line 6 see line 2
ok, now the killer line: line 3
354603184>> (i-1)*5 & 31 | ! !(i<6) << 6
( * ) (! )
( >> ) (! )
( & ) ( << )
( | )
the parenthensis show the precedence of the operators.
putchar simply puts out one character (really!) but the question is
which one. let's look at the first part:
354603184>>(i-1)*5&31
we have a magic numer which we shift to the right (i-1)*5 bits, i.e. we
divide through 32^(i-1) afterwards we do a logical AND with
11111b=1fh=31 so that this value is in the range of 0 to 31 both
inclusively.
the second part:
!!(i<6)<<6
forget about those 2 negations. they are useless and just there so that
the program fits excatly into the line:)
so we have:
(i<6)<<6
where (i<6) is a value either 0 or 1 and <<6 shifts this 6 bits to the
left resulting in either 0 or 64.
if i is <6 we get 64 and if i>=6 we get 0.
then we do a bitwise OR on both of these.
what we now have is:
a number between 0 and 31 (determined by the magic number and i) and 0
or 64 depending on (i<6)
iow if i < 6 we get values above 64 ('A' == 65, ..) and when i finally
gets 6 we have a value in the range from 0 to 31 in my case 10 which is
a newline.
so the number to get
ABCDE
is:
1+
32*(2+
32*(3+
32*(4+
32*(5+
32*10
)
)
)
)
where 1 to 5 return the A to E and 10 is for the newline.
any questions?
--
Weasel http://www.cosy.sbg.ac.at/~ppalfrad/
main(i){putchar(354603184>>(i-1)*5&31|!!(i<6)<<6)&&main(++i);}
We have full klingon console support just in case.
-- Alan Cox on linux-kernel
Previous post | Next post | Timeline | Home