Am Donnerstag 24 Dezember 2009 03:30:54 schrieb Patrick LeBoutillier:
> How do you do it with drinkPerms? The constant element is in the
> middle (with Nations
> it seems easier since it's the first one).
insertAt :: Int -> a -> [a] -> [a]
insertAt k x xs = case splitAt k xs of
(front,back) -> front ++ x:back
drinkPerms = map (insertAt 2 Milk) $ permutations [Coffee, Tea, Water, Beer]
Another possibility to have x inserted at a fixed position in all permutations of xs is to use
do (fs,bs) <- picks k xs
pf <- permutations fs
pb <- permutations bs
return (pf ++ x:pb)
which has the advantage that the permutations of the front are shared (if the back is longer than the front, it might be better to swap lines 2 and 3 to share the permutations of the back) and avoids the many splits.
picks :: Int -> [a] -> [([a],[a])]
picks k xs
| k == 0 = [([],xs)]
| k == l = [(xs,[])]
| k > l = []
| otherwise = pickHelper l k xs
where
l = length xs
pickHelper s t yys@(y:ys)
| s == t = [(yys,[])]
| otherwise = [(y:zs,ws) | (zs,ws) <- pickHelper (s-1) (t-1) ys]
++ [(zs,y:ws) | (zs,ws) <- pickHelper (s-1) t ys]
It's by far not as nice as keeping the first element fixed, but you can easily keep more than one position fixed. And when you have a couple more items, this approach is enormously faster than filtering.