On-demand algorithm returns a contiguous combination of k elements from n


lad

This post shows how to write an algorithm that spit out all combinations of k elements of n at a time , thus avoiding permutations. But how to write an algorithm that provides the next combination on demand (obviously, without precomputing and storing them)? It will be initialized with an ordered set of symbols n and integers k , and then called to return the next combination.

For my purposes, pseudocode or good English narration would be fine - I don't speak much of Perl and C and Java.

Leandro Caniglia

original wording

(skip to update below )


  1. Suppose nthe elements are integers 1..n.
  2. kRepresents each -combination in increasing order (this representation gets rid of the permutation inside the -combination k).
  3. Now consider the lexicographic order between k combinations (of nelements) . In other words, {i_1..i_k} < {j_1..j_k}if there is an index tsuch that
    • i_s = j_sall s < tand
    • i_t < j_t
  4. If -combination, define it {i_1..i_k}as the next element in lexicographical order.knext{i_1..i_k}

Here's how it is calculated next{i_1..i_k}:

  • Find the largest exponent rsuch thati_r + 1 < i_{r+1}
  • If no index satisfies this condition i_k < n, setr := k
  • If none of the above conditions are met, there is no next (and k-combination equals {n-k+1, n-k+2,... ,n})
  • If rthe first condition is met, set nextto{i_1, ..., i_{r-1}, i_r + 1, i_{r+1}, ..., i_k}
  • if r = k(second condition), setnext := {i_1, ..., i_{k-1}, i_k + 1}.

Update (many thanks to @rici for improving the solution)

  1. Suppose nthe elements are integers 1..n.
  2. kRepresents each -combination in increasing order (this representation gets rid of the permutation inside the -combination k).
  3. Now consider the lexicographic order between k combinations (of nelements) . In other words, {i_1..i_k} < {j_1..j_k}if there is an index tsuch that
    • i_s = j_sall s < tand
    • i_t < j_t
  4. If -combination, define it {i_1..i_k}as the next element in lexicographical order.knext{i_1..i_k}
  5. Note that in this order, the smallest kcombination is {1..k}the largest {n-k+1, n-k+2,... ,n}.

Here's how to calculatenext{i_1..i_k}

  • Find the largest index rso that it i_rcan be increased 1.
  • Increments the value at index rand resets the following elements from consecutive values ​​starting at i_r + 2.
  • Repeat until there are no more places to add.

more specifically:

  • If i_k < n, increment i_kby 1(ie, replace i_kwith i_k + 1)
  • If i_k = n, find the largest exponent rsuch that i_r + 1 < i_{r+1}. Then increase i_rthe pass 1and reset the following positions{i_r + 2, i_r + 3, ..., i_r + k + 1 - r}
  • repeat until reach{n-k+1, n-k+2,... ,n}

Note the recursive nature of this algorithm : every time the least significant position is incremented, the tail is reset to the lexicographically smallest sequence that starts with the value just incremented.


Smalltalk code

SequenceableCollection >> #nextChoiceFrom: n
    | next k r ar |
    k := self size.
    (self at: 1) = (n - k + 1) ifTrue: [^nil].
    next := self shallowCopy.
    r := (self at: k) = n
      ifTrue: [(1 to: k-1) findLast: [:i | (self at: i) + 1 < (self at: i+1)]]
      ifFalse: [k].
    ar := self at: r.
    r to: k do: [:i | 
      ar := ar + 1.
      next at: i put: ar].
    ^next

Related


Algorithm to generate K elements from a slice of N elements

Andrew LeFevre: I'm trying to port an algorithm from a Stackoverflow question in Go . The algorithm I'm trying to use is the following: Given a string slice of arbitrary length and a "depth", find all combinations of elements of length depth in the original sl

Algorithm to generate K elements from a slice of N elements

Andrew LeFevre: I'm trying to port an algorithm from a Stackoverflow question in Go . The algorithm I'm trying to use is the following: Given a string slice of arbitrary length and a "depth", find all combinations of elements of length depth in the original sl

Algorithm to return all combinations of k elements from n

Frederick I want to write a function that takes an array of letters as a parameter and selects multiple letters. Suppose you provide an array of 8 letters and want to select 3 letters from it. Then you will get: 8! / ((8 - 3)! * 3!) = 56 Returns an array (or

Algorithm to return all combinations of k elements from n

Frederick I want to write a function that takes an array of letters as a parameter and selects multiple letters. Suppose you provide an array of 8 letters and want to select 3 letters from it. Then you will get: 8! / ((8 - 3)! * 3!) = 56 Returns an array (or

print n choices using recursive k-combination algorithm

Erin This must be a classic interview question, however, I'm having trouble understanding it. Below is my implementation in Python, if you run it it just prints ab, ac, ad. It's not up to the 'b' (bc, bd)level. def Print_nCk (the_list, k, str_builder, used):

print n choices using recursive k-combination algorithm

Erin This must be a classic interview question, however, I'm having trouble understanding it. Below is my implementation in Python, if you run it it just prints ab, ac, ad. It's not up to the 'b' (bc, bd)level. def Print_nCk (the_list, k, str_builder, used):

lexicographical combination of k of 1...n, algorithm too slow

nultype: Here's one way (using backtracking) to list all possible combinations of k numbers in the interval [1, n] in lexicographical order. Duplicates are not allowed. which is: enter: 5 3 output: 1 2 3 1 2 4 1 2 5 1 3 4 1 3 5 1 4 5 2 3 4 2 3 5 2 4 5 3 4 5

print n choices using recursive k-combination algorithm

Erin This must be a classic interview question, however, I'm having trouble understanding it. Below is my implementation in Python, if you run it it just prints ab, ac, ad. It's not up to the 'b' (bc, bd)level. def Print_nCk (the_list, k, str_builder, used):

A combination of N ordered elements

Neptune I have a set of K elements and I need to create a combination of N ordered elements. For example, if K=1 and I have {X1, emptyset} and n=2, then I have an ordered pair and I need to do this: Example 1: ({},{}) ({X1},{}), ({},{X1}) ({X1},{X1})

A combination of N ordered elements

Neptune I have a set of K elements and I need to create a combination of N ordered elements. For example, if K=1 and I have {X1, emptyset} and n=2, then I have an ordered pair and I need to do this: Example 1: ({},{}) ({X1},{}), ({},{X1}) ({X1},{X1})

Is there an easy way to generate combination k from n in PARI/GP?

Peter Suppose I have a vector with n elements in PARI/GP. I want to generate combination k from n elements. For example, if the vector is [3,7,11,14,18] and k=3, the output should be [3,7,11] [3,7,14] [3,7,18] [3,11,14] [3,11,18] [3,14,18] [7,11,14] [7,11,18]

Combination of M elements from N with non-consecutive repeats

rock formation I have the following questions, which can be summarized as follows: Suppose you have two integers greater than 0, N (defining the array n=np.array(range(N)) and M. We want to generate all possible combinations of elements of length M , provided

Combination of M elements from N with non-consecutive repeats

rock formation I have the following questions, which can be summarized as follows: Suppose you have two integers greater than 0, N (defining the array n=np.array(range(N)) and M. We want to generate all possible combinations of elements of length M , provided

select k from n elements of mapreduce

mental illness Assume that the xrecords ' inputs nhave the desired properties (e.g. their values are positive) and that all records xhave unique keys. kWhat I want to do is, using a map-only job in MapReduce, emit these records exactly .n For example, let's sa

A good algorithm to get a combination of casual elements

user1978386 I try to write an application which will have a function called "special_reorder" and is the core of my application. Maybe this is the most complicated function in my app. This function is a class member of a class similar to std::map, but does not