首页 > 解决方案 > Haskell 使用 exeptions 旋转字符串

问题描述

我是 Haskell 的新手,我正在尝试将一个字符向右移动一个字符,并且最后一个字符将始终是第一个字符,并且它将返回一个字符串。

例如:shiftString "abcd" = "dabc"但是编译器不同意我的观点,有人可以帮我解决这个问题吗?

shiftString :: String -> String
shiftString x = take (length x) $ iterate rot1 x
        where rot1 = drop 1 x ++ take 1 x

另外,我想在这之后检查两个字符串,如果其中一个是应用 shiftString 一次或多次的结果,则返回 True,我该如何使用它来做到这一点?如:

isShifted :: String -> String -> Bool

标签: stringhaskell

解决方案


Haskell 中的AString只是Chars 的列表 - 所以你可以使用简单的模式匹配来做到这一点:

shiftString' :: String -> String
shiftString' (firstChar:restChars) = restChars ++ [firstChar]
shiftString' [] = []

现在,如果你尝试这个,它会做与你想要的相反的事情 - 但有一个技巧:我们将字符串反转两次:

shiftString :: String -> String
shiftString = reverse . shiftString' . reverse

这应该够了吧


修复你的:

我认为你只需要rot1(它与我的相同shiftString')以及上面的反向技巧

或者 - 修复你的更多:

我猜你尝试迭代rot1更多次,然后放弃其余的 - 这也有效:

shiftS cs = head $ drop (length cs - 1) $ iterate rot1 cs

rot1 cs = drop 1 cs ++ take 1 cs

请注意,它iterate为您提供了一个字符串列表(旋转越来越多)-我删除了第一个字符串(n-1其中n= 输入的长度),它再次给了我一个列表(您的版本中出现了一个类型错误)并占据了主导地位,因为我只想要String这个列表中的第一个。


对于您isShifted,您可以重用iteratewith rot1(无需关心订单) - 这次length cs从这里获取,然后检查您的其他输入是否是此列表的元素:

isShifted cs cs' = cs `elem` take (length cs) (iterate rot1 cs')

例子:

Prelude> isShifted "abcd" "cdab"                                           
True                                                                       
Prelude> isShifted "abdc" "cdab"                                           
False                                                                      

请注意,您不能只使用iterate rot1 cs'而没有采取 - 考虑一下然后尝试会发生什么;)(提示:当您的输入转移时它会起作用-但如果它们不是,您会遇到麻烦 - 为什么?)


推荐阅读