Translate ASCII text to braille

19

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 .  . .

Greg Hewgill

Posted 2014-07-04T02:00:26.840

Reputation: 2 641

define "valiant attempt". Also, is line-wrapping required? – John Dvorak – 2014-07-04T02:20:26.910

@JanDvorak: Thanks, updated question. – Greg Hewgill – 2014-07-04T02:23:45.870

I'm sorry, but a single example doesn't cut it in a code golf specification. Please give us the objective minimal requirements to qualify for the bonus. – John Dvorak – 2014-07-04T02:30:08.580

@JanDvorak: Fair point, I've removed the "valiant attempt" weasel words. There is considerable variation in real world use of these contractions, and fully spelling out contractable words using only letters is valid but considered clumsy by braille readers. – Greg Hewgill – 2014-07-04T02:53:07.280

What punctuation do we need to support? Some symbols don't have a standard braille equivalent. – qwr – 2014-07-04T04:42:57.827

@qwr the basic punctuation listed in the braille Wikipedia article. – Greg Hewgill – 2014-07-04T04:45:57.310

1@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 – 2014-07-04T04:48:36.717

@qwr: I'm not going to change the bonus at this point. Note that capitals aren't separate letter codes, but a prefix code that means "the next letter is capital". – Greg Hewgill – 2014-07-04T08:34:28.390

1You 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 – 2014-07-04T17:19:58.187

can the output be vertical? – xem – 2014-07-04T18:13:41.790

1Man... 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 – 2014-07-04T20:37:09.337

Which English grade-2 Braille? American, British or Unified? – aditsu quit because SE is EVIL – 2014-07-05T15:54:23.977

@aditsu: I'm probably going to make the Grade-2 challenge a separate problem, and specify the requirements carefully. – Greg Hewgill – 2014-07-05T22:15:50.357

@GregHewgill from what I've seen around here (to my dismay), that would likely get a bunch of downvotes and be closed as a duplicate – aditsu quit because SE is EVIL – 2014-07-06T06:38:04.357

Answers

6

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 .

grc

Posted 2014-07-04T02:00:26.840

Reputation: 18 565

6

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="")

qwr

Posted 2014-07-04T02:00:26.840

Reputation: 8 929

1Why not make it a one-liner? for l in input():print("⠀⠁⠃⠉⠙⠑⠋⠛⠓⠊⠚⠅⠇⠍⠝⠕⠏⠟⠗⠎⠞⠥⠧⠺⠭⠽⠵"[max(0,ord(l)-96)],end="") 75 characters. – ɐɔıʇǝɥʇuʎs – 2014-07-04T07:26:38.863

@ɐɔıʇǝɥʇuʎs wow, I forgot about the max trick. Thank you – qwr – 2014-07-04T07:31:35.837

You can save a char by just putting blanks for all non-letter characters: for l in input():print((" "*97+"⠁⠃⠉⠙⠑⠋⠛⠓⠊⠚⠅⠇⠍⠝⠕⠏⠟⠗⠎⠞⠥⠧⠺⠭⠽⠵")[ord(l)],end="") – xnor – 2014-07-06T17:09:34.553

3

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"

Greg Hewgill

Posted 2014-07-04T02:00:26.840

Reputation: 2 641

3

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

Level River St

Posted 2014-07-04T02:00:26.840

Reputation: 22 049

2

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

Digital Trauma

Posted 2014-07-04T02:00:26.840

Reputation: 64 644

1

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.

Matt

Posted 2014-07-04T02:00:26.840

Reputation: 777

2You 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 – 2014-07-04T06:12:50.287

1Will have to remember that approach, nice long single statement for loop :) – Matt – 2014-07-06T23:06:21.767

1

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.

Snack

Posted 2014-07-04T02:00:26.840

Reputation: 2 142

2I think it's okay to use a short opening tag in [tag:code-golf], so you can use <? instead of <?php[SPACE] to save 4 characters. – nyuszika7h – 2014-07-04T17:25:40.520

1

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

aditsu quit because SE is EVIL

Posted 2014-07-04T02:00:26.840

Reputation: 22 326

0

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__

Adam

Posted 2014-07-04T02:00:26.840

Reputation: 591

0

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.

Marcus Dirr

Posted 2014-07-04T02:00:26.840

Reputation: 51

Maybe it'd be shorter to assign string.toLowerCase to a variable? – mbomb007 – 2016-11-22T16:33:57.547

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 – 2016-11-22T18:35:26.130

I've seen different charts - that wasn't the case on the one I checked. – Marcus Dirr – 2016-11-22T18:39:51.430

And I just realized I used the ASCII Braille encoding rather than an actual Ascii chart. So this is disqualified anyway. – Marcus Dirr – 2016-11-23T15:02:39.087

0

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

Fox

Posted 2014-07-04T02:00:26.840

Reputation: 341