алгоритм, который будет принимать цифры или слова и находить все возможные комбинации - PullRequest
14 голосов
/ 10 августа 2009

Я ищу алгоритм, который будет принимать числа или слова и находить все возможные варианты их вместе, а также позволю мне определить, сколько значений искать вместе.

Пример: допустим, строка или массив:

cat  
dog  
fish  

тогда результаты для значения 2 могут быть:

cat dog  
cat fish  
dog cat  
dog fish  
fish cat  
fish dog   

ТАК, что результаты из набора из 3 предметов - это 6 возможных вариаций при 2 совпадениях результатов
при совпадении 3 результатов это будет:

cat dog fish  
cat fish dog  
dog cat fish  
dog fish cat  
fish cat dog  
fish dog cat  

... возможно, даже больше вариантов

Я нашел ссылку на Stackoverflow на этот пример, который делает это, но это в javascript, мне интересно, если кто-нибудь знает, как это сделать в PHP, может быть, что-то уже построено?

http://www.merriampark.com/comb.htm (неработающая ссылка)

Ответы [ 3 ]

23 голосов
/ 10 августа 2009

Взгляните на http://pear.php.net/package/Math_Combinatorics

<?php
require_once 'Math/Combinatorics.php';
$words = array('cat', 'dog', 'fish');
$combinatorics = new Math_Combinatorics;
foreach($combinatorics->permutations($words, 2) as $p) {
  echo join(' ', $p), "\n"; 
}

печать

cat dog
dog cat
cat fish
fish cat
dog fish
fish dog
13 голосов
/ 12 июня 2013

Если вы ищете, как что-то подобное работает, вот как я это сделал без библиотек php, использующих бинарный файл.

function search_get_combos($query){
$list = explode(" ", $query);
$bits = count($list); //bits of binary number equal to number of words in query;
//Convert decimal number to binary with set number of bits, and split into array
$dec = 1;
$binary = str_split(str_pad(decbin($dec), $bits, '0', STR_PAD_LEFT));
while($dec < pow(2, $bits)) {
    //Each 'word' is linked to a bit of the binary number.
    //Whenever the bit is '1' its added to the current term.
    $curterm = "";
    $i = 0;
    while($i < ($bits)){
        if($binary[$i] == 1) {
            $curterm .= $list[$i]." ";
        }
        $i++;
    }
    $terms[] = $curterm;
    //Count up by 1
    $dec++;
    $binary = str_split(str_pad(decbin($dec), $bits, '0', STR_PAD_LEFT));
}
return $terms;
}

Обратите внимание, что это вернет только уникальные комбинации, но может быть легко расширено для получения каждого возможного порядка комбинаций, поэтому в вашем примере это выдает:

Array
(
    [0] => fish 
    [1] => dog 
    [2] => dog fish 
    [3] => cat 
    [4] => cat fish 
    [5] => cat dog 
    [6] => cat dog fish 
)

Редактировать (Больше уточнений)

Базовая теория

Итак, во-первых, двоичные числа, как вы, вероятно, знаете, представляют собой строку из 1 и 0. Длина числа - это количество битов, которое оно имеет, например. число 011001 имеет 6 бит (цифры 25, если вы заинтересованы). Затем, если каждый бит числа соответствует одному из терминов, каждый раз, когда он считает, если бит равен 1, термин включается в вывод, тогда как если он равен 0, он игнорируется. Так что это основная теория того, что происходит.

Копаем в код

PHP не имеет возможности считать в двоичном формате, но вы можете преобразовать десятичные дроби в двоичные. Таким образом, эта функция на самом деле считает в десятичном виде и преобразует это в двоичный. Но поскольку число битов важно, поскольку каждому члену нужен свой собственный бит, вам необходимо добавить начальные 0, вот что делает этот бит: str_pad(decbin($dec), $bits, '0', STR_PAD_LEFT)

Теперь эта функция использует цикл while, но, поскольку количество циклов, необходимых для изменения цикла, зависит от количества терминов, нужно выполнить немного математики. Если вы когда-либо работали с двоичным файлом, вы будете знать, что максимальное число, которое вы можете сделать, равно 2 ^ n (где n - количество бит).

Я думаю, что это должно было покрыть все запутанные биты функции, дайте мне знать, если я что-то пропустил.

Посмотрите, что происходит

Используйте следующий код для вывода используемой логики, может показаться немного более понятным, если смотреть таким образом!

function search_get_combos_demo($query){
    $list = explode(" ", $query);
    $bits = count($list);
    $dec = 1;
    while($dec < pow(2, $bits)) {
        $binary = str_split(str_pad(decbin($dec), $bits, '0', STR_PAD_LEFT));
        $curterm = "";
        $i = 0;
        while($i < ($bits)){
            if($binary[$i] == 1) {
                $curterm[] = $list[$i]." ";
            }
            $i++;
        }
        //-----DISPLAY PROCESS-----//
        echo "Iteration: $dec <table cellpadding=\"5\" border=\"1\"><tr>";
        foreach($binary as $b){
            echo "<td>$b</td>";
        }
        echo "</tr><tr>";
        foreach($list as $l){
            echo "<td>$l</td>";
        }
        echo "</tr></table>Output: ";
        foreach($curterm as $c){
            echo $c." ";
        }
        echo "<br><br>";
        //-----END DISPLAY PROCESS-----//
        $terms[] = $curterm;
        $dec++;
    }
    return $terms;
}
0 голосов
/ 13 апреля 2015

Вы можете попробовать этот открытый исходный код для этого. Он реализует итератор. Нажмите

Доступно на PHP, Java.

Вы должны расширить его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...