14
\$\begingroup\$

The International Code of Signals flag alphabet is used by ships for communication, particularly for static signals.

Your challenge is to write a program or function that will take a string from STDIN or as an argument, and display the corresponding text in the ICS flag alphabet. If your language does not display to the screen, saving to a file is acceptable.

Your program or function shall support letters A-Z in upper and lower case, plus Space and Newline. Behaviour with other characters is undefined.

The display shall be large enough to display capable of displaying at least 8 flags horizontally and 6 flags vertically. Behaviour is undefined if the right hand edge is reached before a newline is received, or if the message is too long to fit the display vertically.

The flag alphabet is as shown below (Roman letters are for reference only, they are not required in the output.)

enter image description here

Dimensions

There is no universally agreed standard for the dimensions of these flags, so for the purpose of this challenge the following shall apply:

Flags shall be 60x60 pixels, with a 30 pixel gap between them both horizontally and vertically.

The swallowtail cut on A and B shall be 15 pixels deep.

All other lines shall be horizontal, vertical, or at 45 degrees.

The features shall be located by dividing the flag into an imaginary NxN grid of side 3,4,5 or 6 squares. Refer to the above image, but for further clarification:

A,E,H,K, L and U are based on a 2x2 grid : width of each colour zone shall be 30pixels. Also the points of the diamond in F shall be halfway along each side of the flag.

J and T are based on a 3x3 grid: each band shall be 20 pixels.

P,N and S are based on a 4x4 grid. Also the diagonal lines of Y shall split the edges of the flag into 4.

C,D,R and X shall be based on a 5x5 grid. Bands and arms of crosses shall be 12 pixels wide.

G,W,M,V are based on a 6x6 grid. Bands of G and borders of W shall be 10 pixels wide. Arms of crosses on M and V shall cover the first and last 10 pixels of each edge of the flag, leaving triangle zones measuring 40 pixels along the long edge.

The circle of I shall be in the centre of the flag and have diameter 30 pixels.

An error of +/-1 pixel from the above text is permitted. If your language only supports scalable graphics, you may interpret "pixels" to mean "units."

Colours

Colours shall be red, white, blue, yellow and black as defined by your language or its documentation. If your language does not define colours, you may use the following: Red FF0000, White FFFFFF, Blue 0000FF, Yellow FFFF00, Black 0000000.

Background shall be grey (r,g and b channels equal, between 25% and 75% intensity.)

Scoring /Loopholes

This is codegolf. Shortest code in bytes wins.

Standard loopholes are disallowed.

No builtin or library functions for displaying flags may be used. Output shall be non-text (and in particular, unicode characters shall not be used to build up the flag shape.)

Example

JFK got
my VHS
PC
and XLR
web quiz

should produce the following

enter image description here

\$\endgroup\$
  • \$\begingroup\$ I'm not entirely sure what you mean by "The display shall be large enough to display at least 8 flags horizontally and 6 flags vertically", especially given that your test case shows an output which is only 5 flags tall. Is it just that answers must handle messages up to those dimensions and are not required to handle larger ones, or do you intend to require that all lines should be padded to at least 8 chars and all messages to at least 6 lines? \$\endgroup\$ – Peter Taylor Mar 5 '15 at 10:16
  • 1
    \$\begingroup\$ @PeterTaylor If your program or language is intelligent enough to resize the display according to the output, there is no need to pad the display to 8x6 if the output is smaller. The output shall be have a grey background and be rectangular (all lines padded to at least the length of the longest line.) \$\endgroup\$ – Level River St Mar 5 '15 at 10:27
15
\$\begingroup\$

CJam, 464 bytes

You thought CJam didn't have image manipulation functions? Well, you thought right! But I wasn't going to let that stop me.

"P3
690 690 4
"3a3*a690_@*a*qeuN/{0:U;{_'C<.5*:N;i[{XY+Z<[E8][9C]?XY<=}WWWW{XH<9F?}C{YC/[9FCF]=}{YC/3&9E?}{YH<9F?}{X29.5:R-zYR-z+H>FC?}{XA/1&9E?}{XH<FC?}{XR-_*YR-_*+F_*>E8?}{YK/(9F?}{XH<E9?}{XH<YH<^8E?}{XY+Z-A/XY-A/e&9F?}{XF/YF/^1&F9?}{XY<EC?}{XH-F/YH-F/|9F?}E{XHm6/YHm6/e&CE?}{XH-F/YH-F/|F9?}{XK/[CF9]=}{XH<YH<^FC?}{XY+Z-A/XY-A/e&FC?}{XR-zYR-ze>iA/[CF9]=}{XHm6/YHm6/e&F9?}{XY+F/1&CE?}]=:P~!!{60:Z{Z30:HYH-z-N*-{YV+_2$=XU+P2b1>4f*tt}fX}fY}*U90+:U;}/V90+:V;}/`"[]"-

This program outputs the image in the best way CJam can: as text that represents the image when saved as a PPM file. Don't even try running it with the online interpreter, by the way; you'll blow the stack. Run it with the Java interpreter and pipe the output to a file with a command like java -jar cjam-0.6.4.jar flags.cjam > flags.ppm. Once you've provided your input, send an EOF (may need to be immediately after a newline) with ctrl+D on Unix or ctrl+Z on Windows.

Sample

If it's really desired, I can try to paste the original ~3MB image source somewhere. But here's the result opened in GIMP and conerted to a PNG:

ABCDEFG
hijklmn
OPQRSTU
vwxyz z

flags_alphabet.png

Explanation

The image header, easily identifiable in the source, consists of the magic number, width, height, and maximum channel value. So the output is a 690*690 image (enough for 8*8 60px flags with 30px of spacing between them) with each R, G, and B value ranging from 0 to 4.

The image data is initialized as a 690*690*3 array filled with 3's, making the whole image light gray. Then the input is read, converted to uppercase, and split into lines. The lines are processed in a loop, incrementing the flag Y coordinate by 90 each iteration, and in each line, each character is processed in a loop, incrementing the flag X coordinate by 90 each iteration. Now the magic begins.

Each character is mapped to a flag's pixel function that, when called, returns the color of the pixel at the position (X, Y) on the flag. This is where most of the hard work went: concisely describing 26 images as mathematical functions. Each of these functions returns a color value from 8-15. This range takes advantage of the fact that, when converted to base 2, the resulting bit array can be interpreted as [1, R, G, B]. The first element can be removed and the rest multiplied by 4 to easily give a pixel value in the desired format that covers all the possible flag colors (as well as green, cyan, and magenta). It also works out nicely that there are one-character variables initialized to 10-15, and since varaibles don't need a space to syntactically separate them, any two colors besides black and blue can be entered next to each other without needing any spacing.

Once the function is retrieved, it's just a matter of iterating over both of X and Y from 0-60, calling the function at each step, and writing the result back to the image data array. An astute observer might notice that the color values returned by each flag function don't allow gray, though. So there's a bit of extra logic to skip spaces. But there are still the swallowtail cuts on 'A' and 'B'. So there's a bit of extra logic there, too. If the character value is less than 'C', a value is set such that the upper bound on the X loop varies correctly with respect to Y and the cut-out areas are never drawn.

