Let us first clean up the rotatebyone
function:
rotatebyone :: [Int] -> [Int]
rotatebyone [] = []
rotatebyone (x:xs) = ((tail (x:xs)) ++ (take 1 (x:xs)))
Here you call tail
on (x:xs)
but that is quite weird, since we already have a tail: xs
. So we can replace tail (x:xs)
with xs
.
The same holds for take 1 (x:xs)
. This will construct a list with the head of the list, so [x]
. So we can clean up the code to:
rotatebyone :: [Int] -> [Int]
rotatebyone [] = []
rotatebyone (x:xs) = xs ++ [x]
Furthermore your function only works on lists of type Int
(it has signature [Int] -> [Int]
). We can however rotate lists by one regardless the type of elements these lists hold, so we can write it as:
rotatebyone :: [a] -> [a]
rotatebyone [] = []
rotatebyone (x:xs) = xs ++ [x]
Now we can look for a way to rotate n
times with:
rotatebyn :: Int ->[a] -> [a]
rotatebyn ...
In case we wish to rotate over zero places, then the list remains the same, so as a base case we can write:
rotatebyn 0 l = l
and in case we want to rotate over one or more places, we can rotate over one place by the rotatebyone
function, and then rotate this result another n-1
times:
rotatebyn n l = rotatebyn (n-1) (rotateone n)
or these together:
rotatebyn :: Int ->[a] -> [a]
rotatebyn 0 l = l
rotatebyn n l = rotatebyn (n-1) (rotateone n)
But the above is, like @dfeuer says not efficient: it takes O(n) time to rotate a list, if we need to do this k times, the time complexity is thus O(n k).
Note furthermore that the above function only works in case n
is greater than or equal to zero.