简体   繁体   English

如何在没有重复的情况下进行排列?

[英]How to make a permutation without the repetitions?

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,1,1 | 1,2,0 | 1,2,0 | 3,0,0] if lenght of the combination is 3 and three possible values. 3,0,0] 如果组合的长度是 3 和三个可能的值。 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.例如,有数组 [1,1,2,3],我想要一个返回 [[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], ...] 从来没有两次相同的组合。

To make permutations, I use a script but it generates a lot of repetitions with combinations like [1,1,1,1,2,3].为了进行排列,我使用了一个脚本,但它会生成大量重复,例如 [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.我还找到了一个我认为是我需要的脚本,但它是用 python 编写的,而我需要它在 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.我不知道如何翻译php中的第二个代码,也不知道如何修改第一个代码以排除重复。

  • You start with an original collection, lets say [a, b, a]你从一个原始集合开始,比如说 [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对于集合的每个唯一元素,您创建一个由当前元素开始的列表,然后是集合的置换减去当前元素(此处允许重复),如下所示:置换递归算法的伪代码

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM