Login [Register]
Don't have an account? Register now to chat, post, use our tools, and much more.
Now that I have gained semi-competence in JavaScript, I've started trying to get my code down to a certain size, occasionally as small as I can get it. (A.K.A. "code-golfing")

I was inspired to do this primarily by this, which is simply beautiful (in my opinion, of course), and some of the below projects reflect that.

This is a growing list, ordered by creation date, and I'll probably end up editing this post with new scripts as I make them.
1) ASCII art π character, in 360 bytes of code:

Code:
document.body.innerHTML=atob("/AAAAAPwAAAAA+AAAAAD4eD/h//H4P8H/9/g/wf/3+D/D///4f8P///h/w///+H/D///wf4P///B/g///8P+D///w/4P//+D/g///wP+D///B/4P8/4D/gfz/Af/AAP4D/8AB/gP/4AP+B//wB8=").split('').map(x=>x.charCodeAt(0).toString(2).padStart(8).split('').map(x=>"# ".charAt(x)).join('')).join('').match(/.{40}/g).map(x=>'<pre style="margin: 0">'+x+'</pre>').join('');

You can find an explanation for this one here. It's really simple, and I created it just as an experiment to see what I could do.
2) Rotating 3D Cube in 500 bytes of JS:

Code:
(a=>{var r=-1,e=[r,r,r,r,1,1,1,1],m=[r,r,1,1,r,r,1,1],n=[r,1,r,1,r,1,r,1],t=Math.sin,o=Math.cos,p=Math.PI/36,i=a=>16+(a<0?Math.floor(8*a):Math.ceil(8*a)),l=e.map((a,r)=>.5*a+m[r]*t(24*p));m=m.map((a,r)=>e[r]*t(24*p)-.5*a),e=l,setInterval(a=>{var r=Array.from(Array(32),a=>new Array(32).fill("  "));l=n.map((a,r)=>a*o(p)-e[r]*t(p)),e=e.map((a,r)=>a*o(p)+n[r]*t(p)),n=l,e.map((a,e)=>r[i(m[e])][i(a)]="#"),document.body.innerHTML=r.map(a=>'<pre style="margin:0;">'+a.join("")+"</pre>").join("")},50)})()

I haven't taken the time to produce an explanation for this one, but all it is doing are some point rotations, which (let's be honest) aren't really that interesting. If you just look through the code, you can probably guess what it is doing, and you'll most likely be right, if you know your trig. I'm not really satisfied with it, because I can easily shave off 20+ bytes by storing Array and Math to variables. I also don't need all of the fancy calculations determining when to use Math.floor or Math.ceil. It doesn't provide a noticeable difference to the output and it's just hoarding bytes. Using this suddenly available bytage, I should force the text height:width ratio something I can easily deal with, instead of assuming it is 2.
3) Rainbow Flashy Text in almost 256 bytes of JS

Code:
eval(s=`var q=0,a=x=>{q++;document.body.innerHTML=
s.split('\\n').map((x,j)=>x.split('').map((x,i,a)=>
'<kbd style="color: hsl('+(360*(i+q+j))/50+',100'+
'%,50%)">'+x+'</kbd>').join('')).join('<br />')}//
setInterval(a,9);s='eval(s=\`'+s+'\`)'//_iPhoenix_`)

This is by far my favorite one (so far). It uses several of the tricks found in the aemkei world thing, linked above. It displays (almost, I can't do character escaping without some serious additions) the source code of the program and does a fun rainbow pattern. I can't really describe what it does in words, just check it out Razz. As with the 3D Cube, this script could also be optimized. But in order for my rainbow effect to look good, all of the rows should be the same length, and any more optimizations would mess with it.
4) Animated CW mascot (), in almost 1800 bytes

