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

时间:2014-07-06 09:27:02

标签: haskell state-monad

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

  • 董事会是不变的,不会改变,所以我们说我们有兴趣使用Reader
  • 在搜索单词时,我们需要在棋盘上保留一组访问过的拼贴,所以我们说我们有兴趣使用State for it

第一个想法是使用这样的东西:

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

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

其中Position是(Int,Int)用于识别我们当前在董事会中的位置(并且Set存储我们在此搜索路径中访问过的位置)

董事会只是在每个位置存储有关字符的信息,为简单起见,可以将其视为[[Char]]

返回Bool意味着用作最终结果来说明董事会是否包含单词

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

现在针对实际问题:如果我们使用State来解决这个问题,我们如何确保函数在找到单词后立即返回,并且不会继续搜索其他路径?例如,如果我们要查找的单词是“AAAAA”并且该单板只是16个字符“A”,那么该函数应该在5次迭代之后返回并且不继续搜索所有可能的路径(因为成功的数量)路径很大)?

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

1 个答案:

答案 0 :(得分:0)

我可以建议在变换器堆栈中使用另一个monad,而不是返回Bool,而是使用明确的快捷计算能力,例如: Maybe

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

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

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

之类的东西
msum $ map (findWord remainingString) listOfNeighboringPositions