You may have heard of the "Hacker Logo", also called the "Hacker Emblem". It looks like this:

hacker logo

This is a pattern from a mathematical simulation called the Game of Life. The glider is the simplest Life pattern that moves, and the most instantly recognizable of all Life patterns.

The challenge

The challenge is pretty simple: Display the hacker logo. This is defined as:

  • A 3x3 grid with a border, a white background and gray gridlines.
  • Five black dots arranged in the GoL glider pattern.
  • Nothing else.

The rules

  • The black dots must fill 40%-80% of their individual grid-boxes.
  • You will display the emblem with graphical output but no ASCII art.
  • The output must be at least 30x30 pixels.
  • The output must only have the colors gray, black and white.
  • Each grid-box in the grid will be the same size. The grid will be a regular 3x3 square.
  • You may not pull the logo from the internet or your filesystem.
  • Your program will display the logo on an empty screen/window. If it terminates it must do so normally.
  • Note that "dots" does not necessarily mean "circles". A "dot" is a single geometric shape centered in the middle of the grid-box with one surface. For example, while a circle or square will qualify as a dot, two triangles or a checkerboard will not.

The winner

As this is , the shortest answer in each language wins!

Please include a screenshot of the output of your program in your answer.

  • 22
    \$\begingroup\$ I had no idea this was called the Hacker Logo. I have used it as my avatar on some sites, guess that makes me a Hacker. \$\endgroup\$ – Mark Thomas May 31 '17 at 19:18
  • 15
    \$\begingroup\$ @MarkThomas that or a GoL nerd xD \$\endgroup\$ – Stephen May 31 '17 at 19:21
  • 3
    \$\begingroup\$ @DavidConrad "clear the screen" means if you're using an IDE/interface that has builtin graphics you can't display it with existing text on the screen. Yes, you can display it in a window. \$\endgroup\$ – MD XF Jun 1 '17 at 2:40
  • 3
    \$\begingroup\$ Is multiple shades of gray (and related off colors) due to anti-aliasing allowed? \$\endgroup\$ – Ian Miller Jun 1 '17 at 8:01
  • 3
    \$\begingroup\$ Do we have to display the output or can we return it or save to a file? \$\endgroup\$ – TheLethalCoder Jun 1 '17 at 9:02

53 Answers 53


Mathematica, 62 bytes


enter image description here

Mathematica, 71 bytes


