Recently I stumbled upon a challenge on challengepost.com – “20 lines of JavaScript”. The goal was to write a 20 line JS code that does something that can make the challenge judges vote for you. I thought the best idea would be to treat this challenge like a good ol’ demoscene compo. I’ve already had a good effect – the flower fractals. Unfortunately, after porting it to JavaScript it was 11 KBytes :( and 383 lines of code, not always shorter than the required 80 chars (or maybe even more, but I don’t remember where I put the first version). I used PIXI, great 2D javascript library because it uses several enhancements for JS canvas (it also supports WebGL, but WebGL isn’t really a vector-like drawing thing, the lines are aliased and poor quality, to obtain better quality I’d need to use textures and stuff, I thought it would be too complicated for 20 lines of code).
OK, so I’ve got 383 lines and 11 kilobytes. As we all know, 20 lines of 80 char code is 1600 bytes, so there’s way to go… I checked with google closure compiler, how I could squish that – after compressing, it was about 5 kilos. Still too much. After hours of merging functions, deleting smooth line bezier-based rendering, reusing some vars, it went down to about 3 kilos.
I started to think that its impossible to do, unless some miracle happens.
Then I stumbled upon this great method of utilising somehow buggy behaviour of browsers – treating PNG files like HTML, when compressed PNG data resembles HTML data. After changing the JS to one big eval(…) function and compressing it to PNG I went down to 1600 bytes. Well, exactly 1595. Changing some things inside eval and making the code larger allowed PNG to compress it enough. So there’s this curiosity – PNG JavaScript: 1600BYTES
This was of course no-go, because it wasn’t really javascript – it was png, and I it would be really really hard to intoduce line breaks inside zipped binary data. Also, it’s very ugly, you can see some errors appearing when running this code – some PNG IHDR data is displayed for a short period of time. I had to come up with something else. But how to squish the code better than the zip algorithm itself?
Then I had a moment of enlightning – it’s 20 lines of 80 characters challenge, not 1600 bytes challenge. How about UTF-16? I could write 2 bytes inside 1 UTF16 character.
It worked! Excited, I searched on google if anyone else did it – of course someone already came up with that idea ;/ And the idea was better because the decoder is like:
eval(unescape(escape('SOME STRING').replace(/uD./g,'')))
And mine was much longer and 2 lines:
function(s){A=[];for(i=0;i<s.length;i++){c=s.charCodeAt(i);A.push(c&255);
c>>8?A.push(c>>8):c;}return String.fromCharCode.apply(String,A)}("SOME STRING");
But my method used a bit different technique, so I could use normal letters and fit some ASCII art inside the code, not only some strange chinese letters.
OK, so after compiling with google closure, making big eval and changing to UTF-16, the code looks like this:
And can be seen on the challengepost’s winners’ ( ?° ?? ?°) gallery:
http://challengepost.com/software/20-lines-of-green
or here
or JSFiddle: http://jsfiddle.net/to267224/tbgad7uz/
ps. I will enhance this post later maybe, to provide some missing info on technical things and add some images, cause there’s too much unformatted text ; )