Data.List permutations

Daniel Fischer daniel.is.fischer at web.de
Tue Aug 4 14:23:46 EDT 2009


Am Dienstag 04 August 2009 19:48:25 schrieb Slavomir Kaslev:
> A friend mine, new to functional programming, was entertaining himself by
> writing different combinatorial algorithms in Haskell. He asked me for some
> help so I sent him my quick and dirty solutions for generating variations
> and
>
> permutations:
> > inter x [] = [[x]]
> > inter x yys@(y:ys) = [x:yys] ++ map (y:) (inter x ys)
> >
> > perm [] = [[]]
> > perm (x:xs) = concatMap (inter x) (perm xs)
> >
> > vari 0 _ = [[]]
> > vari _ [] = []
> > vari k (x:xs) = concatMap (inter x) (vari (k-1) xs) ++ vari k xs
>
> After that I found out that nowadays there is a permutation function in the
>
> Data.List module:
> > permutations            :: [a] -> [[a]]
> > permutations xs0        =  xs0 : perms xs0 []
> >   where
> >     perms []     _  = []
> >     perms (t:ts) is = foldr interleave (perms ts (t:is)) (permutations
> > is) where interleave    xs     r = let (_,zs) = interleave' id xs r in zs
> > interleave' _ []     r = (ts, r)
> >             interleave' f (y:ys) r = let (us,zs) = interleave' (f . (y:))
> > ys r in  (y:us, f (t:y:us) : zs)
>
> I was surprised to find that not only my version is much simpler from the
> one in Data.List but it also performs better. Here are some numbers from my
> rather old ghc 6.8.1 running ubuntu on my box:
>
> *Main> length $ permutations [1..10]
> 3628800
> (10.80 secs, 2391647384 bytes)
> *Main> length $ perm [1..10]
> 3628800
> (8.58 secs, 3156902672 bytes)

But you compare *interpreted* code here, that's not what counts.

Prelude Perms> length $ perm [1 .. 10]
3628800
(1.20 secs, 1259105892 bytes)
Prelude Perms> length $ permutations [1 .. 10]
3628800
(0.56 secs, 551532668 bytes)
Prelude Perms> length $ perm [1 .. 11]
39916800
(13.18 secs, 14651808004 bytes)
Prelude Perms> length $ permutations [1 .. 11]
39916800
(4.30 secs, 5953485728 bytes)

Apparently the library code is more amenable to the optimiser (note that the actual 
library is faster still:

Prelude Data.List> length $ permutations [1 .. 10]
3628800
(0.49 secs, 551532812 bytes)
Prelude Data.List> length $ permutations [1 .. 11]
39916800
(3.73 secs, 5953485816 bytes)

I have no idea why).

>
> I would like to suggest to change the current implementation in Data.List
> with the simpler one. Also, it would be nice to add variations and
> combinations in the Data.List module.
>
> Cheers.



More information about the Glasgow-haskell-users mailing list