Instantly share code, notes, and snippets.

# ericnormand/00 Phone to letter translations.md

Last active October 6, 2021 17:14
Show Gist options
• Save ericnormand/ec3a492c760bb1623febdaf7222bfa14 to your computer and use it in GitHub Desktop.

Phone to letter translation

Phone keypads and rotary dials have little letters on them. Most numbers translate into letters. Of course, with only 10 digits, but 26 letters, there is a problem: the translation from letters to numbers is lossy. When translating from numbers to letters, there is always more than one possible interpretation.

Write a function that takes a string of digits and returns a collection of the possible strings of letters it corresponds to.

Examples

`(digits->letters "22") ;=> ["aa" "ab" "ac" "ba" "bb" "bc" "ca" "cb" "cc"]`

Here are the mappings you should use:

``````1: no letters
2: abc
3: def
4: ghi
5: jkl
6: mno
7: pqrs
8: tuv
9: wxyz
0: space
``````

If a character appears in the input that does not have a mapping, it will appear in the output untranslated.

Thanks to this site for the problem idea, where it is rated Expert in JavaScript. The problem has been modified.

### ZaymonFC commented Aug 5, 2021

```;; combo is clojure.math.combinatorics
(def phone-letter-mapping
{\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]
\0 [\ ]})

(defn number-to-list [xs]
(->> xs
(map (fn [x] (get phone-letter-mapping x [x])))
(apply combo/cartesian-product)
(map (partial apply str))))
```

### mcuervoe commented Aug 5, 2021

```(defn digits->letters [digits-str]
(let [mapping {\1 [\1], \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], \0 [\space]}]
(->>
(loop [digits digits-str
results [nil]]
(if (= 0 (count digits))
results
(let [chars (get mapping (first digits))]
(recur
(next digits)
(for [c chars, result results]
((fnil conj []) result c))))))
(map (fn [chars] (apply str chars))))))```

```(require '[clojure.math.combinatorics :as combo])

(def digit->letters {\2 "abc"
\3 "def"
\4 "ghi"
\5 "jkl"
\6 "mno"
\7 "pqrs"
\8 "tuv"
\9 "wxyz"
\0 " "})

(defn digits->letters [digits] (->> digits
(map digit->letters)
(filter seq)
(apply combo/cartesian-product)
(mapv #(apply str %))))```

### igajsin commented Aug 7, 2021

There are 3 steps here:

1. deconstruct a digit string into a list of letters.
2. do a permutation on lists.
3. construct strings from lists.
``````(def dict {
:1 [""]
: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"]
:0 [" "]
})

(defn letter->list [letter]
((keyword letter) dict))

(defn string->list [s]
(str/split s #""))

(defn get-letters [digits]
(map letter->list (string->list digits)))

(map #(list letter %)  letters))

(defn permutate2 [l1 l2]

(defn msg [s l]
(print (str s ": ")) (clojure.pprint/pprint l))

(defn permutate [letters]
(cond
(< (count letters) 2) letters
(= (count letters) 2) (permutate2 (first letters) (second letters))
:else (permutate2 (first letters) (permutate (rest letters)))))

(defn list->string [permutted]
(map clojure.string/join
(map flatten permutted)))

(defn digits->letters [digits]
(list->string (permutate (get-letters digits))))
``````

```(def dial {\1 "1", \2 "abc", \3 "def", \4 "ghi", \5 "jkl", \6 "mno",
\7 "pqrs", \8 "tuv", \9 "wxyz", \0 " "})

(defn digits->letters [digits]
(map
(partial apply str)
(loop [digs (-> digits reverse rest),
acc  (->> digits last dial
(map list))]
(if (empty? digs)
acc
(recur (rest digs)
(->> (dial (first digs))
(mapcat (fn [ltr]
(->> acc
(map #(conj % ltr)))))))))))```