# Translate ASCII text to braille

Write a program that translates ASCII text to braille output. Requirements:

• Input may come from stdin, command line, or some other external input source.
• Output should be recognisable as braille, the form of output is up to you. An example would be o for a raised dot and . for a non-raised dot. Textual pattern representation such as 1-3-4 is not acceptable. Long line wrapping is not required.
• Only the 26 alphabet characters and space are required for a minimal solution. All input characters not supported by your solution should be ignored.

Scoring is by number of characters in the source code. Penalties and bonuses are:

• +50 penalty for using Unicode braille characters as output.
• -50 bonus for supporting capitals, numbers, and punctuation.
• -200 bonus for supporting ligatures and one-letter contractions from English (Grade-2) Braille. (Will make this a separate challenge since it's quite a different problem.)

Sample invocation and output (minimal solution):

$braille Hello world o . o . o . o . o . . . . o o . o . o . o o o o . o o . o . . o . . o o . o o o o . . o . . . . o . o . o . . . . o o . o . o . . . • define "valiant attempt". Also, is line-wrapping required? – John Dvorak Jul 4 '14 at 2:20 • @JanDvorak: Thanks, updated question. – Greg Hewgill Jul 4 '14 at 2:23 • @GregHewgill Can you make the bonus for including capitals, numbers, and punctuation larger? Currently that's 26+10+12 = 48 extra characters, not much of a bonus (unless you compress the braille data) – qwr Jul 4 '14 at 4:48 • You could count bytes instead of characters and remove the penalty, the cost is about the same (@DigitalTrauma's first solution is 85 bytes). Edit: I just realized that would penalize languages like APL. It's up to you. – nyuszika7h Jul 4 '14 at 17:19 • Man... the penalty for unicode chars isn't big enough to make this interesting. I wanted to see how people were going to encode the braille set. – Almo Jul 4 '14 at 20:37 ## 11 Answers ## Python, 162 l=map((" a c,bif/e d:hjg'k m;lsp o n!rtq%12s. w -u x v z y"%'').find,raw_input().lower()) for i in 1,4,16:print' '.join('.o.o ..oo'[(n&i*3)/i::4]for n in l) Currently supports lowercase letters and some punctuation, but it's still a work in progress. Example:$ python braille.py
Hello, world!
o .  o .  o .  o .  o .  . .  . .  . o  o .  o .  o .  o o  . .
o o  . o  o .  o .  . o  o .  . .  o o  . o  o o  o .  . o  o o
. .  . .  o .  o .  o .  . .  . .  . o  o .  o .  o .  . .  o .

# Python - 90 75 + 50 = 125

Use lower case letters.

for l in input():
a=ord(l)-96
if a<0:a=0
print("⠀⠁⠃⠉⠙⠑⠋⠛⠓⠊⠚⠅⠇⠍⠝⠕⠏⠟⠗⠎⠞⠥⠧⠺⠭⠽⠵"[a],end="")

One-liner (thanks to ɐɔıʇǝɥʇuʎs)

for l in input():print("⠀⠁⠃⠉⠙⠑⠋⠛⠓⠊⠚⠅⠇⠍⠝⠕⠏⠟⠗⠎⠞⠥⠧⠺⠭⠽⠵"[max(0,ord(l)-96)],end="")
• Why not make it a one-liner? for l in input():print("⠀⠁⠃⠉⠙⠑⠋⠛⠓⠊⠚⠅⠇⠍⠝⠕⠏⠟⠗⠎⠞⠥⠧⠺⠭⠽⠵"[max(0,ord(l)-96)],end="") 75 characters. – ɐɔıʇǝɥʇuʎs Jul 4 '14 at 7:26
• @ɐɔıʇǝɥʇuʎs wow, I forgot about the max trick. Thank you – qwr Jul 4 '14 at 7:31
• You can save a char by just putting blanks for all non-letter characters: for l in input():print((" "*97+"⠁⠃⠉⠙⠑⠋⠛⠓⠊⠚⠅⠇⠍⠝⠕⠏⠟⠗⠎⠞⠥⠧⠺⠭⠽⠵")[ord(l)],end="") – xnor Jul 6 '14 at 17:09

# C, 269

#define C char
#define O*p++=(*t&1)*65+46;*t>>=1;
main(int c,C**v){C b[99]={1,5,3,11,9,7,15,13,6,14},o[99],*q=o,*p=v[1],*t;while(c=*p++)*q++=c=='w'?46:c>='a'&&c<='z'?c-='a'+(c>'w'),b[c%10]|(c>9)*16|(c>19)*32:0;for(c=3;c;c--){p=b;for(t=o;t<q;t++){O;O*p++=32;}puts(b);}}

This implementation requires that its argument, if it contains spaces, must be quoted:

# braille "hello world"

# BBC Basic 103 ASCII characters or 92 tokens

A$="HXIKJY[ZQShxikjy{zqsl|Wmon"FORK=1TO26A=ASC(MID$(A$,K))VDU23,K+96,A AND9;0,A/2AND9;0,A/4AND9;:NEXT Possibly not quite what the OP intended, this redefines the font for the lowercase characters. VDU 23,n,a,b,c,d,e,f,g,h assigns an 8x8 bitmap to character n, consisting of eight bytes. Following a parameter with a semicolon instead of a comma causes it to be treated as a two-byte little-endian number. The braille patterns for letters a through z are stored in A$, according to the following bit pattern. This is extracted by masks with 9=binary1001 and rightshifts (division by 2 and 4 is used as standard BBC basic has no shift operator.)

8 1
16 2
32 4

Ungolfed code

A$="HXIKJY[ZQShxikjy{zqsl|Wmon" FORK=1TO26 A=ASC(MID$(A$,K)) VDU23,K+96,A AND9;0,A/2AND9;0,A/4AND9; NEXT Usage example This is done in screen mode 6 for clarity (type MODE6 as soon as you open the command line emulator.) Actually, after running the code, any lowercase letters (including keyboard input) appear in Braille. Emulator at http://bbcbasic.co.uk/bbcwin/bbcwin.html. See also this similar answer of mine: https://codegolf.stackexchange.com/a/28869/15599 # Bash + coreutils ### Minimal solution - lowercase only, 83 (33 unicode chars + 50 penalty): tr a-z ⠁⠃⠉⠙⠑⠋⠛⠓⠊⠚⠅⠇⠍⠝⠕⠏⠟⠗⠎⠞⠥⠧⠭⠽⠵⠺ ### Capitals, numbers and punctuation, 120 (120 unicode chars + 50 penalty - 50 bonus): a=⠁⠃⠉⠙⠑⠋⠛⠓⠊⠚⠅⠇⠍⠝⠕⠏⠟⠗⠎⠞⠥⠧⠭⠽⠵⠺ sed 's/$$[0-9]$$/⠼&/g;s/$$[A-Z]$$/⠠&/g'|tr ",;':\-⎖.!“?”()/a-zA-Z1-90" ⠂⠆⠄⠒⠤⠨⠲⠖⠦⠦⠴⠶⠶⠌$a$a$a

Example output:

$echo {A..Z} {a..z} {0..9} ".,;:" | ./braille.sh ⠠⠁ ⠠⠃ ⠠⠉ ⠠⠙ ⠠⠑ ⠠⠋ ⠠⠛ ⠠⠓ ⠠⠊ ⠠⠚ ⠠⠅ ⠠⠇ ⠠⠍ ⠠⠝ ⠠⠕ ⠠⠏ ⠠⠟ ⠠⠗ ⠠⠎ ⠠⠞ ⠠⠥ ⠠⠧ ⠠⠭ ⠠⠽ ⠠⠵ ⠠⠺ ⠁ ⠃ ⠉ ⠙ ⠑ ⠋ ⠛ ⠓ ⠊ ⠚ ⠅ ⠇ ⠍ ⠝ ⠕ ⠏ ⠟ ⠗ ⠎ ⠞ ⠥ ⠧ ⠭ ⠽ ⠵ ⠺ ⠼⠚ ⠼⠁ ⠼⠃ ⠼⠉ ⠼⠙ ⠼⠑ ⠼⠋ ⠼⠛ ⠼⠓ ⠼⠊ ⠲⠂⠆⠒$

# PHP, 331

<?php $d=split("/",gzinflate(base64_decode("NYzBDQBACIM26o3G/r+LRf2QYAOZe4SCLKgU7A9lEWVOzrQVrAiwghWhLKLMyZlawTTGMIYxPg==")));$d[-65]="......";$i=str_split(preg_replace("/[^a-z ]/","",trim(fgets(STDIN))));$o=["","",""];$S="substr";foreach($i as $c){$v=ord($c)-97;for($x=0;$x<3;$x++)$o[$x].=$S($d[$v],$x*2,2)." ";}echo join($o,"\n"); No bonuses for now. • I think it's okay to use a short opening tag in code-golf, so you can use <? instead of <?php[SPACE] to save 4 characters. – nyuszika7h Jul 4 '14 at 17:25 # JavaScript - 286 w=prompt().split('');for(i=0;i<w.length;i++){z=w[i];o="o",p=".";b=[1,5,3,11,9,7,15,13,6,14];e=[c="",1,3];g=z.charCodeAt(0)-97;if(g>22)g--;f=e[g/10|0];d=b[g%10];if(g==22){d=14;f=2;}c+=d&1?o:p;c+=d&2?o:p;c+="\n";c+=d&4?o:p;c+=d&8?o:p;c+="\n";c+=f&1?o:p;c+=f&2?"o\n":".\n";console.log(c);} First attempt. No bonuses. • You can reduce it to 279 with w=prompt().split("");for(i=0;i<w.length;i++)z=w[i],o="o",p=".",b=[1,5,3,11,9,7,15,13,6,14],e=[c="",1,3],g=z.charCodeAt(0)-97,22<g&&g--,f=e[g/10|0],d=b[g%10],22==g&&(d=14,f=2),c+=d&1?o:p,c+=d&2?o:p,c+="\n",c+=d&4?o:p,c+=d&8?o:p,c+="\n",c+=f&1?o:p,c+=f&2?"o\n":".\n",console.log(c) – WallyWest Jul 4 '14 at 6:12 • Will have to remember that approach, nice long single statement for loop :) – Matt Jul 6 '14 at 23:06 # CJam - 51 q{i32%"@hptdx|lX\bjrvfz~nZ^ck]swg"=i2b1>2/}%zSf*N* Try it at http://cjam.aditsu.net/ Example input: braille is strange Example output: 10 10 10 01 10 10 10 00 01 01 00 01 01 10 10 11 11 10 10 11 00 10 10 10 01 00 10 10 00 10 11 11 00 01 11 01 00 10 00 00 10 10 00 00 00 10 00 10 10 10 00 10 00 00 It only supports lowercase letters and space. Other characters are mapped to supported characters (in particular uppercase letters to lowercase). Explanation: Braille characters are encoded using 1 for a raised dot and 0 for a non-raised dot, left to right and top to bottom. This gives 6 base-2 digits; a 1 is prepended to avoid stripping leading zeros, then the number is converted to base 10 then to the corresponding ASCII character. Example: t -> ⠞ -> 01/11/10 -> 1011110 -> 94 -> ^ The program converts back each character to the triplet of pairs of bits (such as [[0 1][1 1][1 0]]) obtaining a matrix of bit pairs. The matrix is then transposed and separators are added (spaces within rows, newlines between rows). q reads the input into a string = array of characters {…}% applies the block to each character i32% gets the ASCII code mod 32 (space->0, a->1, b->2, z->26) "@hptdx|lX\bjrvfz~nZ^ck]swg" is a string containing the braille characters encoded as explained before = gets the corresponding encoded braille character from the string i2b gets the ASCII code then converts to base 2 (obtaining an array of 7 digits) 1> removes the leading 1 digit 2/ splits the array into (3) pairs z transposes the matrix Sf* joins each row with spaces N* joins the rows with newlines # C, 249 244 #define B?111:46 #define P(a,b)printf("%c%c ",a B,b B): a,i;main(int c,char**v){for(char*p;p=v[1],a<3;puts(""),++a)while(i=*p++)i==32?P(0,0)i/97&122/i?c=(i+=(i==119)*17-97-(i>119))%10,a?a^1?P(i/10%3,i/20)P(c>4|c==1,c/3&&c%3-2)P(c<8,5*c/8%2)0;} Input is a command-line argument, which must be escaped or quoted if the string contains spaces. Supported characters are lowercase letters and space. Unsupported characters are silently dropped. Edit: Shaved 5 bytes by simplifying a condition ## perl, 195+2-50=147 This handles capital, number and punctuation, without relying on unicode (195 bytes + 2 bytes (for -pl) - 50 bonus) ~s/([A-Z])/|$1/g,~s/(\d)/#$1/g,tr/1-90/a-ij/;for$i(1,2,4){map{for$j(1,8){$s.=index(" a,b'k;l^cif/msp_e:h*o!r_djg_ntq|_?_-u(v_____x____._)z\"___w_#y",l$"}$_=$s With indentation: ~s/([A-Z])/|$1/g,
~s/(\d)/#$1/g, tr/1-90/a-ij/; for$i(1,2,4){
map{
for$j(1,8){$s.=index(" a,b'k;l^cif/msp_e:h*o!r_djg_ntq|_?_-u(v_____x____._)z\"___w_#y",lc($_))&$j*$i?o:_ }$s.=_
}split//;
$s.=" "}$_=$s Sample output perl -pl brail.pl Hello, 99! ___o__o__o__o__o_________o__o__o__o____ ___oo__o_o__o___o_o______o_o___o_o__oo_ _o_______o__o__o________oo____oo____o__ # Javascript ES6 - 282309297283 270 - 50 = 232259233 220 bytes This would be shorter, but checking for capital letters hurt. f=_=>{z='toLowerCase';k=(a,b)=>a%b>~-b/2?1:0;t=(a,b)=>k(a,b)+${k(a,b/2)} ;b=c=d='';for(v of _){v==v[z]()?0:(b+=0,c+=0,v=v[z](d+=1));$= ,'-";9015283467@./+^_>#i[s!jwt)a*kue:ozb<lvh\\r(c%mxd?nyf$p&g]q=.search(v);b+=t($,64);c+=t($,16);d+=t($,4)}alert(${b}
${c}${d})}

EDIT: Thanks to mbomb007 for saving me two bytes - unfortunately, I found that a little bit of previous golfing had ruined everything, so I had to add 27 characters back in.

EDIT: Aaand 12 bytes saved by moving the spaces.

EDIT: Realized it was silly to output as characters, and saved quite a few bytes. I also saved a few characters by swapping k=(a,b)=>a%(2*b)>b-1?1:0 for k=(a,b)=>a%b>~-b/2?1:0.

• Maybe it'd be shorter to assign string.toLowerCase to a variable? – mbomb007 Nov 22 '16 at 16:33
• Numbers should be two letters (eg. 3=⠼⠉): the number prefix (⠼) and ciphers are converted to the equivalent letter (3=c=⠉). 1-9-->a-i and 0-->j – Adam Nov 22 '16 at 18:35
• I've seen different charts - that wasn't the case on the one I checked. – Marcus Dirr Nov 22 '16 at 18:39
• And I just realized I used the ASCII Braille encoding rather than an actual Ascii chart. So this is disqualified anyway. – Marcus Dirr Nov 23 '16 at 15:02