# PHP algorithm to generate all combinations of a specific size from a single set

Viewed   636 times

I am trying to deduce an algorithm which generates all possible combinations of a specific size something like a function which accepts an array of chars and size as its parameter and return an array of combinations.

Example: Let say we have a set of chars: Set A = {A,B,C}

a) All possible combinations of size 2: (3^2 = 9)

``````AA, AB, AC
BA, BB, BC
CA, CB, CC
``````

b) All possible combinations of size 3: (3^3 = 27)

``````AAA, AAB, AAC,
ABA, ABB, ACC,
CAA, BAA, BAC,
.... ad so on total combinations = 27
``````

Please note that the pair size can be greater than total size of pouplation. Ex. if set contains 3 characters then we can also create combination of size 4.

EDIT: Also note that this is different from permutation. In permutation we cannot have repeating characters for example AA cannot come if we use permutation algorithm. In statistics it is known as sampling.

3

I would use a recursive function. Here's a (working) example with comments. Hope this works for you!

``````function sampling(\$chars, \$size, \$combinations = array()) {

# if it's the first iteration, the first set
# of combinations is the same as the set of characters
if (empty(\$combinations)) {
\$combinations = \$chars;
}

# we're done if we're at size 1
if (\$size == 1) {
return \$combinations;
}

# initialise array to put new values in
\$new_combinations = array();

# loop through existing combinations and character set to create strings
foreach (\$combinations as \$combination) {
foreach (\$chars as \$char) {
\$new_combinations[] = \$combination . \$char;
}
}

# call same function again for the next iteration
return sampling(\$chars, \$size - 1, \$new_combinations);

}

// example
\$chars = array('a', 'b', 'c');
\$output = sampling(\$chars, 2);
var_dump(\$output);
/*
array(9) {
[0]=>
string(2) "aa"
[1]=>
string(2) "ab"
[2]=>
string(2) "ac"
[3]=>
string(2) "ba"
[4]=>
string(2) "bb"
[5]=>
string(2) "bc"
[6]=>
string(2) "ca"
[7]=>
string(2) "cb"
[8]=>
string(2) "cc"
}
*/
``````
Saturday, December 17, 2022
2

If your child class extends the parent class there's no need to do that, do this instead:

``````\$this->update_query_function();
``````

that's the point of inheritance.

Sunday, October 2, 2022
5

See scipy.special.comb (scipy.misc.comb in older versions of scipy). When `exact` is False, it uses the gammaln function to obtain good precision without taking much time. In the exact case it returns an arbitrary-precision integer, which might take a long time to compute.

Wednesday, August 17, 2022
3

First of all, I'd use variable names that mean something, so that the code gets comprehensible. Then, after I understood the problem, it's clearly a recursive problem, as once you have chosen one number, the question of finding the possible values for the rest of the squares are exactly the same problem, but with different values in.

So I would do it like this:

``````from __future__ import division
from math import ceil

def make_combos(max_val,target_sum,n_cells):
combos = []
# The highest possible value of the next cell is whatever is
# largest of the max_val, or the target_sum minus the number
# of remaining cells (as you can't enter 0).
highest = min(max_val, target_sum - n_cells + 1)
# The lowest is the lowest number you can have that will add upp to
# target_sum if you multiply it with n_cells.
lowest = int(ceil(target_sum/n_cells))
for x in range(highest, lowest-1, -1):
if n_cells == 1: # This is the last cell, no more recursion.
combos.append((x,))
break
# Recurse to get the next cell:
# Set the max to x (or we'll get duplicates like
# (6,3,2,1) and (6,2,3,1), which is pointless.
# Reduce the target_sum with x to keep the sum correct.
# Reduce the number of cells with 1.
for combo in make_combos(x, target_sum-x, n_cells-1):
combos.append((x,)+combo)
return combos

if __name__ == '__main__':
import pprint
# And by using pprint the output gets easier to read
pprint.pprint(make_combos( 6,12,4))
``````

I also notice that your solution still seems buggy. For the values `max_val=8, target_sum=20 and n_cells=5` your code doesn't find the solution `(8,6,4,1,1,)`, as an example. I'm not sure if that means I've missed a rule in this or not, but as I understand the rules that should be a valid option.

Here's a version using generators, It saves a couple of lines, and memory if the values are really big, but as recursion, generators can be tricky to "get".

``````from __future__ import division
from math import ceil

def make_combos(max_val,target_sum,n_cells):
highest = min(max_val, target_sum - n_cells + 1)
lowest = int(ceil(target_sum/n_cells))
for x in xrange(highest, lowest-1, -1):
if n_cells == 1:
yield (x,)
break
for combo in make_combos(x, target_sum-x, n_cells-1):
yield (x,)+combo

if __name__ == '__main__':
import pprint
pprint.pprint(list(make_combos( 6,12,4)))
``````
Thursday, September 15, 2022
5

The call of `outstr.deleteCharAt` counters the effect of `outstr.append` by deleting the last character of the `outstr`.

Each loop iteration proceeds as follows:

1. append a character
2. print the result
3. perform a recursive invocation at the level `i+1`
4. remove the character we added at step 1
Thursday, September 29, 2022