如果我们有一个带有字符(可能重复)的4x4板和一些随机字,我们需要找到是否可以在板上找到该字。现在这个问题很容易解决而不使用任何花哨的东西。但是从学习的角度来看,当我们考虑这些事情时,如何解决这个问题:
第一个想法是使用这样的东西:
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的用法。任何信息都是有价值的,无论是一些建议,一些伪代码甚至是一个有效的解决方案。感谢。
答案 0 :(得分:0)
我可以建议在变换器堆栈中使用另一个monad,而不是返回Bool
,而是使用明确的快捷计算能力,例如: Maybe
:
findWord :: String -> Position -> ReaderT Board (StateT (S.Set Position) Maybe) ()
我认为这是堆栈中的正确点,让它在每次失败后自动回退状态。
现在,您可以使用msum
(来自MonadPlus
类),它将依次测试列表中的每个选项,并且(对于基于Maybe
的堆栈)暂停如果没有,那么第一个子选项会成功或失败整个msum
。例如。
msum $ map (findWord remainingString) listOfNeighboringPositions