Моя цель - проверить решение созданной мной игры. Как судоку, вы играете с сеткой. Сетка заставляет вас найти секретную комбинацию. Способ, которым я создаю сетку, делает невозможным убедиться, что существует только одно возможное решение, и если их несколько, сетка ложна. Поэтому я должен проверить сетку со всеми возможными комбинациями. Самый быстрый способ создать все комбинации - это сгенерировать все возможные присутствия каждого возможного числа комбинаций: например, [1,1,1 | 1,2,0 | 3,0,0], если длина комбинации составляет 3 и три возможных значения. С этой информацией мне нужно использовать перестановку.
Вот сценарий, который я написал:
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>";
Мне нужен скрипт, чтобы получить все возможные уникальные перестановки комбинации.
Например, имея массив [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], ...] никогда не имеющие дважды одна и та же комбинация.
Для создания перестановок я использую скрипт, но он генерирует много повторений с такими комбинациями, как [1,1,1,1,2,3].
Я нашел это там: Перестановки - все возможные наборы чисел
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)
);
}
}
}
}
Я также нашел скрипт, который, как мне кажется, мне нужен, но он написан на python, и он мне нужен в php.
Я нашел это там: перестановок с уникальными значениями
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)
Я не знаю, как перевести второй код в php или как изменить первый код, чтобы исключить повторы.