Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

All list rotations in Haskell [duplicate]

I have a function to rotate a list:

rotate :: [a] -> [a]
rotate [] = []
rotate (x:xs) = xs ++ [x]

Now I want a function that gives a list with every possible rotation of a finite list:

rotateAll :: [a] -> [[a]]

In a imperative language, I would do something like (in pseudocode)

for i = 1 to length of list
  append list to rotateList
  list = rotate(list)

Of course, thinking imperatively probably doesn't help me find a functional solution to this problem. I'm looking for some hints as to how to tackle this.

Additional thoughts:

To solve this, I have two issues to tackle. First I need to repeatedly rotate a list and collect each result into a list. So a first solution needs to do something like

rotateAll xs = [xs (rotate xs) (rotate (rotate xs)) (rotate (rotate (rotate xs))) ...]

Of course I don't know how many times to do this. I'd be satisfied to do this infinitely and then use take (length xs) to get the finite number of lists I desire. This actually demonstrates the second issue: determining when to stop. I don't know if using take is the most efficient or elegant way to solve the problem, but it came to mind as I was typing this and should work.

Addendum: Now that I have found two solutions on my own or with hints. I will gladly welcome any other solutions that are faster or use different approaches. Thanks!

like image 385
Code-Apprentice Avatar asked Aug 08 '12 18:08

Code-Apprentice


2 Answers

Use the predefined functions in Data.List! You can get a list of all rotations using four function calls, no recursion, and no rotate function.

You asked not to have a full solution posted here. For those who want to see it, a full solution (one line of code) appears at http://pastebin.com/atGiw1ig.

like image 64
Norman Ramsey Avatar answered Sep 30 '22 00:09

Norman Ramsey


Aside from iterate, you could write a function that generates a list of n rotations. Case n=0 would just wrap the input in a list and case n=m+1 would append the input to the result of case m. Although using standard functions is generally preferred, sometimes writing your own solutions is healthy.

like image 34
Karolis Juodelė Avatar answered Sep 30 '22 00:09

Karolis Juodelė