enter image description here

  • 2
    \$\begingroup\$ I think you can save bytes by using a pure function with Graphics@Disk[] as an argument. \$\endgroup\$ – CalculatorFeline May 31 '17 at 19:58
  • \$\begingroup\$ If you mean this Grid[{{,#,},{,,#},{#,#,#}},Frame->All,FrameStyle->Gray]&@Graphics@Disk[] it is 72 bytes \$\endgroup\$ – ZaMoC Jun 1 '17 at 1:02
  • 3
    \$\begingroup\$ A 69 byte variant on this: Rasterize@Grid[{{,●,},{,,●},{●,●,●}},Frame->All,FrameStyle->Gray]. The ● is a two byte unicode character. As it doesn't have to strictly be a circle perhaps some ASCII character could work to meet the 40%-80% requirement. \$\endgroup\$ – Ian Miller Jun 1 '17 at 7:57
  • \$\begingroup\$ actually I made it to 62 bytes meeting all requirements \$\endgroup\$ – ZaMoC Jun 2 '17 at 15:31
  • \$\begingroup\$ I think you need Rasterize or similar to meet the requirement of graphical output but no ASCII art as the symbols are still selectable in the grid as Unicode characters. \$\endgroup\$ – Ian Miller Jun 4 '17 at 10:10

CSS+HTML, 56+84=140 bytes 52+84=136 bytes

Saved 4 bytes by incorporating suggestions from the comments.

td{border:1px solid#888;line-height:.4;font-size:3em
<table cellspacing=0><tr><td><td>•<td><tr><td><td><td>•<tr><td>•<td>•<td>•

This uses the UTF-8 character which is 2 bytes long and takes advantage of the graciousness of HTML syntax.

  • 3
    \$\begingroup\$ Not bad; that's pretty clever using ! \$\endgroup\$ – MD XF May 31 '17 at 21:20
  • 3
    \$\begingroup\$ Very cool. I think you could save a byte with line-height:.4;, and another by omitting the closing } \$\endgroup\$ – ETHproductions May 31 '17 at 21:51
  • 5
    \$\begingroup\$ Doesn't using • count as ASCII art, which is against the challenge rules? \$\endgroup\$ – Hankrecords Jun 1 '17 at 8:55
  • 2
    \$\begingroup\$ @StephenS Sounds like a really futile distinction, plus I don't see the sense in banning ASCII art but allowing unicode art. As for the OP saying it was clever, my comment was in fact directed to the OP, I forgot to put in the @. \$\endgroup\$ – Hankrecords Jun 1 '17 at 13:43
  • 4
    \$\begingroup\$ The only Code Golf answer I ever understood, at least I do believe so. \$\endgroup\$ – Uwe Keim Jun 2 '17 at 7:22

GLSL (fragment shader), 278 235 256 bytes

precision highp float;void main(){vec2 a=gl_FragCoord.xy/20.-.2;ivec2 b=ivec2(a);a-=vec2(b)+.5;if(b.x>2||b.y>2)discard;gl_FragColor=a.x<-.5||a.y<-.5||a.x>.3||a.y>.3?vec4(.5,.5,.5,1.):length(a+.1)<.4&&(b.x+b.y-3)*b.y==0?vec4(0.,0.,0.,1.):vec4(1.,1.,1.,1.);}

enter image description here

See it in action: http://glslsandbox.com/e#40717.2

  • 1
    \$\begingroup\$ Hmm... does the border go all the way around the graphic? Also, are you sure the circles are only 80% of the grid-boxes? \$\endgroup\$ – MD XF Jun 1 '17 at 21:00
  • 14
    \$\begingroup\$ A circle that touches all four sides of its enclosing square fills a proportion π/4 of the square, or about 78.5%. \$\endgroup\$ – Greg Martin Jun 1 '17 at 22:25
  • 2
    \$\begingroup\$ I reduced your code's size to 222 bytes: precision highp float;void main(){vec2 a=gl_FragCoord.xy/20.-.2;ivec2 b=ivec2(a);a-=vec2(b)+.5;gl_FragColor=vec4(vec3(a.x<-.5||a.y<-.5||a.x>.3||a.y>.3?.5:length(a+.1)<.4&&(b.x+b.y-3)*b.y==0?.0:1.)*float(b.x<3&&b.y<3),1.);} \$\endgroup\$ – Gábor Fekete Nov 2 '17 at 3:57

Python 2,  169 140  137 bytes

from turtle import*
while i:i-=1;goto(20-i/3*20,i%3*20-20);stamp();209&2**i or dot(15,0,0,0)

Actual size, 61 by 61, plotted within a much larger canvas of 300 by 400:

actual size

Showing the pixel grid:

pixel grid version

The dots use 177 pixels within the range of 40%-80% whether considering the 19 by 19 white fill (144.4-288.8) or the 21 by 21 including both borders (176.4-352.8).

Note: the program terminates and closes the canvas window as soon as the drawing has been finished, to allow manual window closure append the line done().

turtle is a Python package developed for introductory graphical programming. A pen starts at x,y=0,0 in the middle of a 300 by 400 pixel canvas (by default), up lifts the pen, goto moves the pen, shape sets the shape of the pen to a named shape ("square" is a predefined shape with a default pixel-width of 21), color sets the colour, where two parameters set stroke (with default a width of 1) and fill; a byte is saved by using the (r,g,b) tuple option to replace "white" with [1,1,1] using the list multiplication [1]*3. Finally dot draws a dot with the given width in pixels and colour. The dot's default width value is too small to qualify, as is 9 so I made it an aesthetic and qualifying 15. The dot's colour could be "black" but the unpacked (r,g,b) tuple of 0,0,0 is shorter by two bytes.

The pen must move away from any dot at the end since otherwise the gray/white pen hides the dot.

The grid is traversed using a div (/) and mod (%) of i starting at 8 (i is initialised to 9 but is decremented at the beginning of the while loop) and working down to 0, offsetting the results of 2,1,0 to -1,0,1 using (1-...) and scaling each up to the grid size using a factor of 20 (note that 20-i/3*20 is actually a byte less than 20*(1-i/3), same goes for %). This produces the order [bottom-left, centre-left, top-left, bottom-middle, centre-middle, top-middle, bottom-right, centre-right, top-right], and requires a "hasDot" evaluation of [1,0,0,1,0,1,1,1,0], which is 302 in binary so may be accessed by inspecting the ith power of two component of 302 with using a bitwise-and, 302&2**i. This can then be inverted to 209&2**1 enabling the use of or rather than and.

  • \$\begingroup\$ Very good approach and much shorter than I thought would be possible using turtle. \$\endgroup\$ – Mast Jun 3 '17 at 11:11

HTML & CSS, 155 bytes

Turns out HTML is really forgiving about syntax errors.

1 byte saved thanks to @Octopus · 1 byte saved thanks to @Downgoat · 2 bytes saved thanks to @StephenS

2 bytes saved thanks to @Ryan · 3 bytes saved thanks to @styfle · 4 bytes saved thanks to @Ferrybig

13 bytes saved thanks to @SteveBennett

<table cellspacing=0 border=1><td><td><p><td><tr><td><td><td><p><tr><td><p><td><p><td><p

  • 2
    \$\begingroup\$ Please indicate on which browser (and which version) that works – it doesn't work in Opera 45. \$\endgroup\$ – Paŭlo Ebermann May 31 '17 at 23:38
  • 2
    \$\begingroup\$ The snippet does not work for me using Chrome 58.0.3029.110 (64-bit) on Windows. What Chrome version does it work in? \$\endgroup\$ – Jonathan Allan Jun 1 '17 at 2:11
  • \$\begingroup\$ This does not display the circles with Safari 10.1 on macOS Sierra (10.12.4). \$\endgroup\$ – R. Kap Jun 1 '17 at 3:19
  • \$\begingroup\$ dots are not displayed with Chromium 55.0.2883.87 (64-bit) either. \$\endgroup\$ – Dylan Meeus Jun 1 '17 at 6:56
  • \$\begingroup\$ Can't see the dots on Chrome for Android either (58.0.3029.83) \$\endgroup\$ – Spikatrix Jun 1 '17 at 9:29

Applesoft BASIC, 479 476 516 515 483 482 bytes

-32 by using unreadable variable names :P
-1 because Apple decided to be magical and let me use an implicit/nonexistent GOTO

Here is my own (very beatable) program for an example of an output that does not use circles:



  • 1
    \$\begingroup\$ I am not sure if this is valid, since line 1, being longer than 239 characters, is impossible to enter by normal methods, at least on a //e. \$\endgroup\$ – insert_name_here Jun 2 '17 at 6:29
  • 1
    \$\begingroup\$ @insert_name_here You have to save it to a file on a disk. \$\endgroup\$ – MD XF Jun 2 '17 at 14:20

IA-32 machine code, 81 80 bytes


60 8b f9 b8 50 35 20 20 ab b8 32 35 36 20 ab ab
ab fe 4f fe 33 c9 66 49 51 8a c1 d4 55 50 8a c5
d4 55 5b b2 80 84 c0 74 1f 84 db 74 1b b2 ff 2c
10 3c 35 77 13 93 2c 10 3c 35 77 0c 8d 0c 58 8a
cd b0 e4 d2 e0 79 01 42 92 aa 59 e2 cb aa 61 c3

It's a fastcall function called doit that returns the image in PGM format in the supplied buffer. Usage:

char buf[256 * 256 + 256];

FILE* f = fopen("k.pgm", "wb");
fwrite(buf, 1, sizeof buf, f);


hacker's logo

I used 256x256 resolution because it's cool it lets me split the pixel's index in ecx automatically into coordinates y in ch and x in cl. Also, the PGM file format requires the number 255 in the image header.

The inner squares are 54x54 (41% of the cell by area).

Source code (can be compiled by Visual Studio):

    pushad;                 // save all registers
    mov edi, ecx;           // edi is now the pointer to output
    mov eax, '  5P';        // PGM file header
    stosd;                  // store it
    mov eax, ' 652';        // the number 256 and a space
    stosd;                  // store the width
    stosd;                  // store the height
    stosd;                  // store maximum brightness
    dec byte ptr [edi-2];   // fix maximum brightness to 255

    xor ecx, ecx;           // initialize the counter of pixels
    dec cx;                 // to 65535
    push ecx;

    mov al, cl;             // al = cl = x coordinate in the image
    _emit 0xd4;             // divide by 85
    _emit 85;               // ah = x cell number, al = x coordinate in cell
    push eax;
    mov al, ch;             // al = ch = y coordinate in the image
    _emit 0xd4;             // divide by 85
    _emit 85;               // ah = y cell number, al = y coordinate in cell
    pop ebx;                // bh = x cell number, bl = x coordinate in cell

    mov dl, 0x80;           // gray pixel value
    test al, al             // is cell boundary (y)?
    je output1;
    test bl, bl;            // is cell boundary (x)?
    je output1;

    mov dl, 255;            // white pixel value
    sub al, 16;
    cmp al, 53;
    ja output1;             // if outside the inner square, output white
    xchg eax, ebx;          // exchange the registers to shorten following code
    sub al, 16;
    cmp al, 53;
    ja output1;             // if outside the inner square, output white

    lea ecx, [ebx * 2 + eax]; // cell index = y * 2 + x
    mov cl, ch;
    mov al, 0xe4;           // load the bitmap for the glider pattern
    shl al, cl;             // shift the needed but into SF
    jns output1;            // the bit was 0? - output white
    inc edx;                // the bit was 1? - change to black

    xchg eax, edx;
    stosb;                  // output the byte

    pop ecx;
    loop myloop;
    stosb;                  // output an additional gray pixel

The cell pattern

0 1 0
0 0 1
1 1 1

can be represented by an "optimized" bitmap of 7 bits.

The bits are indexed by the expression y * 2 + x, where (x,y) is the location of the cell. This expression gives the same index to 2 pairs of cells. It's a lucky coincidence that the bit values there are the same.

  • 1
    \$\begingroup\$ This is cool, but I make 42*42/85/85 only 24.4%. \$\endgroup\$ – Jonathan Allan Jun 1 '17 at 21:21
  • \$\begingroup\$ @JonathanAllan: The white parts of the cell are only 84x84, but yes, a 42x42 box is only a quarter of a 84x84 box. \$\endgroup\$ – Nick Matteo Jun 1 '17 at 22:36
  • \$\begingroup\$ I've asked for clarification (if it does go to area I hope it's not too hard to update). \$\endgroup\$ – Jonathan Allan Jun 1 '17 at 22:42
  • \$\begingroup\$ The ruling is in - it's area... \$\endgroup\$ – Jonathan Allan Jun 1 '17 at 22:46
  • \$\begingroup\$ I enlarged the black dots from 42 to 54. It's the minimum, making them 40% by area, and they have already started being ugly... \$\endgroup\$ – anatolyg Jun 1 '17 at 23:00

R (130 119 113 bytes)


enter image description here

  • \$\begingroup\$ You can use axes=F to replace xaxt="n",yaxt="n". If you double all coordinate values, you save 4 net bytes (but can't use the 1:3,2:3 trick). \$\endgroup\$ – user2390246 Jun 1 '17 at 11:02
  • \$\begingroup\$ @user2390246: thx for the suggestions. I didn't find much time to golf this out. I'm sure there are more possible improvements. I had to add ;box() as axes=F also removes the frame. Also, as axes is a plot parameter and not passed on to par through ... as xaxt/yaxt, it doesn't even need to be spelled out completely. \$\endgroup\$ – mschilli Jun 1 '17 at 15:00
  • 1
    \$\begingroup\$ You can shave off 7 bytes by (1) replacing c(1,7) with a variable (l=c(1,7)); (2) replacing ann with an; (3) replacing [xy]li with [xy]li; and (4) removing the second, redundant argument to grid: grid(3,lt=1). In fact, I’ve taken the liberty of editing this in (under review). \$\endgroup\$ – Konrad Rudolph Jun 2 '17 at 13:25
  • 1
    \$\begingroup\$ @KonradRudolph Seems relevant: codegolf.meta.stackexchange.com/questions/1615/… \$\endgroup\$ – Matt Jun 2 '17 at 13:46
  • \$\begingroup\$ @Matt Hm. Seems that this makes sense if it applies fundamentally different optimisations, rather than just implementing straightforward improvements. Fair enough. \$\endgroup\$ – Konrad Rudolph Jun 2 '17 at 13:56

Python 2.7, 214 311 309 bytes

from matplotlib.pyplot import*
for i in j:x.add_artist(Circle((i),.4,color='k'))     
for o in x.spines.values():o.set_edgecolor('gray')
for s in 'xy':exec"x.set_"+s+"ticks((.5,1.5,2.5));"+s+"lim(-.5,2.5);"

This is my first attempt here at code golf, so I'm sure this can be improved upon. I would have liked to not established the limits, but it appears that matplotlib can't detect that I plotted circles where I did. Without setting xlim() and ylim() it only shows the bottom two circles.



Edit:Fixed the color of the borders and removed the tick numbers. I must say matplotlib is very densely worded, and not too friendly with changing axis colors.

Shaved off 3 bytes thanks to @DJMcMayhem

Edit:Took off two bytes by setting my ticks as a tuple inside of set_ticks functions.

  • \$\begingroup\$ Sorry, the numbers on the graph are not allowed. Also, is the border gray? \$\endgroup\$ – MD XF May 31 '17 at 21:53
  • 3
    \$\begingroup\$ Welcome to the site! This is a nice first answer. :) \$\endgroup\$ – James May 31 '17 at 22:02
  • 1
    \$\begingroup\$ Some minor golfs I see: 1) You can join lines 5 and 6 to remove one space and a newline (-2 bytes) 2) if the order of set xy_ticks and xy_lim doesn't matter, you could do something like for s in'xy':exec"x.set_"+s+"ticks(a);"+s+"lim(-.5,2.5);". (I haven't tested that though, so I'm not positive) \$\endgroup\$ – James May 31 '17 at 22:06

