帮助haskell旋转代码

时间:2011-03-19 19:24:33

标签: haskell

好的,所以我知道这有点不对,但我错过了什么?代码是用以下单词旋转单个字母:

rotate 1   "hello" "ohell"  
rotate -1  "hello" "elloh"

我的代码是:

module Main where

import System

main = do  
        (arg1:_) <- getArgs  
        xs <- getContents  
        putStr  (rotate xs arg1)  

rotate input w1 = unlines [ process line | line <- lines input ]  
        where process line = unwords [ word | word <- words line ]  
         map rotate n xs = drop n xs ++ take n xs  

到目前为止,这是否正确,任何线索/提示下一步去哪儿?

更像是这样:

shift :: a -> Int -> a
rotate :: a -> Int -> a

 x shift i   | i<0       = x shiftR (-i)
             | i>0       = x shiftL i
             | otherwise = x

 x rotate  i | i<0       = rotateR (-i)
             | i>0       = rotateL i
             | otherwise = x

1 个答案:

答案 0 :(得分:20)

快速回答:

试试这个:

rotate :: Int -> [Char] -> [Char]
rotate x st = take (length st) $ drop (negate x `mod` length st) $ cycle st

它产生:

rotate (1) "hello"
>>> "ohell"
rotate (-1) "hello"
>>> "elloh"

说明:

这需要的洞察力是cycle函数的知识,它永远重复一个字符串。

cycle "ezra"
>>> "ezraezraezraezraezr..." (forever)

利用这些知识,我们可以利用lengthtakedrop为我们提供我们想要的字符串部分。我们还会将negatemod用于数学部分。


长度

length返回列表的长度(字符串是字符列表)。

length "ezra"
>>> 4

take n返回列表中的第一个n项。

take 9 (cycle "ezra")
>>> "ezraezrae"

drop n返回整个列表,但第一个n元素除外。

drop 3 "ezra"
>>> "a"
drop 3 (take 9 (cycle "ezra"))
>>> "aezrae"

MOD

使用mod功能,我们可以获得正确的偏移量。反引号`使函数“中缀”,这使它更容易理解。如果您不熟悉modular arithmetic,那么这就是除法后的“余数”。

10 `mod` 3
>>> 1

这将为我们提供起点。


否定

negate n返回n的否定,我们需要“反转”方向,并获得您想要的输出。

negate 10
>>> -10

当我们把它们放在一起时,我们得到了上面的功能。当然,有很多方法可以做到这一点:这是一个。

在上面的解决方案中,我按以下顺序开发了它。

  1. 获取无限列表:

    rotate x st = cycle st
    
  2. 选择正确数量的字符:

    rotate x st = take (length st) $ cycle st
    
  3. 从正确的位置取字符:

    rotate x st = take (length st) $ drop (x `mod` length st) $ cycle st
    
  4. 此时我有我想要的东西,但必须添加negate以便我的输出与你的相匹配。

    我还添加了类型签名。我希望尽可能多地明确我的功能。