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.

  • 23
    \$\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\$ May 31, 2017 at 19:18
  • 16
    \$\begingroup\$ @MarkThomas that or a GoL nerd xD \$\endgroup\$
    – Stephen
    May 31, 2017 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, 2017 at 2:40
  • 3
    \$\begingroup\$ Is multiple shades of gray (and related off colors) due to anti-aliasing allowed? \$\endgroup\$
    – Ian Miller
    Jun 1, 2017 at 8:01
  • 3
    \$\begingroup\$ Do we have to display the output or can we return it or save to a file? \$\endgroup\$ Jun 1, 2017 at 9:02

54 Answers 54


OpenTuring, 203 189 bytes

This is a language I hated in high school, but it has graphics, so...

for i:0..2
for j:0..2
if j=0 then
end if
end for
end for


  • \$\begingroup\$ @MDXF, oh sorry, I just remembered about the screenshot, I'll add it now \$\endgroup\$
    – Jeffmagma
    Jun 3, 2017 at 21:48
  • \$\begingroup\$ No problem; thanks! +1 \$\endgroup\$
    – MD XF
    Jun 3, 2017 at 21:59

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.


Python 3 + PyGame, 238 Bytes

from pygame import*
for x in[0,18,36,54]:
for x,y in zip([3,5,1,3,5],[1,3,5,5,5]):draw.circle(s,[0]*3,(x*9,y*9),7)

The seemingly arbitrary constants are from me trying to make the image as large as possible without sacrificing bytes.

With non-printing characters, 229 Bytes

from pygame import*
for x in b'\0␒$6':
for x,y in zip(b'␃␅␁␃␅',b'␁␃␅␅␅'):draw.circle(s,[0]*3,(x*9,y*9),7)

I replaced the lists with byte literals, which saves a bunch of characters, but the non-printing characters can't be displayed properly here. I substituted the non-printing characters with their graphical equivalents U+2400-U+2421 for display purposes.



6502 machine code (C64), 310 bytes

00 C0 A9 00 A8 85 FC A2 E0 86 FD A2 20 91 FC C8 D0 FB E6 FD CA D0 F6 A2 CC 86
FD A2 18 A0 27 C0 09 F0 20 C0 06 F0 1C C0 03 F0 18 C0 00 F0 14 E0 18 F0 10 E0
15 F0 0C E0 12 F0 08 E0 0F F0 04 A9 01 D0 02 A9 C1 91 FC 88 10 D5 A5 FC 69 27
85 FC A5 FD 69 00 85 FD CA 10 C4 A9 FF A2 0F 9D 60 E1 9D A0 E2 9D 38 E5 9D 78
E6 9D C8 E8 9D 08 EA 9D E0 E8 9D 20 EA 9D F8 E8 9D 38 EA CA 10 DF A9 40 85 FC
A9 E1 85 FD A2 20 A0 00 A9 18 91 FC C8 98 29 07 D0 F6 98 69 10 A8 CA F0 13 8A
29 03 D0 EA A5 FC 69 40 85 FC A5 FD 69 01 85 FD D0 DA A9 18 A2 02 9D 05 E0 9D
1D E0 9D 35 E0 9D 4D E0 9D 40 EB 9D 58 EB 9D 70 EB 9D 88 EB CA 10 E5 A9 0B 85
FC A9 E0 85 FD A2 20 A0 00 A9 FF 91 FC C8 98 29 01 D0 F6 98 69 06 A8 CA F0 13
8A 29 07 D0 EA A5 FC 69 C0 85 FC A5 FD 69 03 85 FD D0 DA A9 1F A2 01 9D 03 E0
9D C3 E3 9D 83 E7 9D 43 EB 49 E7 9D 4B E0 9D 0B E4 9D CB E7 9D 8B EB 49 E7 CA
10 E1 A9 94 8D 00 DD A9 3B 8D 11 D0 A9 3D 8D 18 D0 A9 01 8D 20 D0 D0 FE

I expected this to be possible in fewer bytes, but didn't find a way for quite a while, so posting it anyways now :)

Online demo, Usage: sys49152


Explanation: (commented vice disassembly listing)

         00 C0       .WORD $C000

         ; clear 8kiB monochrome bitmap at $E000:
.C:c000  A9 00       LDA #$00
.C:c002  A8          TAY
.C:c003  85 FC       STA $FC
.C:c005  A2 E0       LDX #$E0
.C:c007  86 FD       STX $FD
.C:c009  A2 20       LDX #$20       ; 16 pages to clear
.C:c00b   .cl_loop:
.C:c00b  91 FC       STA ($FC),Y
.C:c00d  C8          INY
.C:c00e  D0 FB       BNE .cl_loop
.C:c010  E6 FD       INC $FD
.C:c012  CA          DEX
.C:c013  D0 F6       BNE .cl_loop

     ; set colors for each 8x8 pixel block:
         ; ------------------------------------