Bash + ImageMagick, 233 226 characters

convert xc: +antialias -resize 31 -draw "stroke gray fill none ${r=rectangle} 0,0 10,30$r 20,0 30,30$r 0,0 30,10$r 0,20 30,30stroke #000 fill #000 ${c=circle} 15,5 15,8$c 25,15 25,18$c 5,25 5,28$c 15,25 15,28$c 25,25 25,28" x:

Sample output:

Glider drawn with Bash and ImageMagick

Bash + ImageMagick, 215 characters

convert xc: -resize 31 -draw "stroke gray fill none ${r=rectangle} 0,0 10,30$r 20,0 30,30$r 0,0 30,10$r 0,20 30,30stroke #000 fill #000 ${c=circle} 15,5 15,8$c 25,15 25,18$c 5,25 5,28$c 15,25 15,28$c 25,25 25,28" x:

The question owner not answered yet the anti-aliasing question and some other solutions also have additional gray shades added by the anti-aliasing, so for now this shorter one looks also acceptable.

Sample output:

Glider drawn with Bash and ImageMagick - with anti-aliasing


PNG, 105 100 bytes

PNG image    (i.e. this image file)

Considering that HTML and other non-programming languages are allowed, I was curious to see how much I could golf a plain browser-displayable image, to serve as a baseline comparison. The result is compressed with the open-source tools optipng (-o7 -zm1-9 -strip all) and pngwolf. I also experimented with zopflipng, but the results were bigger. Other closed-source compression tools might be able to shave off a couple more bytes.

Image data in base64:


<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB8AAAA

Edit I made the dots touch the cell top and bottom, to cause more repetitiveness in the pixel pattern and thus improve the compression ratio. But don't worry, a dot still only fills (7*9)/(9*9) ≈ 78% of its cell.

Non-standard PNG, 88 bytes

As pointed out by @anatolyg, there is some golfing potential by removing the IEND chunk (12 bytes). Technically, IEND is required by the standard. However, each PNG chunk includes its own size and checksum information. It is therefore not absolutely necessary to have an end-marker. And indeed, all browsers I tested can display the image without issue.

Unfortunately (or fortunately), this non-standard image is rejected by imgur, so I cannot actually upload it. This is the base64 encoding:


<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB8AAAA

  • \$\begingroup\$ I'm not sure if this valid. PNG is not a programming language. \$\endgroup\$ – James Jun 2 '17 at 15:43
  • 4
    \$\begingroup\$ Thank you MD XF. @DJMcMayhem Neither is HTML. But considering the small size of the image, I submitted it as an interesting outside-the-box entry. \$\endgroup\$ – Meyer Jun 2 '17 at 15:51
  • 4
    \$\begingroup\$ @DJMcMayhem Answers in non-programming-languages are technically allowed by consensus. Especially, for fixed-output challenges. \$\endgroup\$ – Martin Ender Jun 2 '17 at 16:39
  • 4
    \$\begingroup\$ Also, welcome to PPCG, @Meyer! :) \$\endgroup\$ – Martin Ender Jun 2 '17 at 16:41
  • 1
    \$\begingroup\$ You can remove a few bytes at the end of the file and still have the image. Might depend on a viewer though; I imagine most viewers don't require e.g. the end-chunk to be present. \$\endgroup\$ – anatolyg Jun 4 '17 at 9:50

Ruby, 144 166 164 148 144 bytes

set background:'grey'
g.map{|y|g.map{|x|Square.new(x,y,9);Square.new(x+2,y+2,5,"black")if c[d]>0;d+=1}}



