Phone Numbers to Words

dpuu on 2008-12-24T18:07:07

I couldn't stop with just the "beginners" challenges. "Expert" event 1 asks use to take a phone number, and convert it to a valid word using standard mapping of digits to letters -- http://www.microsoft.com/technet/scriptcenter/funzone/games/games08/aevent1.mspx

The actual challenge uses a file that contains the list of words: I decided to hard code the array:



my @words = < READING SEEDING ELEMENT >.map: { [ .split("") ] };

my @mappings = < 0 1 ABC DEF GHI JKL MNO PQRS TUV WXYX >.map: { [ .split("") ] };

sub word_matches( @word, @phone ) returns Bool { return False unless @word.elems == @phone.elems; for @word Z @phone -> $letter, $digit { return False unless $letter eq any( |@mappings[$digit] ); } return True; }

sub find_word( $phone ) { my @phone = $phone.split(""); for @words -> @word { if word_matches( @word, @phone ) { say "number: { @phone }"; say "result: { @word }"; return } } }

find_word "7323464"


which gives the result: number: 7 3 2 3 4 6 4 result: R E A D I N G

What's interesting here?

This solution uses the zip operator, and junctions. It demonstrates nicely how these features simplify the code.

I originally attempted to write it without the subroutines, but ran into problems because "last" isn't implemented yet. So I formed a subroutine and used "return" for my early exit.

Oh yes, one other thing I hit: I originally wrote "any( @mappings[$digit] )"; That didn't work because, even in perl6, it's still necessary to dereference the inner array of an AofA -- in this case, using the "|" flattening operator.

I can't help but feel that there's a deeper elegance waiting to reveal itself in a reduction of the outer loop. The use of "for" in this context over constrains the implementation in that it is an explicit sequential iteration statement. It should be possible to form the result as a pure functional expression