.C:c015  A2 CC       LDX #$CC       ; start address of bitmap colors
.C:c017  86 FD       STX $FD        ; ($CC00) in zeropage pointer
.C:c019  A2 18       LDX #$18       ; 25 rows
.C:c01b   .sc_loop1:
.C:c01b  A0 27       LDY #$27       ; 40 columns (counts down to 0)
.C:c01d   .sc_loop2:
.C:c01d  C0 09       CPY #$09       ; for every third column ...
.C:c01f  F0 20       BEQ .sc_gray
.C:c021  C0 06       CPY #$06
.C:c023  F0 1C       BEQ .sc_gray
.C:c025  C0 03       CPY #$03
.C:c027  F0 18       BEQ .sc_gray
.C:c029  C0 00       CPY #$00
.C:c02b  F0 14       BEQ .sc_gray
.C:c02d  E0 18       CPX #$18       ; ... or every third row ...
.C:c02f  F0 10       BEQ .sc_gray
.C:c031  E0 15       CPX #$15
.C:c033  F0 0C       BEQ .sc_gray
.C:c035  E0 12       CPX #$12
.C:c037  F0 08       BEQ .sc_gray
.C:c039  E0 0F       CPX #$0F
.C:c03b  F0 04       BEQ .sc_gray   ; ... use gray ($C) on white ($1)
.C:c03d  A9 01       LDA #$01       ; else use black ($0) on white ($1)
.C:c03f  D0 02       BNE .sc_store
.C:c041   .sc_gray:
.C:c041  A9 C1       LDA #$C1
.C:c043   .sc_store:
.C:c043  91 FC       STA ($FC),Y    ; store color
.C:c045  88          DEY
.C:c046  10 D5       BPL .sc_loop2
.C:c048  A5 FC       LDA $FC        ; add offset for next row to pointer
.C:c04a  69 27       ADC #$27
.C:c04c  85 FC       STA $FC
.C:c04e  A5 FD       LDA $FD
.C:c050  69 00       ADC #$00
.C:c052  85 FD       STA $FD
.C:c054  CA          DEX
.C:c055  10 C4       BPL .sc_loop1

         ; draw "dots" as solid squares of 16x16
         ; -------------------------------------
.C:c057  A9 FF       LDA #$FF       ; all 8 pixels set
.C:c059  A2 0F       LDX #$0F       ; loop over 2*8 = 16 rows
.C:c05b   .sq_loop:
.C:c05b  9D 60 E1    STA $E160,X    ; store at different offsets
.C:c05e  9D A0 E2    STA $E2A0,X    ; this works because of the strange
.C:c061  9D 38 E5    STA $E538,X    ; VIC-II framebuffer memory layout:
.C:c064  9D 78 E6    STA $E678,X    ;
.C:c067  9D C8 E8    STA $E8C8,X    ; 8 consecutive bytes form a block
.C:c06a  9D 08 EA    STA $EA08,X    ; of 8x8 pixels.
.C:c06d  9D E0 E8    STA $E8E0,X    ; The next 8x8 block is to the right
.C:c070  9D 20 EA    STA $EA20,X    ; of the previous one.
.C:c073  9D F8 E8    STA $E8F8,X    ; after 40 of these blocks, a new row
.C:c076  9D 38 EA    STA $EA38,X    ; starts.
.C:c079  CA          DEX
.C:c07a  10 DF       BPL .sq_loop

         ; draw vertical grid lines:
         ; -------------------------
.C:c07c  A9 40       LDA #$40       ; load vector with
.C:c07e  85 FC       STA $FC        ; start address of the
.C:c080  A9 E1       LDA #$E1       ; first grid line
.C:c082  85 FD       STA $FD
.C:c084  A2 20       LDX #$20       ; 32 line segments
.C:c086   .gv_loop1:
.C:c086  A0 00       LDY #$00       ; start offset at 0
.C:c088   .gv_loop2:
.C:c088  A9 18       LDA #$18       ; bit pattern for 2pixel wide line
.C:c08a  91 FC       STA ($FC),Y    ; store bit pattern in bitmap
.C:c08c  C8          INY
.C:c08d  98          TYA
.C:c08e  29 07       AND #$07       ; every 8 lines ...
.C:c090  D0 F6       BNE .gv_loop2
.C:c092  98          TYA        ; ... add 16 to offset to
.C:c093  69 10       ADC #$10       ; skip 2 columns
.C:c095  A8          TAY
.C:c096  CA          DEX
.C:c097  F0 13       BEQ .gov
.C:c099  8A          TXA
.C:c09a  29 03       AND #$03       ; every 4 line segments ...
.C:c09c  D0 EA       BNE .gv_loop2
.C:c09e   .gh:
.C:c09e  A5 FC       LDA $FC        ; ... add $140 (8 * 25) to vector
.C:c0a0  69 40       ADC #$40       ; to get one "row" down
.C:c0a2  85 FC       STA $FC
.C:c0a4  A5 FD       LDA $FD
.C:c0a6  69 01       ADC #$01
.C:c0a8  85 FD       STA $FD
.C:c0aa  D0 DA       BNE .gv_loop1

         ; draw vertical grid line endings:
         ; --------------------------------
.C:c0ac   .gov:
.C:c0ac  A9 18       LDA #$18
.C:c0ae  A2 02       LDX #$02       ; every ending is 3 pixels high
.C:c0b0   .gov_loop:
.C:c0b0  9D 05 E0    STA $E005,X    ; store at different offsets
.C:c0b3  9D 1D E0    STA $E01D,X    ; in bitmap, see explanation
.C:c0b6  9D 35 E0    STA $E035,X    ; for squares above
.C:c0b9  9D 4D E0    STA $E04D,X
.C:c0bc  9D 40 EB    STA $EB40,X
.C:c0bf  9D 58 EB    STA $EB58,X
.C:c0c2  9D 70 EB    STA $EB70,X
.C:c0c5  9D 88 EB    STA $EB88,X
.C:c0c8  CA          DEX
.C:c0c9  10 E5       BPL .gov_loop

         ; draw horizontal grid lines:
         ; ---------------------------
.C:c0cb  A9 0B       LDA #$0B       ; load vector with
.C:c0cd  85 FC       STA $FC        ; start address of the
.C:c0cf  A9 E0       LDA #$E0       ; first grid line
.C:c0d1  85 FD       STA $FD
.C:c0d3  A2 20       LDX #$20       ; 32 line segments
.C:c0d5   .gh_loop1:
.C:c0d5  A0 00       LDY #$00       ; start offset at 0
.C:c0d7   .gh_loop2:
.C:c0d7  A9 FF       LDA #$FF       ; all bits set for horizontal lines
.C:c0d9  91 FC       STA ($FC),Y    ; store bit pattern in bitmap
.C:c0db  C8          INY
.C:c0dc  98          TYA
.C:c0dd  29 01       AND #$01       ; every other line ...
.C:c0df  D0 F6       BNE .gh_loop2
.C:c0e1  98          TYA
.C:c0e2  69 06       ADC #$06       ; ... add 6 to offset to get to the
.C:c0e4  A8          TAY        ; next block
.C:c0e5  CA          DEX
.C:c0e6  F0 13       BEQ .goh
.C:c0e8  8A          TXA
.C:c0e9  29 07       AND #$07       ; every 8 line segments ...
.C:c0eb  D0 EA       BNE .gh_loop2
.C:c0ed  A5 FC       LDA $FC        ; ... add $3C0 (8 * 75) to vector
.C:c0ef  69 C0       ADC #$C0       ; to get three "rows" down
.C:c0f1  85 FC       STA $FC
.C:c0f3  A5 FD       LDA $FD
.C:c0f5  69 03       ADC #$03
.C:c0f7  85 FD       STA $FD
.C:c0f9  D0 DA       BNE .gh_loop1

         ; draw horizontal grid line endings:
         ; ----------------------------------
.C:c0fb   .goh:
.C:c0fb  A9 1F       LDA #$1F       ; bit pattern for 5 pixel wide line end
.C:c0fd  A2 01       LDX #$01       ; 2 pixels high
.C:c0ff   .goh_loop:
.C:c0ff  9D 03 E0    STA $E003,X    ; store at different offsets ...
.C:c102  9D C3 E3    STA $E3C3,X
.C:c105  9D 83 E7    STA $E783,X
.C:c108  9D 43 EB    STA $EB43,X
.C:c10b  49 E7       EOR #$E7       ; switch to right line end
.C:c10d  9D 4B E0    STA $E04B,X    ; and store ...
.C:c110  9D 0B E4    STA $E40B,X
.C:c113  9D CB E7    STA $E7CB,X
.C:c116  9D 8B EB    STA $EB8B,X
.C:c119  49 E7       EOR #$E7       ; switch back to left line end
.C:c11b  CA          DEX
.C:c11c  10 E1       BPL .goh_loop

         ; setup hardware to show graphics:
         ; --------------------------------
.C:c11e  A9 94       LDA #$94       ; select top bank for VIC-II
.C:c120  8D 00 DD    STA $DD00      ; address space ($C000 - $FFFF)
.C:c123  A9 3B       LDA #$3B       ; activate hires bitmap mode
.C:c125  8D 11 D0    STA $D011
.C:c128  A9 3D       LDA #$3D       ; select $0c00 for start of bitmap
.C:c12a  8D 18 D0    STA $D018      ; colors, $2000 for start of bitmap
.C:c12d  A9 01       LDA #$01       ; set border color to white
.C:c12f  8D 20 D0    STA $D020
.C:c132   .hl_end:
.C:c132  D0 FE       BNE .hl_end    ; --- and never come back (loop)

C++ using SFML, 708 706 685 bytes

-23 bytes thanks to Zacharý

#define V =RectangleShape({6.f,300.f});r
#define H =RectangleShape({300.f,6.f});r
#define S(a,b).setPosition(a,b);
#define D(c,d)a.setPosition(c,d);w.draw(a);
using namespace sf;int main(){RenderWindow w(VideoMode(300,300),"");RectangleShape r[8];r[0]V[1]V[2]V[3]V[4]H[5]H[6]H[7]H[0]S(-3,0)r[1]S(97,0)r[2]S(197,0)r[3]S(297,0)r[4]S(0,-3)r[5]S(0,97)r[6]S(0,197)r[7]S(0,297)CircleShape a(40);a.setFillColor(Color::Black);while(w.isOpen()){Event e;while(w.pollEvent(e))if(e.type==Event::Closed)w.close();w.clear(Color::White);for(int i=0;i<8;++i){r[i].setFillColor(Color(128,128,128));w.draw(r[i]);}D(110,10)D(210,110)D(210,210)D(110,210)D(10,210)w.display();}}

Open a window where you see that :

SFML Displaying the hacker logo

Window is 300x300, so grid boxes are 100x100, and the dot have a 40 pixel radius, so the number of covered pixels is 40*40*3.14 ( something like 5024 ). So it respects the 40%-80% area filling rule.

If you want to run it by yourself, you should add this line : w.setFramerateLimit(60), to avoid your computer to heat up

  • \$\begingroup\$ IIRC, you don't need a space between your macros and the definitions in this case. I'll work on extreme macro abuse right now. \$\endgroup\$
    – Adalynn
    Sep 4, 2017 at 17:50
  • \$\begingroup\$ @Zacharý I can for S and D, but not for V and H \$\endgroup\$ Sep 4, 2017 at 17:57
  • \$\begingroup\$ Here's what I got, because when I tested that macro-equal-thing on g++ (albeit with a different program) it worked, so you may have to change a few things here and there for it to work in MSVC: pastebin.com/0uTHTc4Q \$\endgroup\$
    – Adalynn
    Sep 4, 2017 at 18:02

TikZ + TeX (plain TeX) 86 83 bytes

\input tikz\def~{)circle()(}\tikz\filldraw[step=2]grid(6,6)(,~3,~5,~5,3~3,5~,);\bye

Try online


I recently found out that plain TeX saves you lots of bytes when compared to LaTeX. Started this one from scratch.

  • \input tikz loads the TikZ-library
  • \def~{)circle()(} defines the single-character-macro ~ (~ is the only active character!) as shorthand for some text. This macro does not need any argument to be supplied. Note that the circle has a radius of 1 if we do not supply an argument.
  • \tikz starts the picture
  • \filldraw draws the grid and fills the circles at the same time
  • [step=2] leaves, by default, 2 units of space between gridlines, cf. here
  • grid(6,6) produces the 3x3 grid
  • (,~3,~5,~5,3~3,5~ paints the circles by using the ~-macro and, in the end, opens another co-ordinate with the last use of ~. Note that, whenever the digit 1 could've been supplied in a co-ordinate entry, I just left it out. This happened three times, with (1,1), (3,1), and (5,1).
  • ,) completes this co-ordinate. It becomes, in total, (,) which is equivalent to (1,1), see above, but does not have any effect on the output.
  • ; ends the filldraw command. We could leave it out if we surrounded everything between \tikz and \bye with curly braces but this would be two bytes more resulting in a grand total of one byte more.
  • \bye ends the TeX document.

What about GRAY?

This is a little tricky but I believe that rgb(x,x,x) with 0≤x≤255 are 256 shades of gray. Basically, black is the darkest gray available.


TeX Output


Applesoft Basic, 405 291 bytes

1hgr:hcolor=3:fori=0to123:hplot0,i to123,i:next
2hcolor=0:fori=18to84step22:hplot18,i to84,i:hploti,18toi,84:next

0data... locates the circles. 1hgr... draws white background. 2hcolor... draws grid. 3for..read.. gets data & calls the circle subroutine. (.5 is added at various points because of quirky Apple II drawing logic). 8for... to 9..return draws circles. (circle code adapted from hoist-point.com). Verified at https://www.calormen.com/jsbasic/


Postscript (72 bytes)

00000000: 924e 337b 924e 337b 3088 0034 2034 9281  .N3{.N3{0..4 4..
00000010: 3420 3092 ad7d 9283 924d 3020 3492 ad7d  4 0..}...M0 4..}
00000020: 9283 924d 337b 3188 0132 2032 9280 3420  ...M3{1..2 2..4
00000030: 3092 ad7d 9283 327b 88fc 3492 ad31 8801  0..}..2{..4..1..
00000040: 3220 3292 807d 9283                      2 2..}..

Text version:

gsave 3{gsave 3{0 0 4 4 rectstroke 4 0 translate}repeat grestore 0 4 translate}repeat grestore 3{1 1 2 2 rectfill 4 0 translate}repeat 2{-4 4 translate 1 1 2 2 rectfill}repeat

More readable text version:

/R {1 1 2 2 rectfill}def
3 {gsave 3 {0 0 4 4 rectstroke 4 0 translate} repeat grestore 0 4 translate} repeat
3 {R 4 0 translate} repeat
2 {-4 4 translate R} repeat
  • \$\begingroup\$ These don't render correctly for me. (And the last one looks rather different to the first two). \$\endgroup\$ Jun 6, 2022 at 12:04
  • \$\begingroup\$ it should be correct now \$\endgroup\$
    – Morgan H
    Jun 7, 2022 at 18:18
  • \$\begingroup\$ Yes, thanks! (I guess your interpretation for the gridline colors is that black is a shade of gray :-) \$\endgroup\$ Jun 8, 2022 at 8:47

Here is my answer in Tcl/Tk 17 lines, 582 Characters:

proc box {sz x y} {return [list [expr {$x*$sz+4}] [expr {$y*$sz+4}] [expr {($x+1)*$sz+4}] [expr {($y+1)*$sz+4}]]}
proc oval {sz x y} {return [list [expr {$x*$sz+($sz*0.8)+4}] [expr {$y*$sz+($sz*0.8)+4}] [expr {($x+1)*$sz-($sz*0.8)+4}] [expr {($y+1)*$sz-($sz*0.8)+4}]]}
set SIZE 100
canvas .c -width [expr {$SIZE*3+8}] -height [expr {$SIZE*3+8}]
pack .c
set y 0
foreach row {{0 1 0} {0 0 1} {1 1 1}} {
set x 0
foreach dot $row {
.c create rectangle {*}[box $SIZE $x $y] -fill {} -outline grey -width 1
if {$dot} {
.c create oval {*}[oval $SIZE $x $y] -fill black
incr x
incr y


enter image description here

  • 2
    \$\begingroup\$ The dots you are using only cover around 28% of the white fill of each cell, the requirement is to cover with the range 40-80%. (It may even cost less bytes to fill ~79% by removing the *0.8s) \$\endgroup\$ Jun 1, 2017 at 22:49
  • \$\begingroup\$ Comparing to my answer, yours is code-bowling! \$\endgroup\$
    – sergiol
    Mar 6, 2018 at 15:51

Processing, 221 bytes

There must be a way to bring this down, but its not jumping out at me. Maybe I can find something with coding some of the oft-used constants to variables, like 30, 15, 25, etc. Possibly it can be done with the rectMode(CENTER) taken out, but I think the coordinates will on average get longer, canceling out the savings.



//open the tiny window
//set the background to white
//all rectangle coordinates will be relative to their centers, rather than the top left corner
//5 rectangles for the glider. Rectangle because "rect" is shorter than "ellipse"
//set border color to gray. 99 because its noticeably gray without being a 3-digit number, saving a byte
//rectangles will be hollow from now on
//draw 4 boxes for the grid lines.  
//Draw a box around the left 1/3 of the window, then the right 1/3, 
//then the top 1/3, and lastly the bottom 1/3

Output: I can't do anything about the gray border in the image, that is the smallest Processing will let me open a window, but the actual image is in the center. If I were to save that frame of the image, it would only be the 30x30 bit in the middle.

tiny glider

  • 1
    \$\begingroup\$ Not bad! It doesn't break any rules, the gray around the image is technically a border! \$\endgroup\$
    – MD XF
    Jun 1, 2017 at 20:57

Bash + feh, 391 bytes

xxd -ps -r<<G|
bzcat|feh -

The hex string in the heredoc is a PNM image of the logo, compressed with BZip2 at level 9. xxd -ps -r converts it into binary data, and it is subsequently piped into bzcat (a BZip2 utility that decompresses data on STDIN and prints it on STDOUT). feh - opens the image viewer feh using data from STDIN.

feh - is two bytes shorter than the traditional ImageMagick display program.

If any bash wizards can help me figure out a way to use the raw binary data instead of having to encode it in hex (echo -ne wasn't working right), I'd be forever grateful.

Thanks to kundor for 2 bytes

  • \$\begingroup\$ Wow, that's pretty creative! \$\endgroup\$
    – MD XF
    Jun 1, 2017 at 18:52
  • \$\begingroup\$ You can get rid of the spaces around the pipes and << to save four bytes or so. \$\endgroup\$ Jun 1, 2017 at 22:49
  • \$\begingroup\$ you can put bzcat... right after the pipe and save a newline \$\endgroup\$
    – Zombo
    Jun 3, 2017 at 18:30
  • \$\begingroup\$ You can save 121 bytes by using base64 and removing the padding. First line becomes: base64 -d<<H|bzcat|feh -. \$\endgroup\$ Jun 5, 2017 at 1:43

Lua + LÖVE, 264 characters

g.setLineStyle("rough")function l.draw()g.setBackgroundColor(255,255,255)for i=0,8 do

Sample output:

Glider drawn with Lua and LÖVE

Lua + LÖVE, 241 characters

function l.draw()g.setBackgroundColor(255,255,255)for i=0,8 do

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 Lua and LÖVE - with anti-aliasing


imagegen, 167 154 55 bytes (non-competing)

Edit 2: Added grid draw function

Edit 1: Fixed bug where you needed spaces to separate rectangle fill functions. Removed those spaces


31x31 F^G910R013,3,5R023,13,5R03,23,5R013,23,5R023,23,5


To run, click the link above to the Github repository and read the usage section. After running imagegen, just paste the code into the console and hit enter. The program will generate an image to out.png in the same folder as the EXE.

Just started working on a new image generation golf language today to help me get used to C#. The score will continue to decrease as I add more features (and the answer will hopefully get less boring).


  1. Fill image with white background
  2. Draw gray grid
  3. Draw each black rectangle individually

Code explanation

  • 31x31 sets image size. If you leave this out it will default to 600x400
  • F^ Fills the image with the color '^'. If you look in ColorCodes.txt in the Github repository, you will see this corresponds to white. This fills the white background.
  • G910 Draws a grid of lines 10 pixels apart with the color '9' which corresponds to #999999 - gray. This draws the gray grid
  • R013,3,5,5 is the fill rectangle function. I use the color '0' (black), and it draws this rectangle at (13,3) with size 5x5.

This is still a major work in progress, just started a couple hours ago

  • 1
    \$\begingroup\$ Not bad, good luck on your language! +1 \$\endgroup\$
    – MD XF
    Jun 12, 2017 at 5:00

Javascript, 187 bytes (174+13) 205 bytes (192+13)

<canvas id=c>


a = 40,w = 80,
x = c.getContext `2d`;
c = (X, Y) => {
    x.arc(X * a + 20, Y * a + 20, 15, 0, 7);
c(1, 0), c(2, 1), c(0, 2), c(1, 2), c(2, 2);
i = 4;
while (i--) x.strokeRect((i&1)*a, (i&2)*20, w, w)
  • \$\begingroup\$ 191 bytes \$\endgroup\$
    – user72349
    Aug 27, 2017 at 15:29
  • \$\begingroup\$ @ThePirateBay nice! I could reduce even further to 187 \$\endgroup\$
    – Vitim.us
    Aug 27, 2017 at 17:08

Tcl/Tk, 173

pack [canvas .c -bg #FFF]
time {.c cr l [incr i 10] 10 $i 40 -f gray;.c cr l 10 $i 40 $i -f gray} 4
lmap x\ y {2 1 3 2 1 3 2 3 3 3} {.c cr o ${x}2 ${y}2 ${x}8 ${y}8 -f #000}

enter image description here

Tcl/Tk, 188

pack [canvas .c -bg #FFF]
lmap i {2 12 22 32} {.c cr l 2 $i 32 $i -f gray;.c cr l $i 2 $i 32 -f gray}
lmap x {13 23 3 13 23} y {3 13 23 23 23} {.c cr o $x $y [incr x 8] [incr y 8] -f #000}

hacker logo


HTML & CSS, 113 bytes

I started working on this version because of Octopus' similar answer.
I've mainly done away with excessive elements and replaced them with CSS-generated pseudo elements.

<table cellspacing=0 border><td><th><td><tr><td><td><th><tr><th><th><th

Here's another one of 95 bytes that makes use of x's instead of bullets

☐☒☐ ☐☐☒ ☒☒☒

  • \$\begingroup\$ Your 95-byte solution is invalid as the X's don't take up 40-80% of their boxes. \$\endgroup\$
    – Makonede
    Jun 11, 2022 at 16:29

Java 11 (OpenJDK), 310 bytes

First time golfing, I hope I got it right...

()->{new Frame(){public void paint(Graphics g){int x=20,y=40,z=60;g.fillOval(x,0,x,x);g.fillOval(0,y,x,x);g.fillOval(x,y,x,x);g.fillOval(y,y,x,x);g.fillOval(y,x,x,x);g.setColor(Color.gray);g.drawRect(0,0,z,z);g.drawRect(0,0,z,y);g.drawRect(0,0,z,x);g.drawLine(x,0,x,z);g.drawLine(y,0,y,z);}}.setVisible(2>1);};

Opens a window as small as the OS allows that can be dragged open. Also the image is partially hidden behind the window border:

enter image description here

Here's how it would look like without the border

enter image description here


Java 11 (OpenJDK), 265 bytes

This is just a golfed version of @mindoverflow's answer, full credit goes to him. The problem is just that I can't comment yet.

()->{new Frame(){public void paint(Graphics g){int x=20,y=40,z=60,i=3;g.fillOval(x,0,x,x);g.fillOval(y,x,x,x);for(;i-->0;g.fillOval(i*x,y,x,x));g.setColor(Color.gray);for(i=4;i-->1;g.drawRect(0,0,z,i*x));g.drawLine(x,0,x,z);g.drawLine(y,0,y,z);}}.setVisible(2>1);};

It looks just like @mindoverflow`s, but by wrapping a couple of method calls into for-loops you can save 45 bytes.

enter image description here


Java 10, 242 236 bytes

import java.awt.*;v->new Frame(){{add(new Panel(){public void paint(Graphics g){for(int i=9,t;i-->0;g.setColor(Color.BLACK),g.fillOval(t%3*10+1,t/3*10+1,8,8),g.setColor(Color.GRAY),g.drawRect(i%3*10,i/3*10,10,10))t=i>4?i:1;}});show();}}

-6 bytes thanks to @ceilingcat.

Screenshot of the actual 30x30 pixels result:

enter image description here

Screenshot of the ten times larger 300x300 result:

enter image description here


import java.awt.*;            // Required import for almost everything
v->                           // Method with empty unused parameter and Frame return-type
  new Frame(){                //  Create the Frame
   {                          //   In an inner code-block:
     add(new Panel(){         //    Add a Panel we can draw on:
       public void paint(Graphics g){
                              //     Overwrite its paint method:
         for(int i=9,t;i-->0  //      Loop `i` in the range (9, 0]:
             ;                //        After every iteration:
                              //         Set the color to black
              g.fillOval(     //         Draw a solid circle:
                t%3*10+1,,    //          At x-coordinate t%3*10 + 1
                t/3*10+1,     //          At y-coordinate t//3*10 + 1
                8,8),         //          Of size 8x8 pixels (80%)
                              //         Then change the color to gray
              g.drawRect(     //         Draw an open square:
               i%3*10,i/3*10, //          At x,y-coordinate i%3*10, i//3*10
               10,10))        //          Of size 10x10 pixels
           t=i>4?             //       If `i` is 5, 6, 7 or 8:
              i               //        Set `t` to `i`
             :                //       Else:
              1;}});          //        Set `t` to 1 instead
     show();}}                //    And afterwards show the Frame

05AB1E, 192 bytes


Try it online! Outputs as a plain PGM.

Output (enlarged)

Hacker Emblem

Actual output size is 30x30.

„P230D2•...•3в1»  # trimmed program
„P2               # push literal
   30             # push literal...
     D            # twice
      2           # push literal
             в    # push list of base-10 values of base...
            3     # literal...
             в    # digits of...
       •...•      # 427541225056090484779390842559962277535356179915664563570852766785644784557400927981185964800417173067134497361607731953969389383383710765821962940570130871145015821269287935868419374755244532042313674055574776583016673806369314382290002772542995095921556681406703587909310388486054711832330497506948107550678784337269482395576308349400348694552486117428881164944824595892240209460307603873442854698425661641130046746477556925533...
              1   # push literal
               »  # join stack by newlines, joining lists on the stack by spaces
                  # implicit output
  • 1
    \$\begingroup\$ does converting the dots to perfect squares help with compression? \$\endgroup\$
    – Razetime
    May 27, 2021 at 4:24
  • \$\begingroup\$ @Razetime I already noticed, thanks for pointing that out though! \$\endgroup\$
    – Makonede
    May 27, 2021 at 15:55

CSS+HTML, 31+95=126 bytes

This is a merge of the solutions from Octopus and Uriel. I figured Uriel solution could benefit from using instead of using div, and Octopus solution could benefit from using the border attribute instead of setting it in CSS.

So, in the spirit of xkcd/927 I made another answer instead of commenting to either of them.

<table cellspacing=0 border=1px><tr><td><td>•<td><tr><td><td><td>•<tr><td>•<td>•<td>•

  • \$\begingroup\$ "You will display the emblem with graphical output but no ASCII art." \$\endgroup\$
    – Vitim.us
    Aug 27, 2017 at 19:00

SVG, 487 449 355 301 Bytes

Compressed Version:

<svg><g id=g><path d=M1,1L1,13L13,13L13,1Z id=r fill=none stroke=gray /><use href=#r x=12 /><use href=#r x=24 /></g><use href=#g /><use href=#g y=12 /><use href=#g y=24 /><circle id=c cx=19 cy=7 r=5 /><use href=#c x=12 y=12 /><use href=#c x=-12 y=24 /><use href=#c x=0 y=24 /><use href=#c x=12 y=24 />

Special Thanks:

@Meyer - Thanks for taking off 54 bytes!

@ovs - Thanks for bringing up compliance issue with radius of circle

Uncompressed Version Code Snippet:

    <g id=g>
        <path d=M1,1L1,13L13,13L13,1Z id=r fill=none stroke=gray />
        <use href=#r x=12 />
        <use href=#r x=24 />
    <use href=#g />
    <use href=#g y=12 />
    <use href=#g y=24 />
    <circle id=c cx=19 cy=7 r=5 />
    <use href=#c x=12 y=12 />
    <use href=#c x=-12 y=24 />
    <use href=#c x=0 y=24 />
    <use href=#c x=12 y=24 />


CSS+HTML = 13+83 = 96 bytes

<table cellspacing=0 border><td><td>⬛<td><tr><td>⬛<td><tr><td>⬛<td>⬛<td>⬛

Thanks to @mbomb007

CSS+HTML = 38+83 = 121 bytes [No Unicode]




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

Tested on:

Chrome 72.0.3626.121

enter image description here

CSS+HTML = 38+87 = 125 bytes [No Unicode]




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

Tested on: Chrome 72.0.3626.121

enter image description here

  • \$\begingroup\$ Nice. How about this for 87 bytes? \$\endgroup\$
    – mbomb007
    Mar 14, 2019 at 19:58
  • \$\begingroup\$ @mbomb007 Nice. This is your version updated. Only 83 bytes. But I think it's against the rules Each grid-box in the grid will be the same size. \$\endgroup\$ Mar 15, 2019 at 8:26
  • \$\begingroup\$ Your first one does the exact same thing (see your first image), but this shorter version doesn't appear to be square, which is a requirement. \$\endgroup\$
    – mbomb007
    Mar 15, 2019 at 12:02

SVG/CSS, 700 bytes

<svg width=48 height=48 ><rect width=16 height=16 /><rect x=16 width=16 height=16 /><circle cx=24 cy=8 r=6 stroke=black stroke-width=1 fill=black /><rect x=32 width=16 height=16 /><rect y=16 width=16 height=16 /><rect x=16 y=16 width=16 height=16 /><rect x=32 y=16 width=16 height=16 /><circle cx=40 cy=24 r=6 stroke=black stroke-width=1 fill=black /><rect y=32 width=16 height=16 /><circle cx=8 cy=40 r=6 stroke=black stroke-width=1 fill=black /><rect x=16 y=32 width=16 height=16 /><circle cx=24 cy=40 r=6 stroke=black stroke-width=1 fill=black /><rect x=32 y=32 width=16 height=16 /><circle cx=40 cy=40 r=6 stroke=black stroke-width=1 fill=black /></svg>

  • 4
    \$\begingroup\$ Welcome to PPCG! I'm not an expert in SVG, but I'm fairly certain that you can remove some unnecessary bytes (indentation, plus the <-- something --> lines that appear to be comments). \$\endgroup\$
    – user45941
    Jun 4, 2017 at 1:26
  • \$\begingroup\$ Here is a golfed version at 700 bytes using svg and css. Feel free to edit it in. \$\endgroup\$
    – ovs
    Jun 5, 2017 at 11:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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