Edit: Now has grey gridlines.

  • 3
    \$\begingroup\$ I can see a few golfing opportunities here. For starters, d=d+1 has a shorter form (d+=1) and ==1 here is equivalent to >0. Also consider what happens when you set c to a Fixnum instead of an array :-) \$\endgroup\$ – RJHunter Jun 1 '17 at 6:26
  • 1
    \$\begingroup\$ @RJHunter I missed some low hanging fruit! And I thought about stuff like creating a bitfield with c, but couldn't come up with a way that's actually shorter in implementation. \$\endgroup\$ – Mark Thomas Jun 1 '17 at 23:34
  • 2
    \$\begingroup\$ Perhaps surprisingly, Ruby actually has some bitfield support built in! You can access an integer with [] as if it were an array of bits (read-only, but that's OK here). \$\endgroup\$ – RJHunter Jun 2 '17 at 0:28
  • \$\begingroup\$ @RJHunter thanks! All I had to do was change c to the appropriate number. Reduced it quite a bit. \$\endgroup\$ – Mark Thomas Jun 2 '17 at 0:44
  • \$\begingroup\$ You can change g=[2,13,24] to g=2,13,24 and replace each with map. \$\endgroup\$ – Jordan Jun 3 '17 at 18:28

Octave, 127 124 bytes

Removed 3 bytes thanks to Luis. grid is sufficient (instead of grid on).


Outputs (after saving):

Note that the output shows grey grid lines in the plot window. They turn black when saving it (for some reason).

enter image description here

Well, that was long and messy! Had to go through a lot of modifications to make this adhere to the specs.

Explanation and hopefully some golfing coming up...

  • \$\begingroup\$ That doesn't look very squary, but since the OP did an answer with a similar output I guess it's fine.. \$\endgroup\$ – L3viathan May 31 '17 at 20:43
  • 2
    \$\begingroup\$ I think the height/width ratio is platform dependent. Add 'square' to make it square on all platforms. spy([0,1,0;0,0,1;1,1,1],'.k',80),set(gca,'XTick',.5:4,'XTickLabel','','YTick',.5:4,'YTickLabel',''),axis(.5+[0,3,0,3],'square'),grid on. \$\endgroup\$ – Stewie Griffin May 31 '17 at 20:55

Processing, 212 198 bytes

background(-1);noFill();stroke(99);rect(0,0,99,99);rect(0,33,99,33);rect(33,0,33,99);fill(0);int f=25;ellipse(15,83,f,f);ellipse(50,83,f,f);ellipse(83,83,f,f);ellipse(83,50,f,f);ellipse(50,15,f,f);

Basically, we are using simple Processing to draw a white Background, then setting the transparency of the rectangles used for the grid and drawing their strokes in gray. We continue by defining the rectangle, setting the fill value again to fill the circles black and defining fives circles.


enter image description here

You could add


or more to see the color of the strokes better.

(That's my first Code-Golf, I hope I did everything right.)

EDIT: Thanks to Kritixi Lithos! Removed the newlines, changed to int f=25 and used -1 in background(float)

  • 1
    \$\begingroup\$ Great first golf, and welcome to PPCG! \$\endgroup\$ – MD XF Jun 1 '17 at 22:05
  • 1
    \$\begingroup\$ You can save some bytes by removing the newlines, changing the float f=25; to int f=25; and by using background(-1) instead of background(255); \$\endgroup\$ – user41805 Jun 2 '17 at 6:19

Tikz, 193 175 170 bytes


Here is the output:


  • 3
    \$\begingroup\$ @MDXF It cuts close but since these are perfect circles and squares they make up π/4 of the square which is just about 79% of the square. \$\endgroup\$ – Wheat Wizard Jun 1 '17 at 18:46
  • \$\begingroup\$ Damn, looked at the challenge and had the exact same idea ;) \$\endgroup\$ – racer290 May 17 '18 at 7:51

MATL, 74 69 68 64 62 bytes


Try it at MATL Online! (It takes a few seconds.)

Output from the online interpreter:

enter image description here


SmileBASIC, 125 bytes

GBOX.,8,30,38GBOX 10,8,20,38GBOX.,18,30,28G.,1G 1,2G-1,3G.,3G 1,3DEF G X,Y
GPUTCHR X*10+12,Y*10,58081,.END

58081 (U+E2E1, which is in the "Private Use Area" block) is the character code for a circle symbol. Putting it in a string would work too, but since it is encoded as 3 bytes in UTF-8, it would be the same length (and not show up correctly here).

markdown is awful

  • 1
    \$\begingroup\$ It's always refreshing to see basic answers! \$\endgroup\$ – Taylor Scott Feb 23 '18 at 19:24

Processing, 134 bytes

Inspired by @Zep, here's my Processing one-liner (and also my first code golf):

stroke(127);for(int i=0;i<9;i++){int x=i%3*30;int y=i/3*30;fill(255);rect(x+5,y+5,30,30);if(i==1||i>4){fill(0);ellipse(x+20,y+20,23,23);}};

Thanks for @Kritixi Lithos for his brilliant tips on shaving a few bytes off!

glider in Processing

  • \$\begingroup\$ Please include a Language and Score line. \$\endgroup\$ – Theraot Jun 2 '17 at 3:50
  • \$\begingroup\$ Welcome to PPCG and nice first answer! As stated by Theraot, all submissions are required to have a header that contains the language and the bytecount. Also, you can golf some bytes by declaring all the variables in the for-loop, like for(int i=0,x,y;... so that you can drop the int in the body of the loop. Additionally, fill(255); can become just fill(-1); \$\endgroup\$ – user41805 Jun 2 '17 at 6:17
  • \$\begingroup\$ I haven't tested this, but I think you can drop the +20 while setting the values of x and y, so that you can change the rect to rect(x+5,y+5,30,30); and the ellipse to ellipse(x+20,y+20,23,23); and save two bytes. \$\endgroup\$ – user41805 Jun 2 '17 at 6:24

LaTeX + Tikz, 155 bytes

\documentclass[tikz]{standalone}\begin{document}\tikz{\draw(0,0)grid(3,3);\foreach\x/\y in{0/0,1/0,2/0,2/1,1/2}\fill(\x+.5,\y+.5)circle(.5);}\end{document}


  • 1
    \$\begingroup\$ Is that 1/0 doing division? \$\endgroup\$ – wizzwizz4 Jun 2 '17 at 11:52
  • \$\begingroup\$ Sorry, but no, it is a simple separator in the pairs of x and y coordinates. \$\endgroup\$ – TonioElGringo Jun 2 '17 at 11:54
  • \$\begingroup\$ You should be able to save a few bytes by scaling everything up by 2, so that your .5's become just 1. \$\endgroup\$ – Chris Aug 28 '17 at 4:07
  • \$\begingroup\$ @Chris The grid builtin produces unit-length cells by default, and it takes about 8 bytes more (adding [step=2]) to produce a larger grid. Simplifying the coordinates for the circles drawing would not save enough bytes. (You get 157 bytes if you do it) \$\endgroup\$ – TonioElGringo Aug 28 '17 at 8:38
  • \$\begingroup\$ @TonioElGringo Ah, true. Teaches me to comment without testing it first ;) \$\endgroup\$ – Chris Aug 28 '17 at 18:39

C#, 333 bytes

using System.Drawing;_=>{var b=new Bitmap(31,31);var g=Graphics.FromImage(b);g.FillRectangle(Brushes.White,0,0,31,31);for(int x=0,y;x<3;++x)for(y=0;y<3;++y){g.DrawRectangle(Pens.Gray,x*10,y*10,10,10);if(x==1&y<1|x>1&y==1|y>1)g.FillEllipse(Brushes.Black,x*10+1,y*10+1,8,8);}b.Save("t.png");System.Diagnostics.Process.Start("t.png");};

Full/Formatted version:

using System.Drawing;
Action<int> a = _ =>
    var b = new Bitmap(31, 31);
    var g = Graphics.FromImage(b);

    g.FillRectangle(Brushes.White, 0, 0, 31, 31);

    for (int x = 0, y; x < 3; ++x)
        for (y = 0; y < 3; ++y)
            g.DrawRectangle(Pens.Gray, x * 10, y * 10, 10, 10);
            if (x == 1 & y < 1 | x > 1 & y == 1 | y > 1)
                g.FillEllipse(Brushes.Black, x * 10 + 1, y * 10 + 1, 8, 8);


Idea is simple we create a graphics object from the image and use that to make the image all white. Then loop over each square of the image drawing the bounding rectangle. If it is one of the locations for a dot we draw that too. Lastly we save the image to file and let windows decide how to open it, in my case it opens with Windows Photo Viewer.

Using a Process to show the image and saving to file is a lot shorter than creating a windows forms or WPF app because of all the different classes and extra fluff needed to create them.



  • \$\begingroup\$ I don't think you have to use Process.Start, for example Titus answer just outputs image, doesn't open it \$\endgroup\$ – Jeremy Thompson Jun 4 '17 at 11:55
  • \$\begingroup\$ @JeremyThompson the rules state you must display the image \$\endgroup\$ – TheLethalCoder Jun 4 '17 at 16:40

PHP, 221+2 bytes

<?imagefill($i=imagecreatetruecolor(31,31),0,0,~0);function q($i,$x,$y,$f){imagerectangle($i,$x*=10,$y*=10,$x+10,$y+10,5e6);$f?:imagefilledellipse($i,$x+5,$y+5,8,8,0);}for($p=16;$p--;)q($i,$p&3,$p>>2,53>>$p&1);imagepng($i);

Save to file; call in browser. Should your browser display gibberish,
insert header("Content-Type:image-png"); before imagepng($i);.

output The dots aren´t very round; that´s due to the small proportions.


function q($i,$x,$y,$f){        # function to draw quadrant:
    imagerectangle($i,$x*=10,$y*=10,$x+10,$y+10,5e6);   # draw lines in 0x4c4b40
    $f?:imagefilledellipse($i,$x+5,$y+5,8,8,0);         # if bit not set, draw dot

    imagecreatetruecolor(31,31) # create image
    ,0,0,~0);                   # fill with 0xffffff (white)
for($p=16;$p--;)q($i,           # loop through positions, call function
    $p&3,                           # $x=lower two bits
    $p>>2,                          # $y=upper two bits
    53>>$p&1                        # $f=one bit from %0000 0000 0011 0101
);                                      # (reversed inverted bit mask for dots)
imagepng($i);                   # output image

I think that 0x4c4b40 qualifies as approximated gray. If not, add four bytes.


R 313 236 bytes

a=function(s,...){axis(s,labels=F,tck=1, col="gray",lwd=9,...)}

Revised Code, based mostly on comments from @user2390246 saved 77 bytes. Much appreciate the help.

Also, want to add a call-out to the shorter R solution by @mschilli. It shows an elegant way of addressing the problem of the R graphical defaults.


Goes to a file names "r". Omitting and extension saved me four bytes. But then I had to edit the file extension back to "bmp" to get it to upload. So maybe I should not get credit for those four bytes.

The Hacker Logo


I thought to myself, "That graphic's nothing but a simple graph with five dots. Should be a simple matter to implement in a language with robust data graphics capabilities. Let's try it in R." But then I had to spend on the order of 80% of the bytes just working around R's graphic defaults.

Kinda the wrong tool for the job....

I could not find a less verbose way of guaranteeing the size and aspect ratio of the graphic than by calling the bmp constructor and then dev.off(). The combination accounts for 25 bytes. If your R session is set up right, you might get a graphic that looks more or less correct without spending those bytes, but it's not reliable or consistent.

  • 1
    \$\begingroup\$ A few suggestions: don't define your data frame b at all, just put the two vectors unnamed directly into the plot function. Use c(l,3) for xaxp and yaxp. You can just use F for false, no need to define it. And define a new function a(x,...) that calls axis(x) but has default values for labels, tck, etc, so that you don't need to specify them all twice. \$\endgroup\$ – user2390246 Jun 1 '17 at 10:33
  • \$\begingroup\$ You can also use axes=F rather than xaxt='n',yaxt='n'. And you forgot to use .5 when defining l though you did use that trick later. \$\endgroup\$ – user2390246 Jun 1 '17 at 10:46
  • 1
    \$\begingroup\$ Actually, what if you doubled all coordinate values to get rid of those pesky .5s altogether? \$\endgroup\$ – user2390246 Jun 1 '17 at 10:54
  • 1
    \$\begingroup\$ If you're already gonna take off the .bmp file extension, you might as well just name the file r. \$\endgroup\$ – MD XF Jun 1 '17 at 18:49
  • \$\begingroup\$ @user2390246 -- Many thanks for the suggestions. Cumulatively saved on the order of 70 bytes. This was my first effort at golfing in R, and you spotted a lot of tyro's errors I probably should have seen. Next time I'll know better. \$\endgroup\$ – CCB60 Jun 2 '17 at 4:42

TI-BASIC, 218 140 137 bytes

Note: this byte count is a bit inflated. The program only uses 85 tokens, but that's saved in 137 bytes. Also, if you're using a non-color calculator, you could save another 4 tokens because you don't have to specify the color (which is blue by default), but I don't know if their screens are large enough for this challenge because I don't own one.

prgmHACKER (138 bytes, 86 tokens):


For proper display, this program requires that Xmin = Ymin = 0, Xmax = Ymax = 3, Xscl = Yscl = 1. dX also needs to be properly set, but the calculator does that for you when you set any other window variable. I couldn't see how much space these variables used in RAM.

Furthermore, the format settings should be { RectGC, CoordOff, GridLine, GridColor:MEDGRAY, Axes:OFF, ExprOff, BorderColor:1, Background:OFF } but these are toggled values and don't consume any extra space depending on the setting.

  • \$\begingroup\$ To golf down the list, you could express these as {0,1,2,1,2} and {0,0,0,2,1} then add 0.5 to each item. \$\endgroup\$ – wizzwizz4 Jun 2 '17 at 11:58
  • \$\begingroup\$ Tried that, but it didn't change the amount of RAM used by the lists. However, you gave me the idea to get rid of the lists in RAM and define them when the program runs, saving 78 bytes in RAM. \$\endgroup\$ – foxite Jun 2 '17 at 12:04
  • \$\begingroup\$ Order in the golf people! Change the L1 and L2 to L₁ and L₂, since you already use them. I think you can remove }, and L₁(I)+.5→A=>.5+L₁(I and L₂(I)+.5→B => .5+L₂(I→B. \$\endgroup\$ – Adalynn Aug 1 '17 at 0:11

R, 119 114 111 bytes

(Thans to @JayCe for saving me 3 bytes)

Not shorter than the other R solution, but a completely different approach:

for(i in 1:9){frame();if(i>4)points(.5,.5,,19,cex=29);box(fg=8)}

Uses a layout in which the 4 first plots are the empty cells, and the 5 others the ones with dots in them.


  • \$\begingroup\$ Can me made shorter than the other solution using positional arguments: here \$\endgroup\$ – JayCe May 16 '18 at 18:33
  • \$\begingroup\$ @JayCe indeed, thanks! \$\endgroup\$ – plannapus May 17 '18 at 7:40

Excel VBA, 180 bytes

An anonymous VBE Immediate window function that takes no input and outputs to the default worksheet object (Sheet1).

Cells.RowHeight=48:Cells.Interior.Color=-1:[B2:D4].Borders.Color=7434613:For Each s In[{21,32,13,23,33}]:Sheet1.Shapes.AddShape(9,48*(s\10)+4,Mid(s,2)*48+4,40,40).ShapeStyle=8:Next

Commented Version

Cells.RowHeight=48                      ''  Make the Cells square
Cells.Interior.Color=-1                 ''  Remove the default grid
[B2:D4].Borders.Color=7434613           ''  Create the 3x3 gray grid at range `B2:D4`
For Each s In [{21,32,13,23,33}]        ''  Assign and iterate over a list of where
                                        ''  to place the dots; This list is a range that 
                                        ''  is coerced into a numeric array
    Sheet1.Shapes.AddShape(         _   ''  Add a shape to the Sheet1 object
                9,                  _   ''  An Oval (msoShapeOval)
                48*(s\10)+4,        _   ''  At the calculated value from the left
                Mid(s,2)*48+4,      _   ''  At the calculated value from the top
                40,                 _   ''  that is 40 units wide
                40                  _   ''  and is 40 units tall
                ).ShapeStyle=8          ''  and is black filled with a black outline

Next                                    ''  repeat to end of list


Hacker Logo

-6 bytes for using [{21,32,13,23,33}] over Split("21 32 13 23 33")

-2 bytes for using Mid(s,2) over Right(s,1)

-3 bytes for using (s\10) over Left(s,1)


Octave 107 94 103 bytes

scatter([1:3,3,2],[1,1,1:3],1e5,zeros(5,3),'.');axis off;a=[1,7]/2;for i=.5:3.5;line(a,i);line(i,a);end


plot([1:3,3,2],[1,1,1:3],'k.','markersize',250);axis off;a=[1,7]/2;for i=.5:3.5;line(a,i);line(i,a);end

both solutions are 103 bytes.

  • 2
    \$\begingroup\$ I believe the dots have to be black \$\endgroup\$ – TheLethalCoder Jun 1 '17 at 10:38
  • \$\begingroup\$ ah, interesting, matlab interprets a scalar as a point, as opposed to broadcasting it. so instead of line([x1,x2],y) you have to do line([x1,x2],[y,y]) \$\endgroup\$ – Tasos Papastylianou Jun 1 '17 at 10:52

gnuplot, 158 156 bytes

se si ra-1
se xti 2
se yti 2
se st l 9 lc"gray"lt 1
se gr xt ls 9 yt ls 9
se bor ls 9
uns k
se form""
p'-'w cir fc"black"fs s
3 5 1
5 3 1
1 1 1
3 1 1
5 1 1

Because the radii are the same, I tried the following:

[... first eight lines same as above ...]
p'-'u 1:2:(1) w cir fc"black"fs s
3 5
5 3
1 1
3 1
5 1

But that lead to the same byte count.

Ungolfed with comments:

set size ratio -1                                     # make it a square.
set xtics 2                                           # vertical lines every 2 units
set ytics 2                                           # horizontal lines every 2 units
set style line 9 linecolor rgb "gray" linetype 1      # define line type 9 as solid gray
set grid xtics linestyle 9 ytics linestyle 9          # make internal lines of type 9
set border linestyle 9                                # make outside lines of type 9
unset key                                             # no legend please
set format ""                                         # no numbers next to axes please
plot '-' with circle fillcolor rgb "black" fill solid # plot black circles
3 5 1                                                 # at these locations
5 3 1
1 1 1
3 1 1
5 1 1

  • \$\begingroup\$ Are the circles <= 80% of the grid-boxes? \$\endgroup\$ – MD XF Jun 1 '17 at 18:49
  • \$\begingroup\$ Maybe by area, 𝜋/4 ≈ 78% \$\endgroup\$ – anatolyg Jun 1 '17 at 20:00
  • 2
    \$\begingroup\$ Yes, they cover pi/4, which is around 78%. I could make them slightly smaller and look better, but that would cost byte. \$\endgroup\$ – user34409 Jun 2 '17 at 5:47
  • \$\begingroup\$ ... would cost one byte. \$\endgroup\$ – user34409 Jun 2 '17 at 6:22

Apple Swift (iOS - CoreGraphics/QuartzCore) - 832 Bytes

I drew the shape entirely using Quartz for an Apple iOS device. Unfortunatly this isn't a particularly size mindful language so the result is quite large, but this is as small as I can get it.

UIGraphicsBeginImageContext(CGSize(width:60,height:60));let c=UIGraphicsGetCurrentContext()!;UIColor.lightGray.setStroke();c.addRect(CGRect(x:0,y:0,width:60,height:60));c.move(to: CGPoint(x:20,y:0));c.addLine(to: CGPoint(x:20,y:60));c.move(to: CGPoint(x:40,y:0));c.addLine(to: CGPoint(x:40,y:60));c.move(to: CGPoint(x:0,y:20));c.addLine(to: CGPoint(x:60,y:20));c.move(to: CGPoint(x:0,y:40));c.addLine(to: CGPoint(x:60, y:40));c.strokePath();UIColor.black.setFill();c.addEllipse(in:CGRect(x:22,y:2,width:16,height:16));c.addEllipse(in:CGRect(x:42,y:22,width:16,height:16));c.addEllipse(in:CGRect(x:2,y:42,width:16,height:16));c.addEllipse(in:CGRect(x:22,y:42,width:16,height:16));c.addEllipse(in:CGRect(x:42,y:42,width:16,height:16));c.fillPath();let i=UIGraphicsGetImageFromCurrentImageContext();sub.addSubview(UIImageView(image:i))

A more readable version for anyone that is interested:

    UIGraphicsBeginImageContext(CGSize(width: 60, height: 60))
    let c = UIGraphicsGetCurrentContext()!
    c.addRect(CGRect(x: 0, y: 0, width: 60, height: 60))
    c.move(to: CGPoint(x: 20, y: 0))
    c.addLine(to: CGPoint(x: 20, y: 60))
    c.move(to: CGPoint(x: 40, y: 0))
    c.addLine(to: CGPoint(x: 40, y: 60))
    c.move(to: CGPoint(x: 0, y: 20))
    c.addLine(to: CGPoint(x: 60, y: 20))
    c.move(to: CGPoint(x: 0, y: 40))
    c.addLine(to: CGPoint(x: 60, y: 40))
    c.addEllipse(in: CGRect(x: 22, y: 2, width: 16, height: 16))
    c.addEllipse(in: CGRect(x: 42, y: 22, width: 16, height: 16))
    c.addEllipse(in: CGRect(x: 2, y: 42, width: 16, height: 16))
    c.addEllipse(in: CGRect(x: 22, y: 42, width: 16, height: 16))
    c.addEllipse(in: CGRect(x: 42, y: 42, width: 16, height: 16))
    let i = UIGraphicsGetImageFromCurrentImageContext()
    sub.addSubview(UIImageView(image: i))

Here is the output produced in the iOS Simulator: Output


Ruby with Shoes, 118 characters

stroke gray
fill white
rect x=i%3*w=10,y=i/3*w,w,w
stroke fill black
oval x+2,y+2,7if 482[i]>0}}

