-2

My goal is to test the solution of a game I created. Like a sudoku, you play with a grid. The grid makes you find a secret combination. The way I create the grid makes it impossible to make sure there is only one possible solution, and if there is more than one the grid is false. So I have to test the grid with all possible combinations. The fastest way to create all combinations is to generate all the possible presences of each possible number of the combination : for example [1,1,1 | 1,2,0 | 3,0,0] if lenght of the combination is 3 and three possible values. With that info I need to use permutation.

Here is the script I wrote :

function recursion($grd_chfr, $pt_chfr, $tab, &$tab_all) {
    if($grd_chfr == 0) {
        $tab_all[] = $tab;
        return;
    }
    for($n = $pt_chfr; $n <= $grd_chfr; $n++) {
        $b = $tab;
        $b[] =  $n;
        recursion($grd_chfr - $n, $n, $b, $tab_all);
    }
}

function permutations(array $elements)
{
    if (count($elements) <= 1) {
        yield $elements;
    } else {
        foreach (permutations(array_slice($elements, 1)) as $permutation) {
            foreach (range(0, count($elements) - 1) as $i) {
                yield array_merge(
                    array_slice($permutation, 0, $i),
                    [$elements[0]],
                    array_slice($permutation, $i)
                );
            }
        }
    }
}

$somme = 7;
$depart = 1;
$entrees = 7;
$tab_all = [];

$time_start = microtime(true);

// I use a recursive function to get every manner to spread values, to fill the combination whose length is $somme
recursion($somme, $depart, [], $tab_all);

$new_tab_all = [];
$count_gen = 0;

//  if the number of possible values to use ($entrees) is higher or smaller than the length of the combination I adjust by adding zeros or by deleting distributions
foreach($tab_all as $tab){
    if(count($tab) < $entrees){
        $count = count($tab);
        for($x = $depart; $x <= $entrees - $count; $x++){
            $tab[] = 0;
        }
        //  I create all possible permutation for each distribution, and that's where there is too much duplicatas
        foreach(permutations($tab) as $combi){
            if(!in_array($combi, $new_tab_all)) {
                $new_tab_all[] = $combi;
            }
        }
    }
    elseif(count($tab) == $entrees){
        $new_tab_all[] = $tab;
    }
}


$time_stop = microtime(true);
echo round(($time_stop - $time_start), 2)."s d'écoulées, ".count($new_tab_all)." solutions (".$count_gen." générées).</br></br>";

I need a script to get every possible unique permutation of a combination. For example, having the array [1,1,2,3], I would like a script returning [[1,1,3,2], [1,3,1,2], [3,1,1,2], [2,1,3,1], [2,3,1,1], [1,3,2,1], [1,1,2,3], ...] an never having twice the same combination.

To make permutations, I use a script but it generates a lot of repetitions with combinations like [1,1,1,1,2,3]. I found it there : Permutations - all possible sets of numbers

function permutations(array $elements)
{
    if (count($elements) <= 1) {
        yield $elements;
    } else {
        foreach (permutations(array_slice($elements, 1)) as $permutation) {
            foreach (range(0, count($elements) - 1) as $i) {
                yield array_merge(
                    array_slice($permutation, 0, $i),
                    [$elements[0]],
                    array_slice($permutation, $i)
                );
            }
        }
    }
}

I also found a script which I think is what I need, but it is scripted in python, and I need it in php. I found it there : permutations with unique values

class unique_element:
    def __init__(self,value,occurrences):
        self.value = value
        self.occurrences = occurrences

def perm_unique(elements):
    eset=set(elements)
    listunique = [unique_element(i,elements.count(i)) for i in eset]
    u=len(elements)
    return perm_unique_helper(listunique,[0]*u,u-1)

def perm_unique_helper(listunique,result_list,d):
    if d < 0:
        yield tuple(result_list)
    else:
        for i in listunique:
            if i.occurrences > 0:
                result_list[d]=i.value
                i.occurrences-=1
                for g in  perm_unique_helper(listunique,result_list,d-1):
                    yield g
                i.occurrences+=1




a = list(perm_unique([1,1,2]))
print(a)

I don't know how to translate the second code in php, or how to modify the first code to exclude repetitions.

  • Rather than asking a question for which the answer is the solution, try to come up with a question that will help YOU find the solution. 1. It's much easier to learn that way. 2. I think the goal here should be to learn how to come up with the solution yourself. As a general rule of thumb, when you ask a question, think about weather the answer will help you find the solution, or the answer to your question is the solution. The former will likely get you more help than the latter. And if you could post a snippet of your own attempt at converting the code to php, that would be even better. – Callan Jul 03 '19 at 22:48

1 Answers1

0
  • You start with an original collection, lets say [a, b, a]
  • now you need to parse the collection
  • for each unique element of the collection, you create a list started by the current element and followed by the permutation of the collection minus the current element (repetition allowed here) like this: pseudo code of the permutation recursive algorithm