Random silly puzzle (code)
by at 8:57 PM
So, the friend who hosts this site for me popped online and gave me a little code snippet:
rc(char*ni){char*n=ni;while(n&&*n){if(*n>='A'&&*n<='Z'){*n+=32;if(*(n+1)){*(n+1
)-=32;return;}else{*ni-=32;}}n++;}}main(int
c,char**v){if(c<2)exit();while(1){printf("%s ",v[1]);rc(v[1]);}}
Basically, compile it and run it with something like "./a.out Foobar" and it'll output the string repeatedly, rotating the capitalization to the right. (With the caveat that it doesn't work with more than one capital letter.)But it seemed rather bloated to me, so I rewrote it...
main(int c,char**v){char*m,q;v++;while(c-1)for(m=*v; q=*m;)(q==(q&95))?(*m++)^=32,*(*m?m:*v)^=32:m++,puts(*v);}
which was nice and all, but it still seemed a bit big, and now also couldn't handle spaces.Then I had another insight which led to shrinking it further:
main(int c,char**v){char*m,q;v++;while(c-1)for(m=*v; q=*m;*m++|=32,*(*m?m:*v)^=~q&32)puts(*v);}
so now it was at a size I could be proud of. But it still couldn't handle more than one capital letter, which led me to think about a totally different solution:
main(int
c,char**v){char*m,q;v++;while(c-1)for(puts(m=*v),q=0;q^=~*m&32,*m; *m++^=q,*(*m?m:*v)^=q);}
which was great, since now it could handle strings with more than one capital letter, but it still died with spaces. Unfortunately, fixing that required adding a bunch of characters, making it bloated again:
main(int c,char**v){char*m,q;v++;while(c-1)for(puts(m=*v),q=0;q^=~*m&32,*m;*m^=(*m^q?q:0),m++,*(*m?m: *v)^=((*m^q)?q:0));}
(there's an easy way to trim two characters off but it makes the behavior technically undefined, even if it works in gcc).Can anyone shorten this further? (For bonus points, make it handle characters other than [A-Za-z ] correctly too...)
Comments
Handling spaces too:
main(int c,char**v)is the same length asmain(c,v)char**v,c;)Hm, and I hadn't considered that "v++;" didn't actually cancel out just using v[1] everywhere. It's too bad the ++ can't just be folded into one of the loops.
However, your algorithm doesn't work right, since you're not wrapping around. The capitalization needs to rotate, like "a.out Foobar" should produce
and I don't even see any attempt at handling that in the first one (which isn't that hard to decipher). Your codes produce:
So, your code might be compact, but it's incorrect. I give you an E for effort.
I just realized there's a way of saving two more characters without getting undeinfed behavior, and there were a lot of unnecessary parentheses. So, now it's down to:
*m;*m^=(*m^q?q:0),*(*++m?m:*v)^=*m^q?q:0);}
I tried writing a single for loop and got two chars on top of that:
main(t,v,p)char**v,*p;{for(t=*(p=*++v);p-*v||puts(p);*++p||(t=*--p,p=*v))*p-32?t^=*p,*p^=t&32,t^=*p:0;}
t=*p,puts(p):0;}
It doesn't like the first character to be a space, otherwise it should work, but will fail in an obvious way as soon as I hit "Post"
It can probably be shortened a bunch.