使用scala查找所有可能的拼字游戏单词的最佳方法是什么?
有一个可用单词和字母的字典,可以用来组合这些单词
例如,有一个字典["lobby", "bar", "bold", "bobby"]
和字母"borblyd"
。结果应为["lobby", "bold"]
。
答案 0 :(得分:1)
生成所有可能的字母组合的列表。然后过滤掉真实的单词。绝对使用Iterator
来防止炸毁您的计算机。由于迭代器它不是纯功能解决方案,因为它们具有可变状态,但它会相当有效。
val letters = "borbly"
val dictionary = Set("lobby", "bar", "bold", "bobby")
val possibilities = Iterator.range(1, letters.length + 1).flatMap(letters.combinations).flatMap(_.permutations)
possibilities.filter(dictionary).toList
或者你可以反过来做,这看起来不那么酷,但如果你有很多字母可能会快得多:
import scala.annotation.tailrec
@tailrec
def canBeMade(word: String, letters: String): Boolean =
word.isEmpty || (letters.contains(word.head) && canBeMade(word.tail, letters.replaceFirst(word.head.toString, "")))
dictionary.filter(canBeMade(_, letters))
答案 1 :(得分:1)
似乎有@stefanobaghino的错字:"大胆"不应该在结果中。我的想法是建立地图Char - >发生在每个单词和输入字母上,并使用这些地图查找争夺词:
def chars2Occurs(chars: Seq[Char]): Map[Char, Int] = {
chars.foldLeft(Map.empty[Char, Int]) {
case (map, ch) =>
val occurs = map.get(ch).getOrElse(0) + 1
map + ((ch -> occurs))
}
}
def getScrambleWords(words: Seq[String], letters: Array[Char]): Seq[String] = {
val etalon: Map[Char, Int] = chars2Occurs(letters)
val word2Occur: Seq[(String, Map[Char, Int])] = words.map { word =>
(word, chars2Occurs(word))
}
val result: Seq[String] = word2Occur.flatMap { case (word, map) =>
val isOk = map.forall { case (c, n) =>
etalon.get(c) match {
case Some(k) => k >= n
case None => false
}
}
if (isOk) Some(word) else None
}
result
}
答案 2 :(得分:1)
这是另一种方法 - 翻阅字典中的每个单词,并且仅在以下情况下保留:1)单词不长于手中的字母数,以及2)删除字母中的每个字符后剩余字母的数量手中字母的单词等于原始字母数减去单词长度:
val letters = "borblyd".toSeq
val letterCount = letters.size
val dict = Set("lobby", "bar", "bold", "bobby")
dict.filter( word =>
word.length <= letterCount &&
word.foldLeft(letters)(
(lettersRemained, ch) => lettersRemained.diff(Seq(ch))
).size == letterCount - word.length
)
// res1: scala.collection.immutable.Set[String] = Set(lobby, bold)