19
\$\begingroup\$

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 .  . .
\$\endgroup\$
  • \$\begingroup\$ define "valiant attempt". Also, is line-wrapping required? \$\endgroup\$ – John Dvorak Jul 4 '14 at 2:20
  • \$\begingroup\$ @JanDvorak: Thanks, updated question. \$\endgroup\$ – Greg Hewgill Jul 4 '14 at 2:23
  • 1
    \$\begingroup\$ @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) \$\endgroup\$ – qwr Jul 4 '14 at 4:48
  • 1
    \$\begingroup\$ 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. \$\endgroup\$ – nyuszika7h Jul 4 '14 at 17:19
  • 1
    \$\begingroup\$ 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. \$\endgroup\$ – Almo Jul 4 '14 at 20:37

11 Answers 11

6
\$\begingroup\$

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 .
\$\endgroup\$
6
\$\begingroup\$

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

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"
\$\endgroup\$
3
\$\begingroup\$

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.

enter image description here

Emulator at http://bbcbasic.co.uk/bbcwin/bbcwin.html.

See also this similar answer of mine: https://codegolf.stackexchange.com/a/28869/15599

\$\endgroup\$
2
\$\begingroup\$

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 
⠠⠁ ⠠⠃ ⠠⠉ ⠠⠙ ⠠⠑ ⠠⠋ ⠠⠛ ⠠⠓ ⠠⠊ ⠠⠚ ⠠⠅ ⠠⠇ ⠠⠍ ⠠⠝ ⠠⠕ ⠠⠏ ⠠⠟ ⠠⠗ ⠠⠎ ⠠⠞ ⠠⠥ ⠠⠧ ⠠⠭ ⠠⠽ ⠠⠵ ⠠⠺ ⠁ ⠃ ⠉ ⠙ ⠑ ⠋ ⠛ ⠓ ⠊ ⠚ ⠅ ⠇ ⠍ ⠝ ⠕ ⠏ ⠟ ⠗ ⠎ ⠞ ⠥ ⠧ ⠭ ⠽ ⠵ ⠺ ⠼⠚ ⠼⠁ ⠼⠃ ⠼⠉ ⠼⠙ ⠼⠑ ⠼⠋ ⠼⠛ ⠼⠓ ⠼⠊ ⠲⠂⠆⠒
$ 
\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
  • 2
    \$\begingroup\$ 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. \$\endgroup\$ – nyuszika7h Jul 4 '14 at 17:25
1
\$\begingroup\$

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.

\$\endgroup\$
  • 2
    \$\begingroup\$ 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) \$\endgroup\$ – WallyWest Jul 4 '14 at 6:12
  • 1
    \$\begingroup\$ Will have to remember that approach, nice long single statement for loop :) \$\endgroup\$ – Matt Jul 6 '14 at 23:06
1
\$\begingroup\$

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

\$\endgroup\$
0
\$\begingroup\$

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

\$\endgroup\$
0
\$\begingroup\$

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__
\$\endgroup\$
0
\$\begingroup\$

Javascript ES6 - 282 309 297 283 270 - 50 = 232 259 233 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.

\$\endgroup\$
  • \$\begingroup\$ Maybe it'd be shorter to assign string.toLowerCase to a variable? \$\endgroup\$ – mbomb007 Nov 22 '16 at 16:33
  • \$\begingroup\$ 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 \$\endgroup\$ – Adam Nov 22 '16 at 18:35
  • \$\begingroup\$ I've seen different charts - that wasn't the case on the one I checked. \$\endgroup\$ – Marcus Dirr Nov 22 '16 at 18:39
  • \$\begingroup\$ And I just realized I used the ASCII Braille encoding rather than an actual Ascii chart. So this is disqualified anyway. \$\endgroup\$ – Marcus Dirr Nov 23 '16 at 15:02

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.