How to define a rotates function

后端 未结 8 1996
佛祖请我去吃肉
佛祖请我去吃肉 2021-01-11 14:47

How to define a rotates function that generates all rotations of the given list?

For example: rotates [1,2,3,4] =[[1,2,3,4],[2,3,4,1],[3,4,1,2],[4,1,2,3]]

8条回答
  •  自闭症患者
    2021-01-11 15:06

    The following

    shift :: [a] -> Int -> [a]
    shift l n = drop n l  ++ take n l
    
    allRotations :: [a] -> [[a]]
    allRotations l = [ shift l i | i <- [0 .. (length l) -1]]
    

    yields

    > ghci
    Prelude> :l test.hs
    [1 of 1] Compiling Main             ( test.hs, interpreted )
    Ok, modules loaded: Main.
    *Main> allRotations [1,2,3,4]
    [[1,2,3,4],[2,3,4,1],[3,4,1,2],[4,1,2,3]]
    

    which is as you expect.

    I think this is fairly readable, although not particularly efficient (no memoisation of previous shifts occurs).


    If you care about efficiency, then

    shift :: [a] -> [a]
    shift [] = []
    shift (x:xs) = xs ++ [x]
    
    allRotations :: [a] -> [[a]]
    allRotations l = take (length l) (iterate shift l)
    

    will allow you to reuse the results of previous shifts, and avoid recomputing them.

    Note that iterate returns an infinite list, and due to lazy evaluation, we only ever evaluate it up to length l into the list.


    Note that in the first part, I've extended your shift function to ask how much to shift, and I've then a list comprehension for allRotations.

提交回复
热议问题