Write all possible Braille characters

13

1

An interesting puzzle came to me looking at the elevator buttons this morning.

You are required to generate a list of all Braille patterns that fit in a 2x3 grid. Use a hash # to denote a bump and a hyphen - to denote a flat area.

Expected output sample:

#-
--
--

##
--
--

#-
#-
--

(and so on...)

Rules:

  • Your program must separate each pattern by at least one character or line.
  • The patterns may be generated in any order.
  • All patterns, regardless of what the Braille alphabet actually uses, should be produced. The completely blank pattern is optional.
  • Only unique bump patterns should be generated. The following patterns are considered equivilent as the bumps are in an identical arangement. In these cases, use the pattern that is closest to the top-left corner (ie. the first option in this example.)
#-  -#  --  --
#-  -#  #-  -#
--  --  #-  -#

Bonus points if you can make it work for any x by y sized grid. (EDIT: Within reasonable bounds. Up to 4x4 is enough for proof of concept.)

Reading the wiki article, it appears there are 45 patterns (including the blank) that meet this puzzle's rules.

Hand-E-Food

Posted 2012-09-26T05:22:31.657

Reputation: 7 912

It's not quite counting, but it's very close. For x x y grids you generate the first 2^(xy) numbers and filter out those which mask to 0 against 2^x - 1 or (2^(xy+1) - 1)/(2^y - 1). – Peter Taylor – 2012-09-26T08:11:59.913

Answers

6

GolfScript, 34 32 chars

44,{84+2base(;{'-#'=}/@\n.}%2/n*

Turns out that there are shorter solutions than simply generating all 64 patterns and filtering out the bad ones. In fact, by suitably mapping bits to grid positions, it's possible to map all valid (non-empty) patterns to a consecutive range of numbers, as this program does.

Specifically, the mapping I use is:

5 4
3 1
2 0

where the numbers denote the bit position (starting from the least significant bit 0) mapped to that position in the grid. With this mapping, the valid grids correspond to the numbers 20 to 63 inclusive.

This is almost the same as the obvious mapping obtained by writing out the 6-bit number in binary and adding line breaks between every second bit, except that the bits 1 and 2 are swapped — and indeed, that's exactly how my program computes it. (I also add 64 to the numbers before converting them to binary, and then strip the extra high bit off; that's just to zero-pad the numbers to 6 bits, since GolfScript's base would otherwise not return any leading zeros.)

Ps. Online demo here. (Server seems overloaded lately; if you get a timeout, try again or download the interpreter and test it locally.)

Edit: Managed to save two chars by avoiding unnecessary array building and dumping. Phew!

Ilmari Karonen

Posted 2012-09-26T05:22:31.657

Reputation: 19 513

2Do you mind adding some details? I'm interested to see how you're defining this mapping. – ardnew – 2012-09-27T02:02:31.857

@ardnew: Done, see above. – Ilmari Karonen – 2012-09-27T11:31:05.450

I think this is going to change a lot of people's answers. :-) – Hand-E-Food – 2012-09-27T20:41:29.780

3

Mathematica 97

Grid /@ Cases[(#~Partition~2 & /@ Tuples[{"#", "-"}, 6]), x_ /; 
         x[[All, 1]] != {"-", "-", "-"} && x[[1]] != {"-", "-"}]

braille


Blank is not included:

Length[%]

44

N.B. != is a single character in Mathematica.

DavidC

Posted 2012-09-26T05:22:31.657

Reputation: 24 524

3

C# – 205

class C{static void Main(){var s="---##-##";Action<int,int>W=(i,m)=>{Console.WriteLine(s.Substring((i>>m&3)*2,2));};for(int i=0;i<64;++i){if((i&3)>0&&(i&42)>0){W(i,0);W(i,2);W(i,4);Console.WriteLine();}}}}

Readable version:

class C
{
    static void Main()
    {
        var s = "---##-##"; // all two-bit combinations
        // a function to write one two-bit pattern (one line of a Braille character)
        Action<int,int> W = (i,m) => { Console.WriteLine(s.Substring(((i >> m) & 3) * 2, 2)); };
        // for all possible 6-bit combinations (all possible Braille characters)
        for(int i = 0; i < 64; ++i)
        {
            // filter out forbidden (non-unique) characters
            if ((i & 3) > 0 && (i & 42) > 0)
            {
                // write three rows of the Braille character and an empty line
                W(i,0);
                W(i,2);
                W(i,4);
                Console.WriteLine();
            }
        }
    }
}

Mormegil

Posted 2012-09-26T05:22:31.657

Reputation: 1 148

3

Perl, 71 67 65 char

y/10/#-/,s/../$&
/g,/^#/m&&print
for map{sprintf"%06b
",$_}18..63

Convert int to binary, perform transliteration, and add a newline after every two chars. The /^#/m test eliminates two patterns (20 and 21) that don't have a raised bump in the leftmost column.

General solution, 150 106 103 100 char

Read x and y from command line args. Newlines are significant

y/01/-#/,s/.{$x}/$&
/g,/^#/m*/^.*#/&&print
for map{sprintf"%0*b
",$x*$y,$_-1}1..1<<($y=pop)*($x=pop)

Iterate over 0..2xy like before, converting each int to binary, substituting - and # for 0 and 1, and inserting a newline after every $x characters.

/^#/m tests that there is a raised bump in the leftmost column, and /^.*#/ tests that there is a raised bump in the top row. Only the patterns that pass both tests are printed.

mob

Posted 2012-09-26T05:22:31.657

Reputation: 2 506

How does this account for the invalid combinations? – scleaver – 2012-09-26T20:11:27.017

Because the loop excludes the patterns for 1..17, 20, and 21. – mob – 2012-09-26T20:40:12.453

2

Python, 120 118 113 95 118

for j in range(256):
    if j/4&48and j/4&42:print''.join('_#'[int(c)]for c in bin(j/4)[2:].rjust(6,'0'))[j%4*2:j%4*2+2]

Edit: used Winston Ewert suggestion and added x by y grid solution

Edit: I somehow missed the last constraint about uniqueness. This script generates all the possible sequences, not just the 45.

Edit: Back up to 118 but now correct

scleaver

Posted 2012-09-26T05:22:31.657

Reputation: 507

Replace ['#','-'] with '#-' – Winston Ewert – 2012-09-26T15:37:54.540

2

J, 35 33 chars

3 2$"1'-#'{~(2 A.i.6){"1#:20+i.44

Uses the approach Ilmari Karonen came up with in their Golfscript solution. However, since the J verb #: (antibase) stores the bits (or, well, digits in the generic case) in a list, we need to index it from the left instead of right (i.e. index 0 is the leftmost, highest bit).

The solution is rather straightforward: 20+i.44 gives a list of the numbers 20..63, inclusive. #: takes the antibase-2 of each element in this list, and thus produces a list of bitpatterns for each number in that range. { selects (basically reorders) the bits into the right pattern, and then { is used again in order to use the digits as indices in the string '-#' in order to prepare the output. Finally, we arrange each entry into a 2-by-3 rectangle with $ (shape).


3 2$"1'-#'{~(2 A.i.6){"1#:20+i.44      N.B. use A. (anagram) to generate the right permutation

3 2$"1'-#'{~0 1 2 4 3 5{"1#:20+i.44

FireFly

Posted 2012-09-26T05:22:31.657

Reputation: 7 107

Does anyone know how something like (0 2 3 ,. 1 4 5) { #: 44 could be tweaked to work with a list of numbers rather than a single number? Would probably shave off a few more chars. – FireFly – 2012-09-27T22:29:42.227

1

Python - 121 112

blank is not included

from itertools import*
print'\n'.join('%s%s\n'*3%b for(b,n)in zip(product(*['_#']*6),range(64))if n&48and n&42)

quasimodo

Posted 2012-09-26T05:22:31.657

Reputation: 985

you can trim that product up with '_#',repeat=6 -> *['_#']*6 – boothby – 2012-09-28T01:43:29.347

@boothby: thanks. Also, b is already a tuple, so no need to convert it :) – quasimodo – 2012-09-29T20:32:56.963