用 Groovy 检查 Wordle

作者:Paul King
发布时间:2023-02-08 12:00AM


这篇文章由 Donald Raab 撰写,探讨了使用 Eclipse 集合 在 Smalltalk 和 Java 中编写 Wordle 检查器的方案。让我们看看如何在 Groovy 中实现同样的功能。虽然我们可以轻松地在 Groovy 中使用 Eclipse 集合,但在这篇博客中我们只使用 JDK 集合。

在 Wordle 中,我们要猜出一个隐藏的单词。对于每次猜测,我们都会得到一个结果。对于每个位置正确的字母,返回大写字母。有时我们会猜对字母,但位置不对。在这种情况下,结果中会出现小写字母。结果中出现的字母数量不会超过隐藏词中出现的次数。

首先,我们的测试用例(来自原文本)

def triples = [
    [".....", "aaaaa", "bbbbb"],
    ["A....", "aaaaa", "abbbb"],
    [".A...", "aaaaa", "babbb"],
    ["..A..", "aaaaa", "bbabb"],
    ["...A.", "aaaaa", "bbbab"],
    ["....A", "aaaaa", "bbbba"],
    [".a...", "abbbb", "caccc"],
    ["..a..", "abbbb", "ccacc"],
    ["...a.", "abbbb", "cccac"],
    ["....a", "abbbb", "cccca"],
    ["A....", "abbbb", "accca"],
    ["A....", "abbbb", "accaa"],
    ["A..a.", "aabbb", "accaa"],
    ["AA...", "aabbb", "aacaa"],
    ["...aa", "aabbb", "cccaa"],
    ["..A..", "bbabb", "aaaaa"],
    ["AAAAA", "aaaaa", "aaaaa"],
    ["BRAVO", "bravo", "bravo"]]

现在我们将编写一个方法来检查隐藏词中的字母列表和猜测中的字母列表。与原文本相比,它与一些 Smalltalk 解决方案和一些 Java 解决方案有相似之处。

def checkGuess(hs, gs) {
    def remaining = hs.groupBy()                                // (1)
    def matches = [hs, gs].transpose().collect{ h, g ->         // (2)
        if (h == g) { remaining[g].pop(); g.toUpperCase() }
        else '.'
    }
    gs.eachWithIndex { g, i ->                                  // (3)
        if (matches[i] == '.' && remaining[g]?.remove(g)) {
            matches[i] = g
        }
    }
    matches.join()
}
  1. 我们将隐藏字母分组在一起。我们的袋子等价物。

  2. 在第一次遍历中,我们使用 zip 运算符(在 Groovy 中称为 transpose)收集精确匹配的字母。

  3. 在第二次遍历中,我们收集匹配但位置不同的字母。

最后,我们使用测试用例检查我们的方法

triples.each { result, hidden, guess ->
    assert result == checkGuess(hidden.toList(), guess.toList())
}