Reputation: 2481
I need a function that will take a list of (list of items), and enumerate all possible combinations of every item in every list. so
someCombo :: [[a]] -> [[a]]
someCombo = undefined
If I have something like this
[
[a1,b1],
[a2,b2,c2],
[a3,b3]
]
I want to spit out an answer like this, where very element of each list is matched with every element of every other list. Presumably in this case there'd be 12 elements to the final list.
[
[a1,a2,a3],[a1,a2,b3],[a1,b2,a3],[a1,b2,b3],...,[b1,c2,b3]
]
There could be an arbitrary number of lists in the main argument. This seems like it should be really simple, but I can't quite wrap my head around it. I can do it for two or three lists, but I can't make it work recursively an arbitrary number of lists. Oh and I don't care about the order of the resulting list, as long as I have all 12 (or whatever) of them.
If anyone is curious what this is for, it is the last piece I need to implement an algorithm which determines what order I would put plates onto a barbell before each lift that would minimize the amount of plate shuffling I would do from exercise to exercise. I figure this might save me a couple minutes per workout. In order to do that I need to enumerate all possible workouts that involve a specific set of plates for each lift and then find the combination of plate orders for each lift that results in the least amount of shuffling.
Upvotes: 2
Views: 1620
Reputation: 35089
import Control.Monad
someCombo = sequence
Let's try it:
>>> someCombo [[1, 2], [3, 4]]
[[1,3],[1,4],[2,3],[2,4]]
To understand this, you will need to understand list comprehensions or the list monad. sequence
effectively does this:
sequence [[1, 2], [3, 4]]
= do x <- [1, 2]
y <- [3, 4]
return [x, y]
You can think of that as saying "Let x
range over 1 and 2, let y
range over 3 and 4, now return all permutations of x
and y
".
Upvotes: 13