Python:在字符矩阵

时间:2015-07-28 20:58:25

标签: python matrix

我正在尝试创建一个包含5x5字符矩阵的文字游戏,如下所示:

[['a', 'a', 'u', 'r', 'a'],
 ['m', 'v', 'g', 'n', 'x'],
 ['a', 'q', 'h', 'y', 'o'],
 ['p', 'r', 'h', 'l', 'h'],
 ['v', 'h', 'y', 'o', 'j']]

我将其列为列表列表。应该找到“xylon”而不是“尼龙”,因为这会重复使用'n'。我发现了一个类似的问题here,但我不知道C.

我当前的解决方案涉及为单词中的每个字母创建一个字典,其中包含其在板上位置的元组列表,如下所示:{'letter':[(row,column),(row,column)] }。然后,对于单词中的每个字母,我检查板上的每个位置是否与前一个字母的位置兼容。如果是,我将该位置添加到新的路径字典

虽然重复字母和其他情况如“尼龙”确实返回True,但这失败了。它已经相当庞大和令人困惑,我应该重新开始。我可以采用更简洁的解决方案吗? 编辑:

澄清:如果存在连接网格中单词中每个字母的路径,则单词在网格中“。允许上,下,左,右和对角线。 'x'与'y'相邻,它与'l'相邻,依此类推。只要每个字母相邻并且板上没有特定字母被使用两次,该路径就不需要具有特定形状。单词可以具有重复的字母,因此可以使用“pama”,因为有多个'a'可以使用。

@MSW是正确的,游戏是boggle,虽然我第一次发现了这个!

1 个答案:

答案 0 :(得分:3)

如果你想检查单词成员资格,你将字母映射到职位的字典的起点是一个很好的:

letter_positions = {}
for (y, row) in enumerate(board):
    for (x, letter) in enumerate(row):
         letter_positions.setdefault(letter, []).append((x, y))

从那里,您的功能应该跟踪已经使用过哪些字母以确保它们不会复制它们:

def move_valid(position, last_position):
    if last_position is None:
        return True
    return (
        abs(position[0] - last_position[0]) <= 1 and
        abs(position[1] - last_position[1]) <= 1
    )

def find_word(word, used=None):
    if word == "":
        return []
    if used is None:
        used = []
    letter, rest = word[:1], word[1:]
    for position in letter_positions.get(letter) or []:
        if position in used:
            continue
        if not move_valid(position, used and used[-1]):
            continue
        path = find_word(rest, used + [position])
        if path is not None:
            return [position] + path
    return None

例如:

>>> find_word("xylon")
[(4, 1), (3, 2), (3, 3), (4, 2), (3, 1)]
>>> find_word("bad")
None

现在,请注意,此处的运行时间为O(not great),因为position in usedused是一个列表,需要O(N)搜索每个字母位置)和used + [position][position] + path(每个都会产生分配+副本)。在实践中,这将是〜O(word length ^ 2),但可以通过一些更合理的数据结构改进为〜O(word length)