Bit checking borrowed from RJHunter's comment made on Mark Thomas's Ruby solution.

Sample output:

Glider drawn with Ruby with Shoes


SVG + HTML, 146 138 135 133 bytes

<path fill=none stroke=#ccc d=m.5.5h30v30h-30zh10v30h10v-30zv10h30v10h-30 />
<path d=m11,1h9v9m1,1h9v9m-29,1h9v9m1-9h9v9m1-9h9v9>

Thanks to the lenient HTML parser, the xmlns="http://www.w3.org/2000/svg" declaration can be omitted, as well as attribute quotes and the closing tag. This version addresses some issues of other HTML solutions:

  • A "dot" is guaranteed to fill at least 40% of its cell (§1)
  • It does not use external graphics, e.g. font glyphs (§2, §6)
  • The grid is perfectly square (§5)

Edit Shaved off 8 bytes by exploiting the fact that subpaths do not need to be closed in order to be filled.

Edit According to the svg grammar, it is not necessary to separate non-digits with a comma (.5,.5). I also abandoned the explicit fill, so that I can change the draw direction of one line from negative to positive, saving a dash. And lastly, I adjusted the count to not include a trailing newline, sorry for this rookie mistake.

Edit Learning from another answer on codegolf, I have replaced the final 9 /> with 9>. This works fine in all tested browsers.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.