Skip to content

Instantly share code, notes, and snippets.

@patcullen
Last active August 29, 2015 13:57
Show Gist options
  • Save patcullen/9626197 to your computer and use it in GitHub Desktop.
Save patcullen/9626197 to your computer and use it in GitHub Desktop.
A boilerplate for starting a JS1k entry. Provides a compression function that allows hand-picking the tokens for replacement while also offering suggested tokens.
<!doctype html><html><head><title>JS1k Entry</title><meta charset="utf-8" /><style>html, body { margin: 0; padding: 0; border: 0; }#c { display: block; } /* kill scrollbars from hell */</style></head><body><canvas id="c"></canvas><script>
var a = document.getElementsByTagName('canvas')[0];
var b = document.body;
var d = function(e){ return function(){ e.parentNode.removeChild(e); }; }(a);
// unprefix some popular vendor prefixed things (but stick to their original name)
var AudioContext = window.AudioContext || window.webkitAudioContext;
var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || function(f){ setTimeout(f, 1000/30); };
// fix bug in safari: http://qfox.nl/weblog/218
document.body.clientWidth;
// auto resize (original) canvas. call `onresize(w,h) to limit the size of the canvas
(window.onorientationchange = window.onresize = function(a){ var mw = Infinity; var mh = Infinity; var min = Math.min; return function(w,h){ if (arguments.length === 2) {mw = w;mh = h;} a.style.width = (a.width = min(mw, innerWidth)) + 'px'; a.style.height = (a.height = min(mh, innerHeight)) + 'px'; }; }(a))();
var c = a.getContext('2d');
</script>
<script>
// ********************** Code everything to be compressed inside of this js1k() function ************************
js1k = function(){
M=function(){
requestAnimationFrame(M);
x=Math.random()*a.width;
y=Math.random()*a.height;
s=Math.random()*60+40;
t=Math.random()*10+10;
g=c.createRadialGradient(x,y,s,x,y,s+t);
g.addColorStop(.1,'rgba('+~~(Math.random()*255)+','+~~(Math.random()*255)+','+~~(Math.random()*255)+',1)');
g.addColorStop(1,'rgba(255,255,255,0)');
c.fillStyle=g;
c.fillRect(x-s*2,y-s*2,s*4,s*4);
};
M();
};
var code='';
// --------------------------------------------- Compression of the above function code -----------------------------------------------
compress = function() {
console.log('Compressing... (manual)');
var raw = js1k.toString().substring(14);
code = raw.substring(0, raw.length-2).replace(/\/\*.+?\*\/|\/\/.*(?=[\n\r])/g, '').replace(/\t/g,'').replace(/\n/g,'');
// the tokens are the most repetitive portions of characters found in the code.
token = [
"255",
"a.height",
"a.width",
"tion",
";c.fill",
"Math.random()*",
";g.addColorStop(",
"1,'rgba(",
"'+~~(Math.random()*255)+',",
"x,y,s",
"-s*2,"
];
var lastLength = 0;
for (var i = 0; i < token.length; i++) {
var temp = String.fromCharCode(255-token.length+i+1);
console.log(i, temp, token[i]);
for (var j = i+1; j < token.length; j++)
while (token[j].indexOf(token[i]) > -1)
token[j] = token[j].replace(token[i], temp);
while (code.indexOf(token[i]) > -1) {
code = code.replace(token[i], temp);
}
if (code.length==lastLength) {
console.log('Token made no difference', ' v:'+token[i]);
}
lastLength = code.length;
}
var these = [/;/g,/\,/g,/\./g,/\[/g,/\{/g]; // some interesting numbers to watch. so many repetitive/wasted bytes
for (var i = 0; i < these.length; i++)
console.log('count:', these[i], code.match(these[i])?code.match(these[i]).length:'---');
function decompressionCode(flag) {
var value = '';
for (var i = 0; i < token.length; i++)
value += token[i] + '|';
return 'T="'+code+'";\nV="'+value+(!flag?'".split("|");for(A='+token.length+';A--;)for(Q=99;Q--;)T=T.replace(String.fromCharCode('+(256-token.length)+'+A),V[A]);eval(T);':'');
}
function suggestion() {
var value = '';
for (var i = 0; i < token.length; i++)
value += token[i] + '|';
var temp = longestRepeatingSubstring(decompressionCode(true));
eval('T="'+temp+'";\nV="'+value+'".split("|");for(A='+token.length+';A--;)for(Q=99;Q--;)T=T.replace(String.fromCharCode('+(256-token.length)+'+A),V[A]);console.log("["+T+"]");');
}
function notOneLineOfCode() {
var display = '';
for (var i = 0; i < code.length; i+=100)
display += code.substring(i, i+100) + '\n';
return display;
}
// compressed result
console.log('Next Longest Repeated Substring: '); suggestion();
console.log('===========================================================: ');
var decomp = decompressionCode();
console.log('Raw length: ', raw.length, ' Packed Length: ', decomp.length, '(Previous: '+localStorage['last_decomp_size']+')', ' Compression: ', ((decomp.length)/raw.length));
console.log('Packed source: ', '\n\n'+decomp);
eval(decompressionCode());
localStorage['last_decomp_size'] = decomp.length;
}
compress();
// function to find the longest repeating substring - thanks to peoples of interwebs- http://stackoverflow.com/questions/3898083/find-longest-repeating-substring-in-javascript-using-regular-expressions
function longestRepeatingSubstring(input) {
var reg = /(?=((.+)(?:.*?\2)+))/g;
var sub = ""; //somewhere to stick temp results
var maxstr = ""; // our maximum length repeated string
reg.lastIndex = 0; // because reg previously existed, we may need to reset this
sub = reg.exec(input); // find the first repeated string
while (!(sub == null)){
if ((!(sub == null)) && (sub[2].length > maxstr.length))
maxstr = sub[2];
sub = reg.exec(input);
reg.lastIndex++; // start searching from the next position
}
return maxstr;
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment