You know, the problem with us Canadians is that sometimes, after a long day of moose hunting and dam repairing, we forget our way back to our cabins! Wouldn't it be great if our handy laptop (which, is always at our side), had some way to point us home? Well, it's been long told that, if you display a compass on your computer, it will be the brightest when pointed North. I'd like to test this out, but I need a compact program to take with me on my next trip, because my hard drive is already filled with maple syrup recipes (and those CANNOT go). So, your task is to design me a program which, when run, saves or displays an image of the following compass rose:

Compass rose

The letters may be in a different font. Remember, least is best, so lowest byte count wins!



  • Light purple: #9999FF
  • Gray: #E5E5E5

Lengths and Angles

Rose specifications

  • Angle a = 45°
  • Angle b = 90°
  • Length c = 250 units
  • Length d = 200 units
  • Length e = 40 units
  • Length f = 45 units


  • The text may be in any appropriate font, where appropriate denotes that it is readable to the average, educated human being.
  • The text must be 3 units away from the spikes at its closest point, must not touch the rose, and must be upright
  • If a line is drawn from the center of the rose, through the end point of the spike and beyond, it should cross through the center of the text with a precision of +/- 2 units (the text must be centered along an axis a, where a extends from the middle of the page, through the end of the spike, and beyond)
  • Each character must be at least 15 units by 15 units, and have an x/y or y/x ratio of no more than 2:1 (no stretching – readability)
  • The dim circle passing through the longer spikes and text closest to the middle on the reference image is not to be drawn.
  • The image must be square, and at least 400px by 400px
  • A compressed image within the source is disallowed
  • A unit must be at least 1 pixel
  • 2
    \$\begingroup\$ When you say "maple syrup recipes", do you mean recipes to make maple syrup, or recipes to make stuff out of maple syrup? Because I can't quite imagine they'd be the former... \$\endgroup\$
    – Joe Z.
    Jan 22, 2015 at 4:26
  • 3
    \$\begingroup\$ @JoeZ. Both, obviously ... (; \$\endgroup\$
    – globby
    Jan 22, 2015 at 4:35

6 Answers 6


HTML + CSS, 487 + 189 = 676

The compass rose is constructed from CSS borders using the triangle technique and some basic transformations. The letters are just given fixed positions, so that turned out quite long :/

The snippet below is scaled down so that it all fits. You can check out the JSFiddle here. Also, I'm not sure how well the letters will line up on different browsers (with different fonts, default styles, etc.).

html{transform:scale(0.2)}body{margin:5em}hr{margin:0;float:left;border:250px solid transparent;border-right:58px solid #E5E5E5;border-bottom:58px solid #9999FF}a{position:fixed;width:616px;font-size:4em}#a{transform:rotate(90deg)}#b{transform:rotate(270deg)}#c{transform:rotate(180deg)}#d{transform:rotate(45deg)scale(.8)}#n{top:20px;left:365px}#e{top:356px;left:700px}#s{top:700px;left:370px}#w{top:356px;left:10px}#N{top:150px;left:550px}#E{top:560px;left:550px}#S{top:560px;left:140px}#W{top:150px;left:140px}
<a id=n>N</a><a id=e>E</a><a id=s>S</a><a id=w>W</a><a id=N>NE</a><a id=E>SE</a><a id=S>SW</a><a id=W>NW</a><a id=d><hr><hr id=a><hr id=b><hr id=c></a><a><hr><hr id=a><hr id=b><hr id=c></a>

  • \$\begingroup\$ It seems as though there's a small gray box around the middle, which has rendered the compass unusable. Is there any chance you could fix that? \$\endgroup\$
    – globby
    Jan 21, 2015 at 19:07
  • 1
    \$\begingroup\$ @globby it doesn't show up for me. Could you post a screenshot? \$\endgroup\$
    – grc
    Jan 21, 2015 at 22:55
  • \$\begingroup\$ imgur.com/dYQoLcM,sSrR94O Using Mozilla Firefox 35.0 on Windows 8.1 \$\endgroup\$
    – globby
    Jan 22, 2015 at 0:02
  • \$\begingroup\$ @globby that might just be an effect of the scaling. Does it happen on the full-sized JSFiddle? \$\endgroup\$
    – grc
    Jan 22, 2015 at 7:43

Processing 2 - 636

A quick solution that just draws all the triangles using the processing triangle method and then places the letters at their tips.

int s,h,m,b,n,t;void setup(){s=400;h=s/2;b=125;t=71;n=32;m=28;size(s,s);noStroke();fill(229);t(h-t,h-t,h-m,h);t(h-t,h+t,h,h+m);t(h+t,h-t,h,h-m);t(h+t,h+t,h+m,h);fill(#9999FF);t(h-t,h-t,h,h-m);t(h-t,h+t,h-m,h);t(h+t,h-t,h+m,h);t(h+t,h+t,h,h+m);t(h-b,h,h-n,h-n);t(h+b,h,h+n,h+n);t(h,h-b,h+n,h-n);t(h,h+b,h-n,h+n);fill(229);t(h-b,h,h-n,h+n);t(h+b,h,h+n,h-n);t(h,h-b,h-n,h-n);t(h,h+b,h+n,h+n);fill(color(0));text("NW",h-t-14,h-t-2);text("NE",h+t+2,h-t-2);text("SW",h-t-14,h+t+10);text("SE",h+t,h+t+10);text("N",h-5,h-b-5);text("S",h-5,h+b+12);text("E",h+b+2,h+5);text("W",h-b-14,h+5);}void t(int a,int b,int c,int d){triangle(h,h,a,b,c,d);}

enter image description here

you can get processing here


PHP, 628 bytes

added a few linebreaks for convenience.


Run with -r. Creates a file n.png with the image; unit is 2 pixels.

I must admit I found the coords for the winds by trial & error, and they are probably a bit off. Will do the calculations soon; but I promise: they won´t change the byte count.
Had my fun for now excavating my trignonometry and struggling with imagecopy ... what a sissy!

on golfing: not many tricks; but these few saved a lot:

  • Assigning function names and two of the values to variables probably had the largest impact.
    I didn´t even count before I replaced the function names.
  • The magic with the array + operator gave 42 bytes.
  • Writing a file instead of sending the image to the browser saved 27 bytes.
  • Moving assignments to the first usage of the variables gave a few more.

PHP North Star


// create images and allocate colors
$h=$c($w=250,$w);   // helper image - just as large as needed or imagecopy will screw up 
$i=$c(530,533);     // main image

$a($h,$f=255,$f,$f);    // white is 0
$a($i,$f,$f,$f);    // must be assigned to both images
$a($h,229,229,229); // grey is 1
$a($h,153,153,$f);  // purple is 2

// draw the south-east quadrant
// small triangle purple first
// point 3: 0.8*e *2
// point 1: center
// point 2: a=45 degrees, d=200 units
    141,141,// d/sqrt(2)=141.421356
// small triangle grey

// large triangles
    57,57   // e*sqrt(2)=56.5685424949


// create rose
$c($i,$h,263,267,0,0,$w,$w);            // copy quadrant to main image (SE)
$c($i,$r($h,90,0),263,17,0,0,$w,$w);    // rotate quadrant and copy again (NE)
$c($i,$r($h,180,0),13,17,0,0,$w,$w);    // rotate and copy again (NW)
$c($i,$r($h,270,0),13,267,0,0,$w,$w);// rotate and copy a last time (SW)

// add circle
#imageellipse($i,263,267,500,500,2);    // grey is now 2: imagecopy shuffled colors

// add names
$s($i,5,259,  0,N,3);   // 5 is actually the largest internal font PHP provides
$s($i,5,259,518,S,3);   // unassigned colors are black
$s($i,5,  0,259,W,3);


// output

Java 8, 756 bytes

import java.awt.*;v->new Frame(){void t(Graphics g,String s,int x,int y){g.drawString(s,x,y);}public void paint(Graphics g){g.setFont(new Font("Hei",0,30));t(g,"N",289,80);t(g,"E",553,341);t(g,"S",290,605);t(g,"W",20,341);t(g,"NE",434,186);t(g,"SE",437,496);t(g,"SW",120,498);t(g,"NW",121,186);g.setColor(new Color(229,229,229));g.fillPolygon(new int[]{300,346,442,390,550,390,442,346,300,254,158,210,50,210,158,254},new int[]{80,240,188,284,330,376,472,420,580,420,472,376,330,284,188,240},16);g.setColor(new Color(153,153,255));g.fillPolygon(new int[]{300,158,254,244,50,300,158,210,244,300,300,442,346,356,550,300,442,390,356,300},new int[]{330,188,240,274,330,330,472,376,386,580,330,472,420,386,330,330,188,284,274,80},20);}{setSize(600,630);show();}}


enter image description here


Code explanation:

import java.awt.*;          // Required import for Frame, Graphics, Font, and Color
v->                         // Method with empty unused parameter and Frame return-type
  new Frame(){              //  Create a new Frame
    void t(Graphics g,String s,int x,int y){
                            //   Create a temp method to reduce bytes:
      g.drawString(s,x,y);} //    To draw the given text at the given coordinate
    public void paint(Graphics g){
                            //   Overwrite the Frame's default paint method:
      g.setFont(new Font("Hei",0,30));
                            //    Set the Font to size 30
                            //    (I've used Font "Hei" here, but "Kai" could be used as
                            //     well for the same byte-count)
      t(g,"N",289,80);      //    Draw the text "N"
      t(g,"E",553,341);     //    Draw the "E"
      t(g,"S",290,605);     //    Draw the "S"
      t(g,"W",20,341);      //    Draw the "W"
      t(g,"NE",434,186);    //    Draw the "NE"
      t(g,"SE",437,496);    //    Draw the "SE"
      t(g,"SW",120,498);    //    Draw the "SW"
      t(g,"NW",121,186);    //    Draw the "NW"
      g.setColor(new Color(229,229,229));
                            //    Change the color to grey
                            //    (the default color was black, which is why we started
                            //     with the texts)
      g.fillPolygon(new int[]{300,346,442,390,550,390,442,346,300,254,158,210,50,210,158,254},new int[]{80,240,188,284,330,376,472,420,580,420,472,376,330,284,188,240},16);
                            //    Draw the 8-pointed star
      g.setColor(new Color(153,153,255));
                            //    Change the color to light purple
      g.fillPolygon(new int[]{300,158,254,244,50,300,158,210,244,300,300,442,346,356,550,300,442,390,356,300},new int[]{330,188,240,274,330,330,472,376,386,580,330,472,420,386,330,330,188,284,274,80},20);}
                            //    Draw a single shape as explained below
    {                       //   In an inner code block:
      setSize(600,630);     //    Set the size of the Frame
      show();}}             //    And show the Frame


Although Java has ways to draw based on rotations, it would increase the byte-count substantial in comparison to this straight-forward approach. There is however one main disadvantage about using this shorter approach: I have to calculate all \$x,y\$-coordinates manually..
So, here's how I did that:

I first used the units as is, since that was easier to calculate with. I've put the center at position \$150,150\$ and started calculating from there.

1) Calculate the coordinates of the tips of the star at N/E/S/W:

This is not too hard. With the center at \$150,150\$ and \$\frac{\color{red}{c}}{2} = 125\$, we'll have the following points:


2) Calculate the coordinates of the tips of the star at NE/SE/SW/NW:

Again, we know the center is at \$150,150\$ and we also know \$\frac{\color{blue}{d}}{2}=100\$. We can make a triangle calculation with the angles being 90, 45, and 45 like this:

enter image description here

(where \$m\$ are the sides \$b\$ and \$c\$ in the triangle above)

Knowing the \$n\$, we have the following points:


3) Calculate the coordinates of the points between the center and the NE/SE/SW/NW tips:

We again know the center \$150,150\$ and also \$\color{violet}{e}=40\$, so we can make a similar calculation as in step 2:


And use that to calculate the points:


4) Calculate the coordinates of the remaining points:

Now all that's left are the points at the concaved intersection of the edges of the star, which are circled in red here:
enter image description here

Since we know the center \$150\$ and \$\color{lightblue}{f}=45\$, a portion of these coordinates aren't hard to calculate. The other part of the coordinates requires some calculations, though..

enter image description here

In the picture above, we know the following things beforehand:

  • Red line: \$\frac{\color{red}{c}}{2}=125\$
  • Both orange lines: \$n=\frac{40}{2}\sqrt{2}=28.284\dots\$

And what we want to calculate is the thick vertical blue line of the small purple triangle.

We start with the horizontal line of the larger green triangle:

Using what we know now, we can calculate the black angle of the large green triangle as follows:


Then we can calculate the light blue angle of the small purple triangle:


As well as the horizontal line of the small purple triangle:


Which we can then both use to calculate the height of the thick blue line of the small purple triangle:


After which we can finally calculate the final coordinates of these red dots, using the center and the points we've calculated in step 2:
enter image description here


We now have all the coordinates of the points we need, so we can draw the shape on the screen. We do this with the Graphics#fillPolygon(int[],int[],int)-method, which takes two integer-arrays for all \$x\$- and \$y\$-coordinates respectively, as well as an integer being the amount of points. The grey star is therefore drawn using the following \$x,y\$-coordinates:

enter image description here

We then draw a single shape for the light purple parts, and the following \$x,y\$-coordinates:

A quarter of this shape goes from the center to point \$NW\$; then to point \$NW_N\$; then \$NW_{center}\$; then \$W\$; and then back to the center again:

enter image description here

And the entire shape is drawn by continuing in a similar fashion.

After that I've doubled everything, because the challenge description states the square should be at least 400 by 400 pixels, and in addition all \$y\$-coordinates are increased by \$30\$, because we draw directly on the frame and we still have the Window-bar at the top to consider (outside codegolf you would add a Panel to the Frame, and draw on that, but drawing directly on the Frame is also possible and -in this case- 1 byte shorter ¯\_(ツ)_/¯).

And finally we add the text, for which no calculations are used. In the used Font the letters aren't monospace (W is for example larger than S), and in Java everything is drawn from the top-left \$x,y\$-coordinate, so we can't really make any smart calculations here tbh. I've just added some temporary red lines going beyond the points and manually adjusted the text positions a bit:

enter image description here

If you think they aren't correct, they can be moved slightly by adjusting the coordinates, without changing the byte-count.
For those curious, here are the adjustments made to the coordinates of the tips to position the texts:

\$N=300-11, 80\$

And well, that's it. Thank you for listening to my TED talk about drawing a compass in Java. :)


R, 877 850 813

Lot's of room to golf this I suspect, but I wanted to get something up to see if I managed to comply with the rules.

Edit: Lost a few cleaning up around the polygon creation, gained a few removing outlines

a=45;b=90;c=125;e=40;h=c(0,0,b,a,a,0,a,b)*pi/180;i=c(0,c,c,100,e,a,(2*a^2)^.5,a);x=i*sin(h);y=i*cos(h);q=x[6:7];r=x[7:8];s=x[2:3];t=x[c(5,5)];u=y[6:7];v=y[7:8];w=y[2:3];z=y[c(5,5)];m=(s-t);n=(w-z);o=(q-r);p=(u-v);i=((q*v-u*r)*m-o*(s*z-w*t))/(o*n-p*m);x=c(x,i)[c(1,2,5,1,3,5,5,4,10,5,4,9)];y=c(y,rev(i))[c(1,2,5,1,3,5,5,4,10,5,4,9)];png("1.png",400,400);par(mar=rep(0,4));a=c(-200:200);plot(a,a,type="n");for(b in 0:3){for(i in(0:3)*3+1){a=c(1,1,1,-1,-1,-1,-1,1);polygon(x[(i):(i+3)]*a[b*2+1],y[(i):(i+3)]*a[b*2+2],border=NA,col=c("#9999FF","#E5E5E5")[(i%%6%/%4+b%%2)%%2+1]);}};for(i in 1:4){a=c("N","NE","E","SE","S","SW","W","NW");b=a[i*2-1];c=a[i*2];o=c(1,1,-1,-1,1);n=o[i+1];m=o[i];e=c(5,2)[i%%2+1];text((x[e]+(11*abs(i%%2-1)))*m,(y[e]+(12*i%%2))*n,b,cex=1.8);text((x[8]+10)*m,(y[8]+12)*n,c,cex=1.8)};dev.off()

This produces the following png image

enter image description here

A bit of an explanation of what I'm doing

h=c(0,0,b,a,a,0,a,b)*pi/180;            # angles to known vertices in one quadrant
i=c(0,c,c,100,e,a,(2*a^2)^.5,a);        # distances to known vertices
x=i*sin(h);                             # calculate x ordinates
y=i*cos(h);                             # calculate y ordinates
q=x[6:7];                               #-----------------------
r=x[7:8];                               #
s=x[2:3];                               # Get the lines required 
t=x[c(5,5)];                            # to determine the vertex
u=y[6:7];                               # for the minor pointers
v=y[7:8];                               #
w=y[2:3];                               # 
z=y[c(5,5)];                            #------------------------ 
m=(s-t);                                # Intersect them
n=(w-z);                                # to give coordinate.
o=(q-r);                                # Just calculate the x's
p=(u-v);                                # as they can be reversed
i=((q*v-u*r)*m-o*(s*z-w*t))/(o*n-p*m);  #------------------------
x=c(x,i)[c(1,2,5,1,3,5,5,4,10,5,4,9)];      # X Triangle groups
y=c(y,rev(i))[c(1,2,5,1,3,5,5,4,10,5,4,9)]; # Y Triangle groups
png("1.png",400,400);                   # Set output to png
par(mar=rep(0,4));                      # Make margins 0
plot(a,a,type="n");                     # Start plot
for(b in 0:3){for(i in(0:3)*3+1){       # draw polygons, alternating colors and drawing all quadrants
for(i in 1:4){                          # Add text to compass points for each quadrant
dev.off()                               # Close PNG

Mathematica, 347 bytes



p = q = {{0, 0}, {0, 125}, 40 {1/Sqrt[2], 1/Sqrt[2]}}; (*defining points*)
q[[3, 1]] *= -1;                                       (*for triangles*)
m = 5 p[[3]]/2;
s = u = {{0, 0}, m, {32, 0}};
u[[3]] = {0, 32};
r = {{0, 1}, {-1, 0}};                                 (*-pi/2 rotation matrix*)

t = Polygon[#] &;
z = MatrixPower[r, #] &;
a[v_] := Table[t[z[n].# & /@ v], {n, 4}];              (*rotate the sets of points*)
                                                       (*four times*)

i = Table[Text[#[[j]], z[j].#2], {j, 4}] &;
G = RGBColor["#E5E5E5"];                               (*need to use this twice*)
                                                       (*so triangles overlap*)
                                                       (*properly so define a variable*)

Graphics[{i[{E, S, W, N}, {0, 130}], 
  i[{NE, SE, SW, NW}, 1.06 m], G, a[u], RGBColor["#9999FF"], a[s], 
  a[p], G, a[q]}]

N and E (base of the natural log) are both built-ins in Mathematica but as text E gets stylized into a lowercase font you see in the image but the problem doesn't quite say we can only use one font for all the text. If that is a requirement then replace E with "E" and I gain two bytes.

Sqrt[2] in Mathematica can be stylized into two characters, so if we count each Sqrt[2] as two characters then my new byte count is 339 instead of 349.

The image below is produced.



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.