Image taken from http://www.flickr.com/photos/gadgetgirl70/225913840/ (CC license)

This is the phone mnemonics problem tested in a well-known empirical comparison of seven programming languages. The Scala version is as short as the scripting-language solutions. Through the use of GWT, the Scala code can run directly within the web browser and not need any server-side support.

Enter phone number

We decided to exclude code handling page updates. GWT libraries didn't get Scala's pimp-love yet so it's not pretty.

package com.google.gwt.sample.mnemonics.client

/** Taken from presentation by Martin Odersky at OSCON 2011 */
class Coder(words: List[String]) {

  private val mnemonics = Map(
    '2' -> "ABC", '3' -> "DEF", '4' -> "GHI", '5' -> "JKL",
    '6' -> "MNO", '7' -> "PQRS", '8' -> "TUV", '9' -> "WXYZ")

  /** Invert the mnemonics map to give a map from chars 'A' ... 'Z' to '2' ... '9' */
  private val charCode: Map[Char, Char] =
    for ((digit, str) <- mnemonics; ltr <- str) yield (ltr -> digit)

  /** Maps a word to the digit string it can represent, e.g. "Java" -> "5282" */
  def wordCode(word: String) = word.toUpperCase map charCode

  /** A map from digit strings to the words that represent them,
    * e.g. "5282" -> Set("Java", "Kata", "Lava", ...) */
  private val wordsForNum: Map[String, List[String]] = (words groupBy wordCode) withDefaultValue List()

  /** Return all ways to encode a number as a list of words */
  def encode(number: String): Set[List[String]] =
    if (number.isEmpty)
      Set(List())
    else {
      for {
        splitPoint <- 1 to number.length
        word <- wordsForNum(number take splitPoint)
        rest <- encode(number drop splitPoint)
      } yield word :: rest
    }.toSet

  /** Maps a number to a list of all word phrases that can represent it */
  def translate(number: String): Set[String] = encode(number) map (_ mkString " ")
}