Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

get all possible combinations of k elements from a list

I need a function that does the same thing as itertools.combinations(iterable, r) in python

So far I came up with this:

{-| forward application -}
x -: f = f x
infixl 0 -:

{-| combinations 2 "ABCD" = ["AB","AC","AD","BC","BD","CD"] -}
combinations :: Ord a => Int -> [a] -> [[a]]
combinations k l = (sequence . replicate k) l -: map sort -: sort -: nub
    -: filter (\l -> (length . nub) l == length l)

Is there a more elegant and efficient solution?

like image 971
Tobias Hermann Avatar asked Feb 14 '14 09:02

Tobias Hermann


People also ask

How do you select K elements from an array?

Below are the steps: Sort the given array. Select the least non-negative value from the above array(say at index idx) using lower_bound() in C++. If a positive value doesn't exist in a given array, then the sum is always negative and none of the K element satisfies the given condition.

How do you create possible combinations of K numbers?

We use the idea similar to the subset sum problem for creating possible combinations of K numbers from n numbers: we select each number from 1 to n and recur for two possible cases: The selected number is the part of the solution or included in the set The selected number is not part of the solution or not included in the set

How to find all possible combinations of K numbers in Python?

Suppose we use the function findKCombination (int K, int n), which returns output in a 2-D array. Inside the function, we declare two temporary arrays to store all outputs one by one: 1-D array temp [] to store any combination of K numbers. The 2-D array output [] [] to store all possible combinations of K numbers

How to print all possible combinations of R elements in array?

We have discussed one approach in the below post. Print all possible combinations of r elements in a given array of size n In this, we use DFS based approach. We want all numbers from 1 to n. We first push all numbers from 1 to k in tmp_vector and as soon as k is equal to 0, we push all numbers from tmp_vector to ans_vector.

How to generate all possible combinations of elements in array?

Given an array of size n, generate and print all possible combinations of r elements in array. For example, if input array is {1, 2, 3, 4} and r is 2, then output should be {1, 2}, {1, 3}, {1, 4}, {2, 3}, {2, 4} and {3, 4}. Following are two methods to do this. We create a temporary array ‘data []’ which stores all outputs one by one.


3 Answers

xs elements taken n by n is

mapM (const xs) [1..n]

all combinations (n = 1, 2, ...) is

allCombs xs = [1..] >>= \n -> mapM (const xs) [1..n]

if you need without repetition

filter ((n==).length.nub)

then

combinationsWRep xs n = filter ((n==).length.nub) $ mapM (const xs) [1..n]
like image 153
josejuan Avatar answered Oct 20 '22 22:10

josejuan


(Based on @JoseJuan's answer)

You can also use a list comprehension to filter out those where the second character is not strictly smaller than the first:

[x| x <- mapM (const "ABCD") [1..2], head x < head (tail x) ]
like image 36
Frank Schmitt Avatar answered Oct 20 '22 21:10

Frank Schmitt


(Based on @FrankSchmitt’s answer)

We have map (const x) [1..n] == replicate n x so we could change his answer to

[x| x <- sequence (replicate 2 "ABCD"), head x < head (tail x) ]

And while in original question, 2 was a parameter k, for this particular example would probably not want to replicate with 2 and write

[ [x1,x2] | x1 <- "ABCD", x2 <- "ABCD", x1 < x2 ]

instead.

With a parameter k things are a bit more tricky if you want to generate them without duplicates. I’d do it recursively:

f 0 _  = [[]]
f _ [] = []
f k as = [ x : xs | (x:as') <- tails as, xs <- f (k-1) as' ]

(This variant does not remove duplicates if there are already in the list as; if you worry about them, pass nub as to it)

like image 4
Joachim Breitner Avatar answered Oct 20 '22 22:10

Joachim Breitner