Glider
"In het verleden behaalde resultaten bieden geen garanties voor de toekomst"
About this blog

These are the ramblings of Matthijs Kooijman, concerning the software he hacks on, hobbies he has and occasionally his personal life.

Most content on this site is licensed under the WTFPL, version 2 (details).

Questions? Praise? Blame? Feel free to contact me.

My old blog (pre-2006) is also still available.

See also my Mastodon page.

Sun Mon Tue Wed Thu Fri Sat
       
23
 
Powered by Blosxom &Perl onion
(With plugins: config, extensionless, hide, tagging, Markdown, macros, breadcrumbs, calendar, directorybrowse, feedback, flavourdir, include, interpolate_fancy, listplugins, menu, pagetype, preview, seemore, storynum, storytitle, writeback_recent, moreentries)
Valid XHTML 1.0 Strict & CSS
Happy Numbers in 1 line of C

This afternoon on IRC people were discussing the assignments of the NIO, a programming contest for high school students I've participated in a few times. One particularly nice one was the "happy" assignment.

In short, the assignment says there are happy numbers and non happy numbers. To see if a number is happy, you take the square of every digit and add these squares together. You do this squaring and summing until you get either the number "1" of the number "4". If you get "1", the number is happy, if you get "4", the number is not. This is a fairly simple assignment to write a program for, but the program could not have more than 1000 characters, which makes it kinda interesting.

As soon as somebody posed that he could to it in four hundred something characters, without leaving out stuff (like whitespace and indentation), people started trying too. Before long, a couple of people were trying to make their programs as short as possible. Later we merged our tries to get even shorter versions. The end result was a very short solution for this problem (chopped into two lines for readability):

m[666],o,x;h(i){for(x=0;i;i/=10)x+=i%10*(i%10);m[x]=m[x]?:h(x);}
main(i){for(m[m[4]=scanf("%d",&i)]=2;i;o+=h(i--)-1);printf("%d\n",o);}

This is exactly 134 characters of C code (which can be reduced to 133 by replacing the \n in the last printf by an actual newline, but newer gcc versions don't eat that). As you can see, we have not left any programming principle or style guideline standing. Whitespace is completely unnecessary (so none is present) and 26 variable names are more than plenty.

For readability, I'll be kind and give you some whitespace, so it becomes at least somewhat readable:

m[666],o,x;

h(i){
    for(x=0;i;i/=10)x+=i%10*(i%10);
    m[x]=m[x]?:h(x);
}

main(i){
    for(m[m[4]=scanf("%d",&i)]=2;i;o+=h(i--)-1);
    printf("%d\n",o);
}

A number of the more ugly hacks are no longer present here, because rewriting the control flow turned out to save more characters that fiddling around with syntax hacks. Still, there are a few things to note. Firstly, this code generates a bunch of warnings, since we left out all type definitions, expecting gcc to just fill in "int" everywhere. Also #including stdio.h is not really necessary, so we didn't.

A particularly nasty hack here is leaving out the return statement in the function h(). The reason this works, is that the value we want to return is coincidentally left in the EAX CPU register where return values are normally stored. Somebody discovered this accidentally be just removing the previous hack that used a global variable to pass the return value back (since "return" is so many characters ;-).

As a last note, if you're trying to compile this, you might want to play around with -O options to GCC. I've been having reports that this does not work with any -O on some versions of GCC and apparently it works only with -O1 or -O2 under cygwin.

If anyone has more suggestions on how to shave off a few more characters from this code, lemme know. I don't think any more can be left out, but I thought that about 20 characters before and other people about 100 characters earlier. So, surprise me :-)

 
1 comment -:- permalink -:- 02:41
Copyright by Matthijs Kooijman - most content WTFPL