За последние 24 часа нас посетили 16710 программистов и 1679 роботов. Сейчас ищут 805 программистов ...

Получить все уникальные комбинации

Тема в разделе "PHP для новичков", создана пользователем inline, 27 дек 2011.

  1. inline

    inline Активный пользователь

    С нами с:
    21 май 2010
    Сообщения:
    466
    Симпатии:
    0
    Есть например десять стульев. (допустим подписаны номерами от одного до десяти)
    Нужно узнать сколько максимум разных уникальных комбинаций по три стула можно сделать с этих десяти и вывести все эти комбинации. (не должно быть двух комбинаций, где будет два одних и тех же стульев)
    п/с с института припоминаю, что это комбинации с 10 по 3 без перестановок
    как на пхп красиво решить задачу и вывести все возможные уникальные комбинации?
    Спасибо!
     
  2. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
  3. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Это только посчитать количество.
    Я бы тупо запустил рандом, а когда за миллион итераций не найдено ни одной новой комбинации - break xD
    Потом их все сохранить, и в будущем использовать в роли радужной таблицы.
     
  4. inline

    inline Активный пользователь

    С нами с:
    21 май 2010
    Сообщения:
    466
    Симпатии:
    0
    восклицательный знак - это знак факториала
    как мне средствами пхп получить все эти уникальные варианты наборов?
     
  5. inline

    inline Активный пользователь

    С нами с:
    21 май 2010
    Сообщения:
    466
    Симпатии:
    0
  6. inline

    inline Активный пользователь

    С нами с:
    21 май 2010
    Сообщения:
    466
    Симпатии:
    0
    набирать 10!/(3!*(10-3)!) в гугле
     
  7. inline

    inline Активный пользователь

    С нами с:
    21 май 2010
    Сообщения:
    466
    Симпатии:
    0
    из 10 по 3
    пока уникальных получилось только
    123
    456
    789
    147
    258
    369
    10 7 6
    1 5 9

    так на вскидку
     
  8. sobachnik

    sobachnik Старожил

    С нами с:
    20 апр 2007
    Сообщения:
    3.380
    Симпатии:
    13
    Адрес:
    Дмитров, МО
    inline
    Из 10 по 3 - будет 120 вариантов.
    PHP:
    1. <?php
    2. // Группировать по:
    3. $combineBy = 3;
    4. // Список элементов для группировки
    5. $elements = array(
    6.     'Стул 1', 'Стул 2', 'Стул 3', 'Стул 4', 'Стул 5',
    7.     'Стул 6', 'Стул 7', 'Стул 8', 'Стул 9', 'Стул 10'
    8. );
    9.  
    10. $total = count($elements);
    11. $max = $total - 1;
    12. // Нельзя сгруппировать 2 элемента по 3
    13. if($combineBy > $total)
    14.     exit("Невозможно сгруппировать {$total} элементов по {$combineBy}");
    15.  
    16. function fact($i = 1) {
    17.     if($i === 0)
    18.         return 1;
    19.     else
    20.         return $i * fact($i - 1);
    21. }
    22. function move($i = 0) {
    23.     global $max, $right, $current;
    24.     if($current[$i] >= $max - ($right - $i)) {
    25.         move($i - 1);
    26.     } else {
    27.         ++$current[$i];
    28.         if($i < $right) {
    29.             $k = 1;
    30.             for($j = $i + 1; $j <= $right; ++$j, ++$k)
    31.                 $current[$j] = $current[$i] + $k;
    32.         }
    33.     }
    34. }
    35.  
    36.  
    37. $comb = 0;
    38. $combs = (fact($total) / (fact($combineBy) * fact($total - $combineBy)));
    39. $result = array();
    40. $right = $combineBy - 1;
    41. $current = range(0, $right);
    42.  
    43. while($comb < $combs) {
    44.     $result[] = $current;
    45.     ++$comb;
    46.     if($comb < $combs)
    47.         move($right);
    48. }
    49.  
    50. header('Content-type: text/plain; charset=UTF-8');
    51. foreach($result as $res) {
    52.     $row = array();
    53.     for($i = 0; $i < $combineBy; ++$i)
    54.         $row[$i] = $elements[$res[$i]];
    55.     echo(implode(' + ', $row) . "\n");
    56. }
    57. ?>
    И ни одной лишней итерации :)
     
  9. inline

    inline Активный пользователь

    С нами с:
    21 май 2010
    Сообщения:
    466
    Симпатии:
    0
    sobachnik
    Вы возможно не правильно поняли

    Нужно без повторов меньших пар

    Стул 1 + Стул 4 + Стул 7
    Стул 1 + Стул 4 + Стул 8


    Стул 1 + Стул 4 не должно быть в двух наборах

    и принимаем то, что
    Стул 4 + Стул 1
    это тоже, что и Стул 1 + Стул 4
    то есть перестановка в наборе не уникализирует набор
     
  10. sobachnik

    sobachnik Старожил

    С нами с:
    20 апр 2007
    Сообщения:
    3.380
    Симпатии:
    13
    Адрес:
    Дмитров, МО
    Так и есть в скрипте, который я привёл.
    Он покажет комбинацию 123, но не покажет 132, 213, 231, 312, 321.
    Вот это странно, если честно...
     
  11. inline

    inline Активный пользователь

    С нами с:
    21 май 2010
    Сообщения:
    466
    Симпатии:
    0
    У меня Ваш скрипт выдал
     
  12. inline

    inline Активный пользователь

    С нами с:
    21 май 2010
    Сообщения:
    466
    Симпатии:
    0
    inline писал(а):
    Стул 1 + Стул 4 не должно быть в двух наборах

    что именно Вы имеете ввиду?
     
  13. sobachnik

    sobachnik Старожил

    С нами с:
    20 апр 2007
    Сообщения:
    3.380
    Симпатии:
    13
    Адрес:
    Дмитров, МО
    inline
    Да, скрипт выдал именно то, что и должен был.
    Ну просто странно :))) Выходит, тебе уже не уникальные комбинации (сочетания) надо получить, а ещё со своими доп. требованиями, чтобы в каждой комбинации не было двух одинаковых.
    А так-то все сочетания, в которых есть и стул 1 и стул 4 - они уникальны, поскольку третий стул в них во всех разный :) Сочетания же по три ты писал, вроде.

    Если теперь я тебя правильно понимаю, то тебе нужно что-то типа такого получить?
    Код (Text):
    1. 1 2 3
    2. 1 4 5
    3. 1 6 7
    4. 1 8 9
    5. 2 4 6
    6. 2 5 7
    7. 2 8 10
    8. 3 4 7
    9. 3 5 6
    10. 3 9 10
    Но тут, например, нету [3 4 5] - это потому, что вот я начал разбирать сперва все, которые начинаются на 1, а ты (где-то выше, где ты писал 123 345 ...) после [1 2 3] сразу перешёл к [3 4 5]. Здесь нету [3 4 5], потому как раньше, чем я дошёл до [3 X X], у меня уже было [1 4 5]. То есть эти комбинации/сочетания могут быть разными, в зависимости от того, с каких начнёшь считать.
     
  14. inline

    inline Активный пользователь

    С нами с:
    21 май 2010
    Сообщения:
    466
    Симпатии:
    0
    sobachnik
    не могу уловить логику, чтобы это запрограмировать по проще

    идея сейчас есть только такая
    из 10 елементов рандомно клепать массивы по три елемента и сравнивать вновь созданный с уже имеющимися уникальными

    может как то проще можно?
     
  15. sobachnik

    sobachnik Старожил

    С нами с:
    20 апр 2007
    Сообщения:
    3.380
    Симпатии:
    13
    Адрес:
    Дмитров, МО
    Ну, для составления такого списка:
    Код (Text):
    1. 1 2 3
    2. 1 4 5
    3. 1 6 7
    4. 1 8 9
    5. 2 4 6
    6. 2 5 7
    7. 2 8 10
    8. 3 4 7
    9. 3 5 6
    10. 3 9 10
    Я воспользовался сперва тем скриптом, который в первом примере (который возвращает все уникальные сочетания, 120 в данном случае), но перед выводом результата - прошёлся по нему и выбросил все те, в которых есть 2 повторяющихся элемента.
     
  16. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Код (Text):
    1. 1 2 3
    2. 1 4 5
    3. 1 6 7
    4. 1 8 9
    5. 2 4 10
    6. 2 5 6
    7. 2 7 8
    8. 3 4 6
    9. 3 5 7
    10. 3 8 10
    11. 4 1 6
    12. 4 7 9
    13. 5 4 8
    13 ня. Надо только найти как посчитать
     
  17. sobachnik

    sobachnik Старожил

    С нами с:
    20 апр 2007
    Сообщения:
    3.380
    Симпатии:
    13
    Адрес:
    Дмитров, МО
    [vs]
    Тоже обратил внимание, что в зависимости от того, как начать - тут получатся не только разные сочетания, но и разное их количество. Просто интересно, ты именно составил алгоритм, который найдёт максмальное количество таких сочетаний или это просто один из вариантов и возможно при каком-то другом раскладе их может быть и больше? И вообще, существует ли такой алгоритм, или можно только перебрать все возможные варианты (пробуем начать с [1 2 X], потом с [1 3 X] и так далее) и проверить потом, в каком из вариантов больше решений?