Code:
var f=0,a=["@L@L@L@L@L@L@L@LUQsL@K-B@L@L@L@L@LEgsL@ALAssAAs-sL@L@L@LC1ELCwoEKQsLDigELCgB@L@L@LCxILCwAsL-LAAs@sAAsL@L@LCwtRCwoJWgMhHgAABCkLDigAAQsL@L@S@AACFNTQAWIQAs@AFgAL@L@LUQsKAAMlTUYHTUkeAQ4oBkEyAQsL@LEgsANyEATU0ATU0hACwAIRZCAAsL@LC1EKAyEgFAACF-CVoDISAWGTIB@LCxIAABYAFiEhIRY-AhIRYWFjcA@LCwtQAQo-MgFAMhISEhIBYWFhYZMgEL@SACxjAAs-AhFhYWFhYWFhYWNwAL@LUAQsKAQpE1oDIBYWFhYWFhYWGTIB@LEgAsLAAsCywAIRYWFhYWFhYWFiEA@LC1AEMVoEKQ4oAyEhISAWFhYWFhceAQsLCxIACwAAYwtjACEhACEAISEWFhZCNwALCwtQBjwBCgkKAyEeAhYXHgMhIBYWGjwB@SAEI-BCACEAQkIWISEhISEhIQA3AAsLUAY8BTIGPAAFOD4WFyEeAyEhIBkyAAELEgAANyEAQgAAQhYWISEAFhYhACFCAAsLC1AABTUeAAIZNBYXIBQAAhYUAAMgGTIBCxIAFiEACwAANyEh-ACw--ISEWAAtQ-B@K-AAQsL@L@LCg-Qs=","@L@-AL@L@L@L@L@LUQsLCwoELCwoAQoAAQsL@L@L@LEgsLCwAsLAsLLAAsLAAL@L@L@LC1ELCgQsKAABCgELCw4oAQsL@L@LCxILCwALACEh-ALAsLL-@L@LCwtRCwoAAyVNRgIXHgQpDigFMgEL@L@S@AACFNTQBNTSEALCwANzcA@L@LUQoFNR4HTUYHTUkeCVoDIBo8AQsL@LEgsAISEW-WAE0AYwAhIRYWNwAL@LC1-hQCFyEhIBQ-MhIBYWGTIB@LCxIAQg-CEWACEhISEhFhYWFjcA@LCwtQBCkKBjw-MgFhYWFhYWFhYZMgEL@SA@ACwLCwAhFhYWFhYWFhYWNwAL@LUAQsKAQpDigDIBYWFhYWFhYWFx4B@LEgAsYwAsCywAIRYWFhYWFhYWFiEA@LC1ABCgAJWxNaAyEhISAWFhYWFhceAQsLCxIAQg-AsAISEhACEhISEWFhZCNwALCwtQBjwBCgY8AyEeAyAWFAMhIBYWGjwAAQsSAEI-BCACEhISEWQjcAISEhIRY3-LUQoAAhQGPAMhISEgFhpBMgMhHgMjMgELEgsAADchABYWFgAhIRYWQgAhIQAhFjcAC1EKBTQXIBQ-IUAhcgFhkyAhYUAyEgFAgLABYh-L@-AAISE3-ACw-AtRCg-QsL@L@LCg-AEL@L@="],w=f=>(atob(a[f].replace(/-/g,'AAA').replace(/@/g,'Cws')).split('').map(x=>x.charCodeAt(0).toString(10).padStart(2,0)).join('')+'1').split(.map(x=>"<tt>"+x.split('').map(x=>"M +o'/:y\n.".charAt(x)).join('').replace(/ /g,'&nbsp;')+"</tt>").join('[br /]');window.onload=x=>{d=document.body,e="innerHTML";setInterval(x=>{d[e]='';d[e]=w(f=+(f==0))},300)}

A friendly example of a CodeWalrus, but it's actually a code walrus. I might be able to shave off a few hundred bytes by only storing every other character, because each character is duplicated twice.
5) Rotating 4d hypercube, in under 640 bytes:

