【问题标题】:Find 5 letter words with 25 distinct characters找到 25 个不同字符的 5 个字母单词
【发布时间】:2022-07-29 09:21:17
【问题描述】:

有效地解决wordle(对于人类和计算机)现在风靡一时。

解决单词的一种特殊方法让我很好奇。这个想法是选择 5 个具有不同字母的单词,这样你最终会得到 25 个字符。如果您在游戏中使用这 5 个单词作为您的前 5 个猜测,那么您将有接近 100% 的机会在最后一次猜测中得到正确的单词(它本质上是所有线索的字谜,您可能会有一个几个绿色的)。有一组词是建议的(所有的词都是有效的英文词):

  • 格伦特
  • 跳跃
  • vozhd
  • waqfs

但这让我想知道:这 5 个单词组合中有多少个,我开始构思一个递归算法,但我快要放弃了。

我最初的想法是:

  • 从第一个单词开始
  • 减少单词列表中的重叠单词
  • 在单词列表中选择下一个剩余的单词
  • 下一个单词重复

但这只有在你有一组五个不同的单词时才真正有效。

对于这个列表:

  • 盛宴
  • 格伦特
  • 跳跃
  • vozhd
  • waqfs

我最终会得到:[brick, feast, jumpy, vozhd],因为feastglent 之前会过滤掉它,但最后glent 会是更好的选择。

我找不到任何算法来解决这个特定问题,所以我想知道是否有任何现有的算法可以应用于这个问题?

【问题讨论】:

  • 您忽略了一个重要事实:字母可以出现多次。所以我认为这不是一个好的策略。例如。我在 sowpods 词典中找到了 ESSES。
  • 我同意这不是一个好策略。我仍然想实现一个算法来找到其中 25 个字符的 5 个单词。
  • 我想实现任意单词列表的算法。
  • 考虑一下:如果每个单词都是一个顶点,并且每个单词都有一个没有共同字母的边,那么您正在尝试找到一个 5-clique。 en.wikipedia.org/wiki/Clique_problem
  • maraca 说得对——没有“简单”的算法可以解决这个问题,因为问题是 NP 难题。但是,它可以是蛮力的,正好有 11 种解决方案

标签: algorithm wordle-game


【解决方案1】:

可以暴力破解。为了提高效率,可以丢弃所有具有重复字母的单词,并对单词进行预处理以使用它们具有哪些字母的位掩码(有 26 个字母,所以这适合 32 位无符号整数)。

然后只需进行深度优先搜索,维护与目前找到的单词不相交的单词列表(位掩码)。

我已经编写了一些执行此操作的 go 代码。它使用仅包含解决方案单词的简短单词列表(完整的单词列表太长,无法在此处包含),但即使使用完整列表,代码也会在几秒钟内运行。

由于它使用位掩码来表示单词,因此解决方案中可能存在多个具有相同字母的单词。该程序显示了介于两者之间的|。解决方案中只有一对:cylix|xylic

bling treck waqfs jumpy vozhd
pling treck waqfs jumby vozhd
brick glent waqfs jumpy vozhd
kreng clipt waqfs jumby vozhd
fjord chunk vibex gymps waltz
fjord gucks vibex nymph waltz
prick glent waqfs jumby vozhd
kempt brung waqfs cylix|xylic vozhd
blunk waqfs cimex grypt vozhd
clunk waqfs bemix grypt vozhd

可以在这里运行:https://go.dev/play/p/wVEDjx3G1fE

package main

import (
    "fmt"
    "math/bits"
    "sort"
    "strings"
)

var allWords = []string{
    "bemix", "bling", "blunk", "brick", "brung", "chunk", "cimex", "clipt", "clunk", "cylix", "fjord", "glent", "grypt", "gucks", "gymps", "jumby", "jumpy", "kempt", "kreng", "nymph", "pling", "prick", "treck", "vibex", "vozhd", "waltz", "waqfs", "xylic",
}

func printSol(res []uint32, masks map[uint32][]string) {
    var b strings.Builder
    for i, r := range res {
        if i > 0 {
            b.WriteString(" ")
        }
        b.WriteString(strings.Join(masks[r], "|"))
    }
    fmt.Println(b.String())
}

func find5(w []uint32, mask uint32, n int, res []uint32, masks map[uint32][]string) {
    if n == 5 {
        printSol(res, masks)
        return
    }
    sub := []uint32{}
    for _, x := range w {
        if x&mask != 0 {
            continue
        }
        sub = append(sub, x)
    }
    for i, x := range sub {
        res[n] = x
        find5(sub[i+1:], mask|x, n+1, res, masks)
    }
}

func find5clique() {
    masks := map[uint32][]string{}
    for _, x := range allWords {
        m := uint32(0)
        for _, c := range x {
            m |= 1 << (c - 'a')
        }
        if bits.OnesCount32(m) == 5 {
            masks[m] = append(masks[m], x)
        }
    }
    maskSlice := []uint32{}
    for m := range masks {
        maskSlice = append(maskSlice, m)
    }
    sort.Slice(maskSlice, func(i, j int) bool {
        return maskSlice[i] < maskSlice[j]
    })
    find5(maskSlice, uint32(0), 0, make([]uint32, 5, 5), masks)
}

func main() {
    find5clique()
}

【讨论】:

    【解决方案2】:

    和一些 wordle 粉丝一样,我很早就认为,一个包含 25 个不同字母的五字列表将是 wordle 解决方案的福音。像大多数网络白痴一样,我费力地寻找并比较了五个字母的单词,直到我最终得到了一个列表,其中几乎没有共享字母,只剩下 Q、X 和 Z 未使用(LINED、GOPAK、BUMFS、JIVEY 和 CRWTH)。当我在 You Tube 中遇到 WALTZ、VIBEX、FJORD、GYMPS 和 CHUNK 时,我感到敬畏,后来发现它很可能来自这个网站!你已经完成了超级工作!赞! 戴夫(uuglypher)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-26
      • 1970-01-01
      • 1970-01-01
      • 2016-01-09
      相关资源
      最近更新 更多