Overall, I'm pretty happy with how this came out. It took a lot of work, but it was fun. Some flags don't perfectly match the reference image, but I think I got all the shapes to be within 1px of the target (if any are off by more than that, let me know and I'll fix them). And there's definitely still potential to optimize, as there's a fair amount of redundancy between the 26 flag functions.


Ineresting first attempt, 559 bytes

Altough I never quite finished this, I'll post it too, because it's pretty interesting. Instead of modelling each flag by a function of (X, Y) → color, flags are drawn as a composition of simple shapes. But I was worried about needing to write a substantial amount of rendering code for each different shape. After a lot of pondering, I realized I could render them all, with some clever overlapping and overdrawing, with just one pseudo-shape: all the points within a specified distance of a specified point, where the definition of "distance" is variable. Chessboard distance gives a square, Manhattan distance gives a diamond, and Euclidean distance gives a circle. This meant every shape had the same five parameters (color, distance mode, x, y, and max distance) and I only needed to write one shape data decoder and one rendering function with a small bit of distance mode logic.

"P3
690 690 4
"3a3*a690_@*a*qeuN/{0:U;{_'C<.5*:N;i[[8EX30:Q0Q9X60:ZQQCXQZQ]LLLL[F9TTQQ]Ca[9FTQ42QCTQ54QFTQ66Q9TQ78Q][E9TIQI9T42QI][9FTQZQ][FCXQQQ][E9T40QQET50QQ9TZQQET70QQ9T80QQ][FCTZQQ][E8YQQF][9FTQAQ9TQ9~Q][E9TZQQ][8ETTTQETZZQ][F9XQTK9XZQK9XQZK9XTQK][F4{4{JW^1&6*9+TJ)F*W)F*F}fJ}fW][CEX0ZZ][9FTQQF]Ea[E[TZ]_m*{CT@~24}/][F9TQQF][9FTAQQCT9~QQ][FCTTTQCTZZQ]C9$1>9a/Fa*+[9FTQQKCTQQA]9 6$1>Ca/Fa*+[C7{7\-_1&2*C+X@TT@F*}/]]=_!!{([TQQQ]+\+}*5/{~:R;.5-:H;.5-:G;:M;2b1>4f*:O;Z{ZQWQ-z-N*-{JG-{zM_!+#}:P~WH-PM{+}{e>}?RP<{WV+_2$=JU+Ott}*}fJ}fW}/U90+:U;}/V90+:V;}/`"[]"-
\$\endgroup\$
  • 1
    \$\begingroup\$ Excellent, this is the kind of creative answer I was looking for. Will try to run it later. \$\endgroup\$ – Level River St Mar 6 '15 at 9:25
  • 1
    \$\begingroup\$ This is quite possibly the longest CJam code I've ever seen. Nice work though, +1. \$\endgroup\$ – Alex A. Mar 6 '15 at 15:32
  • \$\begingroup\$ Again, CJam appears to save the day. \$\endgroup\$ – ASCIIThenANSI Apr 15 '15 at 18:47
  • 9
    \$\begingroup\$ Unfortunately, it's a federal offense to post CJam code longer than 200 bytes. I'm gonna have to take you into custody. \$\endgroup\$ – Deusovi Jan 3 '16 at 20:03
2
\$\begingroup\$

PHP, 811 bytes

function f($s){echo"<body bgcolor=#ccc>";$z=split("\n",gzinflate(base64_decode("vVfNasMwDL7vKQK7xlT+iaHQ9LDTLnuIQus6ENhgxS19+kmO0yRrkhbqGIxtyV8sWbIkZ/Prjtm52p9suYbMHqqjPdHMVYfzx/elhBzyNbXtZoXQ7dvm+Q9+dieb7csvZFkJToNlEq6Zqeq6fAcw2arDqCKXUPMCEYQicIc1xmNfUkBDzXgQkpMQ3W0PEGF7fz49dT7IuSCQ1APJ5h9IKAIhdGn1jIHH6oUzvCpZzhtGjoDiePzuzAPJEkG1JPk1uw29G5rC7pxAvAFxuHqd+nQxpCP65S4gR6wzAkphE4rPHfbYaAueky59BrmrZ4wU0Ss8SES/pCNugMduiBSYs25oJTeBSYNMbHO6+bUg22PPhA8E5LCWhT3SFBjEwxaWiOMYD1+FtZSZxateEAZ7pvsEL7w1aQxD3HxLcmayfNA9ZeXzcdteJLm0H5ZITzAwolDkXeGwVAvlSzUOSDDkMRqRxDkuLquVecbKMRKFaESLSYOMg4b6qVHQMnkMns5jyZLBAnksRehirQWrwClEqakDNrqKpjqKpZ8K5rVYTFE56ZmCyT68KinJX+n/puFpyHXg4RRLwg1oW6YipqfimfJTt6/c6XIv6Tnc/HxNXIj+a9nORdwN5Qa3qzvGHw==")));while($c=ord(ucfirst($s))){$s=substr($s,1);echo$c<32?'<br>':($c^32?$z[$c-64]:$z[0]);}}

The compressed blob contains SVG code for each of the 26 flags. A simple loop then extracts and outputs the SVG image corresponding to each character of the input.

Sample output for "This is\na test":

<body bgcolor=#ccc><svg width=90 height=90 viewBox=0,0,90,90><path d=M0,0h20v60h-20z fill=#f00 /><path d=M20,0h20v60h-20z fill=#fff /><path d=M40,0h20v60h-20z fill=#00f /></svg><svg width=90 height=90 viewBox=0,0,90,90><path d=M0,0h30v60h-30z fill=#fff /><path d=M30,0h30v60h-30z fill=#f00 /></svg><svg width=90 height=90 viewBox=0,0,90,90><path d=M0,0h60v60h-60z fill=#ff0 /><path d=M15,30a15,15,0,0,1,30,0a15,15,0,0,1-30,0z fill=#000 /></svg><svg width=90 height=90 viewBox=0,0,90,90><path d=M0,0h60v60h-60z fill=#fff /><path d=M15,15h30v30h-30z fill=#00f /></svg><svg width=90 height=90 viewBox=0,0,90,90></svg><svg width=90 height=90 viewBox=0,0,90,90><path d=M0,0h60v60h-60z fill=#ff0 /><path d=M15,30a15,15,0,0,1,30,0a15,15,0,0,1-30,0z fill=#000 /></svg><svg width=90 height=90 viewBox=0,0,90,90><path d=M0,0h60v60h-60z fill=#fff /><path d=M15,15h30v30h-30z fill=#00f /></svg><br><svg width=90 height=90 viewBox=0,0,90,90><path d=M0,0h30v60h-30z fill=#00f /><path d=M45,30l15-30h-30v60h30z fill=#fff /></svg><svg width=90 height=90 viewBox=0,0,90,90></svg><svg width=90 height=90 viewBox=0,0,90,90><path d=M0,0h20v60h-20z fill=#f00 /><path d=M20,0h20v60h-20z fill=#fff /><path d=M40,0h20v60h-20z fill=#00f /></svg><svg width=90 height=90 viewBox=0,0,90,90><path d=M0,0h60v30h-60z fill=#00f /><path d=M0,30h60v30h-60z fill=#fff /></svg><svg width=90 height=90 viewBox=0,0,90,90><path d=M0,0h60v60h-60z fill=#fff /><path d=M15,15h30v30h-30z fill=#00f /></svg><svg width=90 height=90 viewBox=0,0,90,90><path d=M0,0h20v60h-20z fill=#f00 /><path d=M20,0h20v60h-20z fill=#fff /><path d=M40,0h20v60h-20z fill=#00f /></svg>

(You can try it out at ideone, although it won't render the page for you.)

\$\endgroup\$

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.