Code:
(t=>{a=document,d=Math,c=d.sin,o=d.cos,i=d.floor,r=0,l=a.body.appendChild(a.createElement("canvas")),s=l.getContext("2d");l.width=l.height=n=200,setInterval(t=>(e=>{r+=.01,s.clearRect(0,0,n,n);t=e.map(e=>[i(100+(h=45+15*e[2])*e[0]),i(100-h*e[1])]);"0102040813151923262a373b45464c575d676e7f898a8c9b9dabaebfcdcedfef".match(/../g).map(e=>{f=e.split("").map(e=>parseInt(e,16)),s.beginPath(),s.moveTo(...t[f[0]]),s.lineTo(...t[f[1]]),s.closePath(),s.stroke()})})(" ".repeat(16).split("").map((t,n)=>((t,n,d,i)=>[t,(a=o(r))*n-(e=c(r))*i,a*d-e*(p=e*n+a*i),e*d+a*p])(...n.toString(2).padStart(4,0).split("").map(e=>2*e-1)))),9)})()


There really isn't too much to say here, it's just a rotating 4d tesseract Smile I'm getting better at golfing, this one used various techniques that I didn't even know about earlier.

If you have any suggestions for relevant things you want me to try (be reasonable), you can post them below, and I might try to do it!

If I didn't provide an explanation, you are welcomed (even encouraged) to provide one of your own! If it is concise and accurate, I'll add it to the respective GitHub repo and link to it here, if you want.
You should try to make a mini-game such as Breakout. If you just want it to be an animation, some sort of illustration of some place? I'd also make the 3D cube a little more 3D and define the lines, but I don't know if that's possible using the techniques you're using. (Same with the mini-game and stuff) I love the rainbow one, and it looks just like the text on The Button when you're in control of it. I'm wondering though. Do the codes for the "Click Me" rainbow text and the one shown above have anything in common? Do they work the same way?

I'd like the "World" globe thing better if there wasn't the stuff on the side, but I guess it's part of the art of it. (EDIT: Actually, I'm kind of starting to like it now...)

If making a cube is easy, I'd try making 3D shapes with more vertices like tetrahedrons, and stuff like that. Make a horse prance! Make a bullet go “pieu!” Make a rocket go WHOOOOOOSH! There are lots of ideas! ***jcgter runs
jcgter777 wrote:
You should try to make a mini-game such as Breakout. If you just want it to be an animation, some sort of illustration of some place? I'd also make the 3D cube a little more 3D and define the lines, but I don't know if that's possible using the techniques you're using. (Same with the mini-game and stuff) I love the rainbow one, and it looks just like the text on The Button when you're in control of it. I'm wondering though. Do the codes for the "Click Me" rainbow text and the one shown above have anything in common? Do they work the same way?

I'd like the "World" globe thing better if there wasn't the stuff on the side, but I guess it's part of the art of it.

If making a cube is easy, I'd try making 3D shapes with more vertices like tetrahedrons, and stuff like that. Make a horse prance! Make a bullet go “pieu!” Make a rocket go WHOOOOOOSH! There are lots of ideas! ***jcgter runs


1) Yeah. I was thinking of games that would be relatively easy to implement, and breakout is high on the list.
2) That's a lot of code, surprisingly. If JavaScript were certain languages, we'd just have a built-in for it.
3) Yep, you are absolutely correct. Both scripts split the text into characters and use the CSS hsl(hue,saturation,lightness) command to get the actual rainbow effect. You should look up HSL (not specific to CSS) if you aren't familiar with it already Smile
4) For me, the best part of the globe thing is the fact that it displays a modified version of the source code. I guess we all have different opinions, though Smile
5) Believe it or not, a tetrahedron is actually easier to add because it has less vertices. I suppose I could do a rocket animation, that could actually be quite cool!
**Referring to the rainbow flashy text
If you really wanted to golf hard, and didn't care to get a nice power of 2 as the number of bytes, you could take off the comments (obviously) and also, you don't need to self-close your tags... you should also be able to change the '\\' into '/', but it seems to give a different result on the page. You don't need to escape the '<' character in a string...
With jQuery, you could shrink it some more, probably to about 200 bytes, but depending on what rules you follow for golfing, that might not be allowed.
Looks to me like someone just wanted the code to be exactly 256 bytes Razz
mr womp womp wrote:
**Referring to the rainbow flashy text
If you really wanted to golf hard, and didn't care to get a nice power of 2 as the number of bytes, you could take off the comments (obviously) and also, you don't need to self-close your tags... you should also be able to change the '\\' into '/', but it seems to give a different result on the page. You don't need to escape the '<' character in a string...
With jQuery, you could shrink it some more, probably to about 200 bytes, but depending on what rules you follow for golfing, that might not be allowed.
Looks to me like someone just wanted the code to be exactly 256 bytes Razz


