Note that there are some explanatory texts on larger screens.

plurals
  1. POCombinations and Permutations in F#
    primarykey
    data
    text
    <p>I've recently written the following combinations and permutations functions for an F# project, but I'm quite aware they're far from optimised.</p> <pre><code>/// Rotates a list by one place forward. let rotate lst = List.tail lst @ [List.head lst] /// Gets all rotations of a list. let getRotations lst = let rec getAll lst i = if i = 0 then [] else lst :: (getAll (rotate lst) (i - 1)) getAll lst (List.length lst) /// Gets all permutations (without repetition) of specified length from a list. let rec getPerms n lst = match n, lst with | 0, _ -&gt; seq [[]] | _, [] -&gt; seq [] | k, _ -&gt; lst |&gt; getRotations |&gt; Seq.collect (fun r -&gt; Seq.map ((@) [List.head r]) (getPerms (k - 1) (List.tail r))) /// Gets all permutations (with repetition) of specified length from a list. let rec getPermsWithRep n lst = match n, lst with | 0, _ -&gt; seq [[]] | _, [] -&gt; seq [] | k, _ -&gt; lst |&gt; Seq.collect (fun x -&gt; Seq.map ((@) [x]) (getPermsWithRep (k - 1) lst)) // equivalent: | k, _ -&gt; lst |&gt; getRotations |&gt; Seq.collect (fun r -&gt; List.map ((@) [List.head r]) (getPermsWithRep (k - 1) r)) /// Gets all combinations (without repetition) of specified length from a list. let rec getCombs n lst = match n, lst with | 0, _ -&gt; seq [[]] | _, [] -&gt; seq [] | k, (x :: xs) -&gt; Seq.append (Seq.map ((@) [x]) (getCombs (k - 1) xs)) (getCombs k xs) /// Gets all combinations (with repetition) of specified length from a list. let rec getCombsWithRep n lst = match n, lst with | 0, _ -&gt; seq [[]] | _, [] -&gt; seq [] | k, (x :: xs) -&gt; Seq.append (Seq.map ((@) [x]) (getCombsWithRep (k - 1) lst)) (getCombsWithRep k xs) </code></pre> <p>Does anyone have any suggestions for how these functions (algorithms) can be sped up? I'm particularly interested in how the permutation (with and without repetition) ones can be improved. The business involving rotations of lists doesn't look too efficient to me in retrospect.</p> <h3>Update</h3> <p>Here's my new implementation for the <code>getPerms</code> function, inspired by Tomas's answer.</p> <p>Unfortunately, it's not really any fast than the existing one. Suggestions?</p> <pre><code>let getPerms n lst = let rec getPermsImpl acc n lst = seq { match n, lst with | k, x :: xs -&gt; if k &gt; 0 then for r in getRotations lst do yield! getPermsImpl (List.head r :: acc) (k - 1) (List.tail r) if k &gt;= 0 then yield! getPermsImpl acc k [] | 0, [] -&gt; yield acc | _, [] -&gt; () } getPermsImpl List.empty n lst </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload