使用State单子在2d迷宫中找到单词



如果我们有一个带有字符(可能重复)和一些随机单词的4x4板,我们需要找到该单词是否可以在板上找到。现在这个问题很容易解决,不需要任何花哨的东西。但从学习的角度来看,当我们考虑这些事情时,如何解决这个问题呢?

  • 板是恒定的,不会改变,所以假设我们有兴趣为它使用Reader
  • 当搜索一个单词时,我们需要在板上保存一组访问过的tile,所以假设我们有兴趣为它使用State

第一个想法是这样使用:

findWord :: String -> Position -> ReaderT Board (State (S.Set Position)) -> Bool

input String是我们要搜索的单词的剩余部分

where Position is (Int, Int),用于标识当前在板上的位置(Set存储在此搜索路径中访问过的位置)

Board只是存储每个位置的字符信息,简单起见,可以认为是[[Char]]

返回Bool值是用来作为最终结果,表示该board是否包含该单词

板上的搜索可以在各个方向进行(所以包括对角线);单词不需要在水平线或对角线上-只要单词的字符在黑板上连接-解决方案是有效的。

现在对于实际的问题:如果我们使用State来解决这个问题,我们如何确保函数在找到单词后立即返回,而不继续搜索其他路径?例如,如果我们正在寻找的单词是"AAAAA",而棋盘只是16个字符的"A",那么函数应该在5次迭代后返回,而不是继续搜索所有可能的路径(因为成功路径的数量是巨大的)?

我正在寻找一些关于如何使用一个必须的约束来解决这个问题的技巧:使用State monad。任何信息都是有价值的,无论是一些建议、一些伪代码,甚至是一个可行的解决方案。谢谢。

不返回Bool,我建议在变压器堆栈中使用另一个具有显式快捷计算能力的monad,例如Maybe:

findWord :: String -> Position -> ReaderT Board (StateT (S.Set Position) Maybe) ()

我认为这是堆栈中正确的点,让它在每次失败后自动回滚状态。

现在,您可以使用msum(来自MonadPlus类),它将依次测试列表中的每个选项,并且(对于基于Maybe的堆栈)在成功的第一个子选项上停止,或者如果没有,则整个msum失败。例如:

msum $ map (findWord remainingString) listOfNeighboringPositions

最新更新