I was more concerned with getting the lines to be even, and less with the actual number of bytes. I'm just casually golfing so I'm setting my own rules. I'm not allowing external CSS or reading from other webpages so I'm not going to do jQuery. I also never use jQuery in my actual JS (You can do everything jQuery can do in vanilla JS), so it's somewhat foreign territory.

With the pi one, I could easily collapse some bytes down over there, but the fact that it is pi (a circle constant) in 360 (another circle constant, but this one is not fundamentally related to the circle as much as pi) bytes is pretty cool.

As for the cube, I could and will easily shave off a bunch of bytes. I set 500 bytes as a goal before I even started writing the code, so once I reached it I stopped optimizing.
_iPhoenix_ wrote:
As for the cube, I could and will easily shave off a bunch of bytes. I set 500 bytes as a goal before I even started writing the code, so once I reached it I stopped optimizing.

You are pretty close to a perfect cube (8³=512) Evil or Very Mad
For my 1337th post, I decided to draw my avatar in 1337 bytes. I tried to do this, but I guess I did too good, because I did it in only (approx) 900 bytes. Whoops. It was fun, at the very least, and kept me occupied for a good hour.


Code:
var z="0y110q1104210p112104220o21310421410n115131043161410l11614z041161415z0i1151620631614171310g21716211061163714z0c31517163110611216351815131082172642z061131216441812106418165213108113121658z0421712164213z091122645161012131017165213z0a113221645131918z516421320c113221637z814z416321320f113163813z0121716241310i112142819z21a171623z0l3171a19181915z0p31a181918z0r41a2210s31a19z0s21a2110s7191a1610r31a18192110q8194710p112183712z0p21712241310q214z2141310q112z312z0r3z3z0e".replace(/z/g,"111"),p="000_|300_|700a14_|500_|a00_|a0141f_|912_|b01729_|ce1d34_|dc2039_|d3213c_".split("|"),e=parseInt,t=document,r=0;z.match(/../g).map(a=>{var z=a.split("");return p[e(z[0],36)].repeat(e(z[1],36))}).join("").split("_").map((a,z)=>{var p=t.createElement("p"),e=p.style;e.position="fixed",e.top=r+"px",e.left=z%32*16+"px",e.backgroundColor="#"+a,e.height=e.width="16px",t.body.appendChild(p),(z+1)%32||(r+=16)})


Explanation:

This looks really intimidating and weird, so let's break it down. First, let's add indentation and do some simple substitutions.


Code:
var z = "0y110q1104210p112104220o21310421410n115131043161410l116141110411614151110i1151620631614171310g217162110611637141110c3151716311061121635181513108217264211106113121644181210641816521310811312165811104217121642131110911226451610121310171652131110a113221645131918111516421320c113221637111814111416321320f1131638131110121716241310i11214281911121a1716231110l3171a191819151110p31a1819181110r41a2210s31a191110s21a2110s7191a1610r31a18192110q8194710p1121837121110p21712241310q2141112141310q1121113121110r311131110e",
  p = ["000_","300_","700a14_","500_","a00_","a0141f_","912_","b01729_","ce1d34_","dc2039_","d3213c_"],
  r = 0;
z.match(/../g).map(a => {
  var z = a.split("");
  return p[parseInt(z[0], 36)].repeat(parseInt(z[1], 36))
}).join("").split("_").map((a, z) => {
  var p = document.createElement("p"),
    e = p.style;
  e.position = "fixed",
  e.top = r + "px",
  e.left = z % 32 * 16 + "px",
  e.backgroundColor = "#" + a,
  e.height = e.width = "16px",
  document.body.appendChild(p),
  (z + 1) % 32 || (r += 16)
});


Let's go through this in sections.

Code:
 var z = "0y110q1104210p112104220o21310421410n115131043161410l116141110411614151110i1151620631614171310g217162110611637141110c3151716311061121635181513108217264211106113121644181210641816521310811312165811104217121642131110911226451610121310171652131110a113221645131918111516421320c113221637111814111416321320f1131638131110121716241310i11214281911121a1716231110l3171a191819151110p31a1819181110r41a2210s31a191110s21a2110s7191a1610r31a18192110q8194710p1121837121110p21712241310q2141112141310q1121113121110r311131110e",
  p = ["000_","300_","700a14_","500_","a00_","a0141f_","912_","b01729_","ce1d34_","dc2039_","d3213c_"]


This is where all of our image data is stored. I am using a color palette, stored in p, to save some bytes. The underscores after each hex color value are important, we will use them later. The variable z contains sets of two characters. The first character is the index in p that the color we want is at, and the second is the number of times that color appears in a row. Both of these are converted into base 36 (0-9, a-z) so that they only take up one character each. We also create a variable, r, that we will use as the vertical offset when drawing.


Code:
z.match(/../g).map(a => {
  var z = a.split("");
  return p[parseInt(z[0], 36)].repeat(parseInt(z[1], 36))
})


This reverses the compression described above. z.match(/../g) splits the text into sets of two characters, the .map performs an action on all of these pairs of characters. var z = a.split(""); splits these two-character pieces into one-character parts, p[parseInt(z[0], 36)] grabs the appropriate color from the palette and .repeat(parseInt(z[1], 36)) repeats it the appropriate number of times.

.join("").split("_") joins these chunks together and splits this combined text into an array of individual colors, such that one element corresponds to one pixel. Now, all that's left is to draw them!


Code:
.map((a, z) => {
  var p = document.createElement("p"),
    e = p.style;
  e.position = "fixed",
  e.top = r + "px",
  e.left = z % 32 * 16 + "px",
  e.backgroundColor = "#" + a,
  e.height = e.width = "16px",
  document.body.appendChild(p),
  (z + 1) % 32 || (r += 16)
});


var p = document.createElement("p") creates an element. One element = 1 pixel. As an optimization, we store p.style into a variable, e, because we will be using it multiple times. e.position = "fixed", e.top = r + "px", and e.left = z % 32 * 16 + "px" all set the element's position on screen. We then set the color of each pixel with e.backgroundColor = "#" + a. Because setting a variable to a value returns the value, you can chain variable assignments like I did in e.height = e.width = "16px". After this, we add the element the the screen. (z + 1) % 32 || (r += 16) is a little weird, but because of how JS evaluates expressions, the vertical offset, r, is only incremented by 16 if the next pixel is on a new line.

I hope this made sense at least a little bit. Enjoy!
I've decided to formalize my golfing rules:


    0. It has to be cool.
    1. No libraries/reading from outside sources.
    2. It has to work (at the very least) in Chrome.
    3. Aesthetics are more important than code size.
    4. Golf it as small as possible, unless it conflicts with rule 3.
    5. Use common sense. If it feels like cheating, it is.
    6. JS hacks are explicitly allowed.
    7. This list can change at any time Razz
I golfed a loading wheel into 424 bytes, you can watch a timelapse of me doing it here:

https://www.youtube.com/watch?v=ltFe87xs7-4


Code:
((e,t)=>{var a=e.createElement("canvas"),o=a.getContext("2d"),r=0,h=t.PI/6,n=t.sin,i=t.cos,l=t.floor;e.body.appendChild(a),a.width=a.height=_=300,o.translate(150,150),setInterval(e=>{r+=21,o.clearRect(0,0,_,_);for(var d=0;d<12;d++){var s=d*h,c=(r+21*d)%256;o.strokeStyle="rgb("+c+","+c+","+c+")",o.beginPath(),o.moveTo(l(50*n(s)),l(50*i(s))),o.lineTo(l(100*n(s)),l(100*i(s))),o.closePath(),o.stroke()}},100)})(document,Math)
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are GMT - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement