The way I solve Scala problems is solving them in Haskell first, and then translating. :)
reorderings xs = take len . map (take len) . tails . cycle $ xs
where len = length xs
This is the easiest way I could think of, which produces the list of all possible shifts, by "shifting left" repeatedly.
ghci> reorderings [1..5]
[[1,2,3,4,5],[2,3,4,5,1],[3,4,5,1,2],[4,5,1,2,3],[5,1,2,3,4]]
The concept is relatively simple (for those comfortable with functional programming, that is). First, cycle
the original list, producing an infinite stream from which to draw from. Next, break that stream into a stream of streams, where each subsequent stream has dropped the first element of the previous stream (tails
). Next, limit each substream to the length of the original list (map (take len)
). Finally, limit the stream of streams to the length of the original list, since there are only len
possible reorderings (take len
).
So let's do that in Scala now.
def reorderings[A](xs: List[A]):List[List[A]] = {
val len = xs.length
Stream.continually(xs).flatten // cycle
.tails
.map(_.take(len).toList)
.take(len)
.toList
}
We just had to use a small workaround for cycle
(not sure if Scala standard libs provide cycle, though I was pleasantly surprised to find they provide tails
), and a few toList
s (Haskell lists are lazy streams, while Scala's are strict), but other than that, it's exactly the same as the Haskell, and as far as I can tell, behaves exactly the same. You can almost think of Scala's .
as behaving like Haskell's, except flowing the opposite way.
Also note this is very nearly the same as dhg's solution, except without the reverses, which (on the upside) makes it more efficient, but (on the downside) provides the cycles in "backwinding" order, rather than "forward" order.