Есть например десять стульев. (допустим подписаны номерами от одного до десяти) Нужно узнать сколько максимум разных уникальных комбинаций по три стула можно сделать с этих десяти и вывести все эти комбинации. (не должно быть двух комбинаций, где будет два одних и тех же стульев) п/с с института припоминаю, что это комбинации с 10 по 3 без перестановок как на пхп красиво решить задачу и вывести все возможные уникальные комбинации? Спасибо!
где n = 10 и m = 3 что такое восклицательный знак я не знаю. взято отсюда http://www.mathelp.spb.ru/book2/tv3.htm
Это только посчитать количество. Я бы тупо запустил рандом, а когда за миллион итераций не найдено ни одной новой комбинации - break xD Потом их все сохранить, и в будущем использовать в роли радужной таблицы.
восклицательный знак - это знак факториала как мне средствами пхп получить все эти уникальные варианты наборов?
если верить гуглу, то из 10 по 3 можно сделать 120 разных вариантов что-то вроде не тоhttp://www.google.com.ua/search?hl=...l0l163875l16l16l0l0l0l0l381l2913l0.4.7.1l12l0
inline Из 10 по 3 - будет 120 вариантов. PHP: <?php // Группировать по: $combineBy = 3; // Список элементов для группировки $elements = array( 'Стул 1', 'Стул 2', 'Стул 3', 'Стул 4', 'Стул 5', 'Стул 6', 'Стул 7', 'Стул 8', 'Стул 9', 'Стул 10' ); $total = count($elements); $max = $total - 1; // Нельзя сгруппировать 2 элемента по 3 if($combineBy > $total) exit("Невозможно сгруппировать {$total} элементов по {$combineBy}"); function fact($i = 1) { if($i === 0) return 1; else return $i * fact($i - 1); } function move($i = 0) { global $max, $right, $current; if($current[$i] >= $max - ($right - $i)) { move($i - 1); } else { ++$current[$i]; if($i < $right) { $k = 1; for($j = $i + 1; $j <= $right; ++$j, ++$k) $current[$j] = $current[$i] + $k; } } } $comb = 0; $combs = (fact($total) / (fact($combineBy) * fact($total - $combineBy))); $result = array(); $right = $combineBy - 1; $current = range(0, $right); while($comb < $combs) { $result[] = $current; ++$comb; if($comb < $combs) move($right); } header('Content-type: text/plain; charset=UTF-8'); foreach($result as $res) { $row = array(); for($i = 0; $i < $combineBy; ++$i) $row[$i] = $elements[$res[$i]]; echo(implode(' + ', $row) . "\n"); } ?> И ни одной лишней итерации
sobachnik Вы возможно не правильно поняли Нужно без повторов меньших пар Стул 1 + Стул 4 + Стул 7 Стул 1 + Стул 4 + Стул 8 Стул 1 + Стул 4 не должно быть в двух наборах и принимаем то, что Стул 4 + Стул 1 это тоже, что и Стул 1 + Стул 4 то есть перестановка в наборе не уникализирует набор
Так и есть в скрипте, который я привёл. Он покажет комбинацию 123, но не покажет 132, 213, 231, 312, 321. Вот это странно, если честно...
inline Да, скрипт выдал именно то, что и должен был. Ну просто странно )) Выходит, тебе уже не уникальные комбинации (сочетания) надо получить, а ещё со своими доп. требованиями, чтобы в каждой комбинации не было двух одинаковых. А так-то все сочетания, в которых есть и стул 1 и стул 4 - они уникальны, поскольку третий стул в них во всех разный Сочетания же по три ты писал, вроде. Если теперь я тебя правильно понимаю, то тебе нужно что-то типа такого получить? Код (Text): 1 2 3 1 4 5 1 6 7 1 8 9 2 4 6 2 5 7 2 8 10 3 4 7 3 5 6 3 9 10 Но тут, например, нету [3 4 5] - это потому, что вот я начал разбирать сперва все, которые начинаются на 1, а ты (где-то выше, где ты писал 123 345 ...) после [1 2 3] сразу перешёл к [3 4 5]. Здесь нету [3 4 5], потому как раньше, чем я дошёл до [3 X X], у меня уже было [1 4 5]. То есть эти комбинации/сочетания могут быть разными, в зависимости от того, с каких начнёшь считать.
sobachnik не могу уловить логику, чтобы это запрограмировать по проще идея сейчас есть только такая из 10 елементов рандомно клепать массивы по три елемента и сравнивать вновь созданный с уже имеющимися уникальными может как то проще можно?
Ну, для составления такого списка: Код (Text): 1 2 3 1 4 5 1 6 7 1 8 9 2 4 6 2 5 7 2 8 10 3 4 7 3 5 6 3 9 10 Я воспользовался сперва тем скриптом, который в первом примере (который возвращает все уникальные сочетания, 120 в данном случае), но перед выводом результата - прошёлся по нему и выбросил все те, в которых есть 2 повторяющихся элемента.
Код (Text): 1 2 3 1 4 5 1 6 7 1 8 9 2 4 10 2 5 6 2 7 8 3 4 6 3 5 7 3 8 10 4 1 6 4 7 9 5 4 8 13 ня. Надо только найти как посчитать
[vs] Тоже обратил внимание, что в зависимости от того, как начать - тут получатся не только разные сочетания, но и разное их количество. Просто интересно, ты именно составил алгоритм, который найдёт максмальное количество таких сочетаний или это просто один из вариантов и возможно при каком-то другом раскладе их может быть и больше? И вообще, существует ли такой алгоритм, или можно только перебрать все возможные варианты (пробуем начать с [1 2 X], потом с [1 3 X] и так далее) и проверить потом, в каком из вариантов больше решений?