Задача состоит в том, чтобы перечислить все упорядоченные разбиения (состав (комбинаторика)) заданного положительного целого числа n
. Эти списки чисел от 1
к n
которой сумма n
. Например, при заданном входе n = 4
результат должен быть:
4
1, 3
3, 1
2, 2
2, 1, 1
1, 2, 1
1, 1, 2
1, 1, 1, 1
Результат может быть в любом порядке, но должен содержать каждый заказанный раздел один раз. Это означает , что для n = 4
, [1, 1, 2]
, [1, 2, 1]
и [2, 1, 1]
все должны быть частью результата.
Вот мой собственный код JavaScript, который достигает этого:
function range(n) {
for (var range = [], i = 0; i < n; range.push(++i));
return range;
}
function composition(n) {
return n < 1 ? [[]] : range(n).map(function(i) {
return composition(n - i).map(function(j) {
return [i].concat(j);
});
}).reduce(function(a, b) {
return a.concat(b);
});
}
Golf6, ES6 ( 169 167 119 109 105 89 85 байт ):
n=>n?[].concat(...[...Array(n)].map((x,i)=>i+1).map(b=>m(n-b).map(a=>[b,...a]))):[[]]
Ответы:
Pyth,
76 байтов7-байтовое решение:
Pyth имеет встроенное целочисленное разбиение
./
, поэтому 5 из 7 байтов получают порядки.Попробуйте онлайн!
Объяснение:
6-байтовое решение:
Если у вас есть список,
./
будет рассчитывать с заказами; Осталось только снова составить номера списков.Попробуйте онлайн!
Объяснение:
источник
Haskell, 37 байт
xnor сохранил два байта.
источник
f n=[a:x|a<-[1..n],x<-f$n-a]
короче.given positive integer n ... numbers from 1 to n
)f 0=[[]]
просто случай короче, чемf 1=[[1]]
:)Python, 56 байт
Рекурсивное решение: Заказанные разбиения
n
являются разбиением некоторых небольшимi
с0<=i<n
последующим остатком вn-i
качестве последнего элемента. Для базового случаяn=0
имеет только пустой раздел.источник
Python 2, 61 байт
Это не самый короткий, но мне очень нравится метод, потому что он такой странный.
Рекурсивно генерирует и оценивает
2**(n-1)
строки, такие какдля
n=4
. Эти строки оцениваются как кортежи, представляющие все разделы. Между любыми двумя единицами есть или+
, объединяющий их в одно число, или,
, разделяющий соседние секции.источник
import re
lambda n:map(lambda n:map(len,re.finall('10*',bin(n))),range(1<<n-1,1<<n))
JavaScript (Firefox 30-57), 63 байта
источник
f=n=>n<2?[[1]]:f(n-1).map(([n,...a])=>r.push([1+n,...a],[1,n,...a]),r=[])&&r
.Mathematica, 40 байт
Встроенные в Mathematica целочисленные разделы не дают всех упорядоченных разделов, поэтому мы должны сгенерировать все возможные перестановки каждого из них, а затем сгладить результат.
источник
CJam ,
1714 байтовПопробуйте онлайн!
объяснение
Я знаю, что сказал, что использование декартового произведения дольше, но в итоге я нашел способ использовать его более эффективно. Я думаю, что оба подхода интересны сами по себе, поэтому я помещаю их в отдельные посты.
Это по-прежнему основано на идее, что мы можем выбирать
n
время между добавлением a1
к текущему разделу или увеличением последнего элемента текущего раздела. В этом решении мы делаем это путем генерации 2 n-1 различных программ, которые соответствуют этим различным вариантам.источник
)
». Поэтому я добавилed
и протестировал. +1 за творческое злоупотребление ошибкой.Желе ,
76 байт-1 байт благодаря @Dennis (конвертировать из унарного
ḅ1
, а не по сумме для каждого для каждогоS€€
)TryItOnline
Как?
источник
Чистый Баш, 51
Это порт блестящего ответа @ xnor , использующего несколько уровней расширений bash для достижения желаемого результата:
Ideone.
$a
содержащей нули,1
за которыми следуютn-1
нули.${a//0/{+,']\ $[}1'}
заменяет каждое0
в$a
копиями строки{+,']\ $[}1'
. Таким образом, n = 4, мы получаем строку1{+,']\ $[}1'{+,']\ $[}1'{+,']\ $[}1'
$[
и постфиксом,],
чтобы дать$[1{+,']\ $[}1'{+,']\ $[}1'{+,']\ $[}1]
$[1+1+1+1], $[1+1+1] 1, $[1+1] $[1+1], $[1+1] 1 1,...
Тщательное использование кавычек, экранирование от обратной косой черты и
eval
гарантирует, что расширения происходят в правильном порядке.источник
Рубин, 61 байт
ungolfed
использование
источник
x<<i
короче чем[i]+x
..flatten(1)
не.flatten 1
?Брахилог , 20 байт
Попробуйте онлайн!
объяснение
В такой ситуации можно подумать, что декларативные языки будут
+
хорошими , но из-за перегрузки и трудностей в написании предиката суммирования, который правильно распространяет ограничения, они этого не делают.источник
L
будет между 1 и вводом.+
также работает с одним целым числом, мне нужно заставить.
быть списком##
, а так как+
также работает со списком списков, мне нужно навязать, что элементы.
являются целыми числами:#$a
.CJam , 19 байтов
Попробуйте онлайн!
объяснение
CJam не имеет полезной встроенной комбинаторики для целочисленных разделов. Поэтому мы сделаем это вручную. Чтобы найти все упорядоченные разделы целого числа
n
, мы можем посмотреть список изn
них и рассмотреть все возможные способы вставки разделителей. Тогда мы будем суммировать1
s в каждом разделе. Пример дляn = 3
:Я попытался использовать декартово произведение для генерации всех этих разделителей, но в итоге получилось 21 байт. Вместо этого я вернулся к этому старому способу генерации наборов мощности (он основан на старом ответе Денниса, но я не могу найти его сейчас). Идея такова: для генерации всех разделов мы можем начать с пустого списка. Затем
n
мы можем принять двоичное решение: либо мы добавляем1
(соответствует разделителю в приведенном выше примере), либо увеличиваем последнее значение в списке (соответствует отсутствию разделителя). Чтобы сгенерировать все разделы, мы просто выполняем обе операции на каждом шаге и сохраняем все возможные выходные данные для следующего шага. Оказывается, в CJam добавление и добавление первого элемента короче, но принцип остается тем же:источник
T-SQL, 203 байта
Golfed:
Ungolfed:
скрипка
источник
Mathematica 10,0, 44 байта
Попытка без использования встроенных разделов. Из каждого упорядоченного раздела размера k генерируются два последующих раздела k + 1 : один с добавлением 1, а другой путем увеличения первого значения.
Более смешной, но, к сожалению, на 2 байта более длинный способ реализации той же идеи:
источник
MapAt
индекс на -1.05AB1E ,
1412 байтСохранено 2 байта благодаря Аднану
объяснение
Попробуйте онлайн!
Соответствующее решение на 2 байта короче на 2sable .
2sable , 10 байт
Попробуйте онлайн!
источник
—
вместоiy,
:).Haskell, 41 байт
Не самое короткое решение на Haskell, но мне нравится, что оно не использует
[..]
диапазоны. Вместо этого он рекурсивно вычисляет разделыn
как разделыn-1
либо с новым 1 в начале, либо с первым более высоким значением. Это ясно дает понять, почему они есть2^(n-1)
.источник
Mathematica, 53 байта
Не
IntegerPartitions
превосходит ответ Мартина Эндера, который использует встроенную функцию (а встроенные функции меня вполне устраивают). (И при этом это не бьет ответ feersum, который я не видел слишком поздно.) Но я хотел практиковать рекурсивную функцию игры в гольф.Рекурсивно генерирует все композиции, генерируя все возможные конечные числа
j
и затем вызывая себя,#-j
где#
находится ввод.источник
Array
вместо негоTable
и избегаяAppend
, используя список иApply
:±0={{}};±n_:=Join@@Array[{##,n-+##}&@@@±#&,n,0]
@@
?f@@g[a,b]
оценивает доf[a,b]
. Здесь мы используем тот факт, что список вроде{ { {1,1,1}, {2,1} } , { {1,2} }, { {3} } }
невидимо имеет головуList
; поэтому имеетJoin@@{ { {1,1,1}, {2,1} } , { {1,2} }, { {3} } }
значение имеетJoin@@List[ { {1,1,1}, {2,1} } , { {1,2} }, { {3} } ]
значение имеетJoin[ { {1,1,1}, {2,1} } , { {1,2} }, { {3} } ]
значение{ {1,1,1}, {2,1}, {1,2}, {3} }
.Сетчатка , 32 байта
Число байтов предполагает кодировку ISO 8859-1.
Попробуйте онлайн!
объяснение
Это работает аналогично моему ответу CJam . Мы просматриваем список
N
и в каждой позиции принимаем обе ветви двоичного решения: а) увеличиваем последнее значение или б) начинаем новое значение с 1.Этап 1
Преобразовать ввод в унарный.
Этап 2
+
Говорит Retina , чтобы выполнить этот этап в цикле , пока выход не перестанет изменяться. Он%
говорит, что нужно разделить ввод на строки перед применением сцены и затем соединить их вместе. Помещая%
после+
, Retina разделяется и возвращается после каждой итерации. Одна итерация этапа принимает одно из упомянутых мною решений и тем самым раздваивает текущий набор разделов.Как это работает на самом деле, так это то, что он соответствует
1
(но только первому, как указано1
перед обратным трюком) и заменяет его на!
(который мы будем использовать в качестве унарной цифры нашего вывода), за которым следуют оставшиеся1
s в этой строке (это увеличивает последнее значение). Затем в другой строке (¶
) он печатает префикс текущей строки, затем следует,!
, который вставляет разделитель и затем начинает следующее значение в1
.Этап 3
Это преобразует ряды
!
в десятичные целые числа, заменяя их длиной.Этап 4
И наконец, мы замечаем, что мы сгенерировали вдвое больше строк, чем мы хотели, и половина из них начинаются с
,
(те, где мы изначально приняли решение о разделении, даже если после этого еще не было чего разделять). Поэтому мы отбрасываем все строки, начинающиеся с,
.источник
Perl, 44 байта
Включает +3 для
-n
(код использует$'
и$0
поэтому не может быть запущен как-e
командная строка)Дайте номер разделу на STDIN:
partitions.pl
Если вы не возражаете против лишних пробелов в конце строки и дополнительной новой строки, это 42-байтовое решение также работает (запустите как
perl -M5.010 partitions.pl
):источник
Юлия, 113 байт
Нерекурсивное решение
Разъяснение:
[vcat([1 for _=i+1:N],sum([1 for _=N-i:N-1])) for i=1:N]
построить набор списков с суммой N, перестановки которых будут напоминать решение (например, для N = 4: [[1,1,1,1], [1,1,2], [1,3], [4] ]])map(x->[permutations(x)...],)
Рассчитать все перестановкиreduce(vcat,)
объединить их в список списковunique()
фильтрация дубликатовисточник
N
качестве входных данных. Вы можете сделать лямбда-функцию, добавивN->
3 байта.f(N)=
потерял при копировании, у меня это было при подсчете байтовMATL , 15 байт
Попробуйте онлайн!
объяснение
Учитывая входные данные
n
, это вычисляет декартову силу с увеличением показателейk
от1
доn
; и для каждого показателяk
выбирает кортежи, которые имеют сумму, равную входным.источник
Lua
214203182 байтаРаскрытая версия.
Найдены пустые пробелы и удалены ненужные переменные в безопасные 11 байтов. как оказалось, table.insert () неэффективен
источник
PHP, 125 байт
-4 байта для
print_r($r);
вместо вместоecho json_encode($r);
для выводарекурсивное решение с 250 байтами
источник
Пролог, 81 байт + 6 байт для вызова
Попробуйте онлайн!
Позвоните
[4]*L.
, повторите,;
пока все решения не будут представлены.Альтернативно, если многократное нажатие
;
не в порядке (или должно быть добавлено к количеству байтов), вызов сbagof(L,[4]*L,M).
которым добавляет 17 байтов для вызова.источник
J ,
3026 байтРаботает, разбивая список унарных n , используя двоичные значения 2 n .
Попробуйте онлайн!
объяснение
источник
На самом деле,
1716 байтЭтот ответ частично основан на ответе Луиса Мендо на MATL . Предложения по игре в гольф приветствуются. Попробуйте онлайн!
Ungolfing
источник
На самом деле
171615 байтЭто интересный ответ CJam Мартина Эндера (тот, что содержит декартово произведение), с разницей в реализации, которая, на мой взгляд, была интересной. Когда одна из строк Мартина начинается с приращения, ошибки не позволяют оценить эту строку. На самом деле, ошибка подавляется, и строка все равно оценивается. Это в конечном итоге дает композиции каждого
k
в диапазоне[1..n]
.Вместо того, чтобы пытаться удалить лишние композиции, я взял
n-1
декартову силу"1u"
добавления a"1"
в начало каждой строки. Этот трюк дает только композицииn
. Это, к сожалению, дольше, чем ответ Мартина.Предложения по игре в гольф приветствуются. Попробуйте онлайн!
Ungolfing
источник