Skip to content

Instantly share code, notes, and snippets.

@cedricblondeau
Last active November 2, 2016 00:52
Show Gist options
  • Save cedricblondeau/12b92ec0e0175b2ea44dcc044e7fa2e7 to your computer and use it in GitHub Desktop.
Save cedricblondeau/12b92ec0e0175b2ea44dcc044e7fa2e7 to your computer and use it in GitHub Desktop.
Generates all the words that can be made for given a phone number.
package phoneletters
import (
"bytes"
"strconv"
"strings"
)
// Generator is a word generator for phone numbers
type Generator struct {
lists [][]byte
}
// NewGenerator creates a new word generator instance for a given phone number
func NewGenerator(s string) Generator {
g := Generator{}
g.lists = lists(parse(s))
return g
}
// Words function generates all the words that can be made
func (g Generator) Words(f func(b []byte)) {
g.generate(0, make([]byte, len(g.lists)), f)
}
// generate function works like an odometer and recursively generates a list of words
func (g Generator) generate(index int, word []byte, f func([]byte)) {
if index == len(word) {
f(word)
return
}
for _, letter := range g.lists[index] {
word[index] = letter
g.generate(index+1, word, f)
}
}
// parse function parses a string and returns a list of digits
func parse(s string) []int {
result := []int{}
digits := strings.Split(s, "")
for _, digit := range digits {
i, err := strconv.Atoi(digit)
if err != nil {
continue
}
result = append(result, i)
}
return result
}
// lists returns the lists of possible characters for a given list of digits
func lists(digits []int) [][]byte {
pad := bytes.Split([]byte("0:1:ABC:DEF:GHI:JKL:MNO:PQRS:TUV:WXYZ"), []byte(":"))
result := [][]byte{}
for _, digit := range digits {
result = append(result, pad[digit])
}
return result
}
package phoneletters
import (
"bytes"
"testing"
"github.com/stretchr/testify/assert"
)
func TestParse(t *testing.T) {
assert.Equal(t, []int{2, 3, 4, 5}, parse("2345"))
assert.Equal(t, []int{1, 2, 3, 4, 5}, parse("12345"))
assert.Equal(t, []int{5, 5, 5, 7, 7, 7, 8, 8, 9, 9}, parse("(555) 777-8899"))
assert.Equal(t, []int{0, 3, 4, 5}, parse("#: (0) 3-4-5"))
}
func TestLists(t *testing.T) {
expected := bytes.Split([]byte("ABC:DEF"), []byte(":"))
result := lists([]int{2, 3})
assert.Equal(t, expected, result)
}
func TestWords(t *testing.T) {
g := NewGenerator("23")
result := []string{}
f := func(b []byte) {
result = append(result, string(b))
}
g.Words(f)
expected := []string{"AD", "AE", "AF", "BD", "BE", "BF", "CD", "CE", "CF"}
assert.Equal(t, expected, result)
}
@cedricblondeau
Copy link
Author

Usage

Print/output combinations

g := NewGenerator("111-269-5566")
f := func(b []byte) {
    fmt.Println(string(b))
}
g.Words(f)

Store combinations in a slice

g := NewGenerator("111-269-5566")
result := []string{}
f := func(b []byte) {
    result = append(result, string(b))
}
g.Words(f)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment