I wondered how Fantom solution would look like? Here's the result:
Not very efficient, but quite compact solution. Method expand accepts phone number and returns list of all possible letter representations. So, for empty input it returns just list with one element - empty string.
Str[] expand(Str num)
{
num.isEmpty ? [""] :
expand(num[1..-1]).map |s|
{
table[num[0]].map |c| { c.toChar + s }
}.flatten
}
private static const Int:Int[] table := [
'2':['A','B', 'C'], '3':['D','E','F'],
'4':['G', 'H', 'I'], '5':['J','K','L'],
'6':['M', 'N', 'O'], '7':['P','Q','R', 'S'],
'8':['T','U','V'], '9':['W','X','Y','Z']]
If input is not empty, it does the following:
- calls itself to get the result of input without first digit
- gets all possible letters for first digit
- adds each letter in the beginning of each word from #1
- returns resulting list
Another possible improvement - use strings for letters instead of lists, so ['A','B', 'C'] becomes ["ABC"]. But here's a small problem with Str - it does not have neither Int[] toChars() nor ,Obj?[]? map(|Int, Int->Obj?|) slot, so we'll have to create a temporary list inside first map, i.e. instead of this:
table[num[0]].map |c| { c.toChar + s }
there would be something like this:
tmp := [,]
table[num[0]].each |c| { result.add(c.toChar + s) }
return tmp
So, in order to simplify declaration, it is easy to implement method like this:
static Int[] chars(Str s)
{
result := Int[,]
s.each { result.add(it) }
return result
}
So, declaration can be simplified in obvious way - instead of ['A','B','C'] will be chars("ABC").