Номер разбиения положительного целого числа определяется как количество способов, которыми оно может быть выражено как сумма положительных целых чисел. Другими словами, количество целочисленных разделов у него есть. Например, номер 4
имеет следующие разделы:
[[1, 1, 1, 1], [1, 1, 2], [1, 3], [2, 2], [4]]
Следовательно, у него есть 5
разделы. Это OEIS A000041 .
задача
По положительному целому числу N определить номер его раздела.
Все стандартные правила применяются.
Ввод и вывод могут быть обработаны любым разумным способом.
Это код-гольф , поэтому выигрывает самый короткий код в байтах.
Тестовые случаи
Вход | Выход 1 | 1 2 | 2 3 | 3 4 | 5 5 | 7 6 | 11 7 | 15 8 | 22 9 | 30 10 | 42
code-golf
math
number-theory
combinatorics
integer-partitions
Мартин Эндер
источник
источник
Ответы:
Pyth , 3 байта
Попробуй это здесь! или попробуйте тестовый пакет.
Форматирование ответа заняло гораздо больше времени, чем написание самого кода: P.
Как?
Pyth - правильный инструмент для работы.
источник
Mathematica, 11 байт
объяснение
источник
Python 2 ,
8583 байта-2 байта благодаря @notjagan
Попробуйте онлайн!
Использование рекурсивной формулы из OEIS A000041 .
источник
==0
эквивалентно<1
в этом случае. РЕДАКТИРОВАТЬ: Используйте подход Notjagan<1
вместо==0
, но код TIO этого не сделал.Эмоджикод 0,5,
204201 байтПопробуйте онлайн!
-3 байта, используя «меньше или равно 1» вместо «меньше 2», потому что эмодзи «меньше чем» имеет довольно длинную кодировку UTF-8. Также сделал
t
заморозку, чтобы заставить замолчать предупреждение, не влияя на количество байтов.Расширяет класс inte (целое число) методом с именем 🅰️. Вы можете написать простую программу, которая берет число из ввода, вызывает 🅰️ на номер и печатает результат следующим образом:
Эту часть можно много сыграть, пропуская сообщения и обработку ошибок, но она не включена в счет, поэтому я предпочитаю показывать больше возможностей Emojicode, одновременно улучшая читабельность по пути.
Ungolfed
объяснение
Примечание: большой выбор смайликов не имеет особого смысла в смайликах 0.5. В конце концов, это 0.x 0.6 исправит это.
Emojicode - это объектно-ориентированный язык программирования, включающий в себя шаблоны, протоколы, дополнительные функции и замыкания, но эта программа не использует замыканий, и все шаблоны и протоколы могут считаться неявными, тогда как в заглушке ввода-вывода отображается только дополнительная опция.
Программа работает только с несколькими типами: 🚂 является целочисленным типом, 🔡 является типом строки и ⏩ является типом диапазона. Также появляется несколько логических значений (👌), но они используются только в условиях. Логические значения могут принимать значения 👍 или 👎, которые соответствуют истинам и ложностям соответственно.
В настоящее время в Emojicode нет операторов, поэтому сложение, сравнения и другие операции, которые обычно являются операторами, реализованы в виде функций, эффективно позволяя выражениям использовать префиксную нотацию . Операторы также запланированы в 0,6.
Давайте сначала займемся тестовой программой.
Это блок 🏁, который можно сравнить с основным из других языков.
Виноград и арбузы объявляют кодовые блоки в смайлик.
Это объявляет «замороженное» имя
str
и устанавливает его значение для новой строки, созданной с использованием инициализатора (конструктора) 😯, который принимает приглашение в виде строки, а затем вводит строку от пользователя. Зачем использовать замороженную вместо переменной? Это не изменится, поэтому переменная выдаст предупреждение.Давайте разберемся с этим.
🚂str 10
вызывает метод on для объектаstr
с аргументом 10. По соглашению, методы, названные с именем типа, преобразуют объект в этот тип. 10 - это база для целочисленного преобразования. Этот метод возвращает необязательный🍬🚂
. Необязательные могут содержать значение базового типа или пустоты, ⚡. Если строка не содержит числа, возвращается ⚡. Чтобы использовать значение, необходимо развернуть необязательное значение с помощью 🍺, что вызывает ошибку времени выполнения, если значение равно ⚡. Следовательно, хорошей практикой является проверка на пустоту перед развертыванием необязательного. Фактически, это так часто, что у Emojicode есть сокращение для этого. Обычно🍊
это «если».🍊🍦 variable expression
означает: оценить выражение. Если необязательный элемент содержит пустоту, условие оценивается как 👎 (false). В противном случае, замороженное имяvariable
создается с развернутым значением необязательного значения, а условие оценивается как 👍 (true). Поэтому при нормальном использовании🍇 ... 🍉
вводится блок, следующий за условным.🅰️ - это метод, к которому основной код добавляет 🚂 с помощью 🐋, который вычисляет количество разделов. Это вызывает 🅰️ для
num
замороженного объекта, который мы объявили в условном выражении, и преобразует результат в строку, используя базу 10 методом 🔡. Затем 😀 печатает результат.🍓 означает «еще», поэтому этот блок вводится, когда пользователь неправильно ввел номер.
Печатает строковый литерал.
Теперь давайте посмотрим на основную программу. Я объясню неоправданную версию; В версии для гольфа только что были удалены пробелы и переменные переименованы в одинарные буквы.
Расширьте класс 🚂. Это функция, которая не часто встречается в языках программирования. Вместо создания нового класса с 🚂 в качестве суперкласса, 🐋 изменяет 🐋 напрямую.
Создает новый метод с именем 🅰️, который возвращает 🚂. Возвращает количество разделов, рассчитанное по формуле
a(n) = (1/n) * Sum_{k=0..n-1} sigma(n-k)*a(k)
🐕 аналогичен
this
илиself
из других языков и относится к объекту метод был вызван. Эта реализация является рекурсивной, так что это условие завершения: если число, для которого был вызван метод, меньше или равно 1, вернуть 1.Создайте новую переменную
sum
и установите для нее значение 0. Неявно предполагается тип type.🔂 перебирает все, что реализует протокол 🔂🐚⚪️, тогда как ⏩ является литералом диапазона, который реализуется implement. Диапазон имеет начальное значение, конечное значение и значение шага, которое предполагается равным 1, если
start < stop
, или -1 в противном случае. Можно также указать значение шага, используя ⏭, чтобы создать литерал диапазона. Начальное значение является включающим, а конечное значение - исключительным, поэтому оно эквивалентноfor k in range(n)
илиSum_{k=0..n-1}
в формуле.Нам нужно вычислить сигма (n - k) или сумму делителей
n - k
другими словами, и аргумент необходим несколько раз, поэтому он сохраняетсяn - k
в переменной,nmk
чтобы сохранить несколько байтов.Это устанавливает
sig
переменную в аргумент сигма и перебирает все числа от 1 доnmk - 1
. Я мог бы инициализировать переменную до 0 и итерировать по 1..nmk, но сделать это таким образом короче.🚮 вычисляет остаток, или модуль и 😛 проверяет равенство, поэтому условие будет 👍, если
i
делительnmk
.Это задание по вызову, похожее на семейство
+= -= >>=
операторов в некоторых низших языках без смайликов. Эта строка также может быть записана как🍮 sig ➕ sig i
. Поэтому после завершения внутреннего циклаsig
будет содержать сумму делителейn - k
илиsigma(n - k)
Еще одно назначение по вызову, так что это добавляет
sigma(n - k) * A(k)
к итогу, как в формуле.Наконец, сумма делится на n и частное возвращается. Это объяснение, вероятно, заняло в три раза больше времени, чем написание самого кода ...
источник
Пари / ГП , 8 байт
Попробуйте онлайн!
источник
Октава, 18 байт
Использует встроенную функцию partcnt.
Не можете сделать это правильно, используя анонимную функцию с помощью @, некоторая помощь будет оценена.
источник
Сетчатка , 34 байта
Попробуйте онлайн!
объяснение
Преобразовать ввод в унарный.
Это вычисляет все 2 n-1 разделов списка унитарных цифр. Мы делаем это путем многократного (
+
) сопоставления первой (1
) границы\B
, не входящей в число слов ( то есть положения между двумя1
s) в каждой строке (%
), и замены его на;
все после него ($'
), перевод строки (¶
), все перед это ($`
) и,
. Пример:становится
Где
v
отмечает результат$'
и^
отмечает результат$`
. Это обычная идиома для получения результата двух разных замен одновременно (мы в основном вставляем как замену, так;
и,
замену, а также недостающие «половинки» строки для завершения двух полных замен).Мы будем рассматривать
;
как фактические разделы и,
как заполнители, которые не позволяют последующим\B
сопоставлениям там. Так что дальше ...... мы удаляем эти запятые. Это дает нам все разделы. Например, для ввода
4
мы получаем:Мы не заботимся о заказе, хотя:
Это сортирует пробеги
1
s в каждой строке, поэтому мы получаем неупорядоченные разделы.Наконец, мы подсчитываем
@
совпадения unique ( ).+
, то есть сколько разных строк / разделов мы получили. Я добавил эту@
опцию давным-давно, затем совершенно забыл об этом и только недавно переоткрыл ее. В этом случае он сохраняет байт поверх первой дедупликации строк сD`
.источник
Python 2 ,
5453 байтаПопробуйте онлайн!
Как это устроено
Каждое разбиение n может быть представлено в виде списка x = [x 1 , ⋯, x m ], такого что x 1 + ⋯ + x m = n . Это представление становится уникальным, если мы требуем, чтобы x 1 ≤ ⋯ ≤ x m .
Определим вспомогательную функцию f (n, k), которая подсчитывает разбиения с нижней границей k , т. Е. Списки x такие, что x 1 + ⋯ + x m = n и k ≤ x 1 ≤ ⋯ ≤ x m . Для ввода n задача, таким образом, запрашивает вывод f (n, 1) .
Для натуральных чисел n и k , для которых k ≤ n , существует хотя бы одно разбиение с нижней границей k : одноэлементный список [n] . Если n = k (в частности, если n = 1 ), это единственный приемлемый раздел. С другой стороны, если k> n , решений вообще нет.
Если k <n , мы можем рекурсивно подсчитать оставшиеся разделы, построив их слева направо следующим образом. Для каждого j такого, что k ≤ j ≤ n / 2 , мы можем построить разбиения [x 1 , ⋯, x m ] = [j, y 1 , ⋯, y m-1 ] . Мы имеем, что x 1 + ⋯ + x m = n тогда и только тогда, когда y 1 + ⋯ + y m-1 = n - j . Кроме того, x 1 ≤ ⋯ ≤ x m, если и только если j ≤ y 1 ≤ 1 ≤ y m-1 .
Следовательно, разделы x из n , начинающиеся с j, могут быть вычислены как f (n - j, j) , что считает действительные разделы y . Требуя, чтобы j ≤ n / 2 , мы гарантируем, что j ≤ n - j , поэтому существует по крайней мере один y . Таким образом, мы можем подсчитать все разбиения n путем суммирования 1 (для [n] ) и f (n - j, j) для всех допустимых значений j .
Код представляет собой простую реализацию математической функции f . Кроме того, для k по умолчанию задано значение 1 , поэтому
f(n)
вычисляется значение f (n, 1) для ввода n .источник
J ,
3735 байтПопробуйте онлайн!
объяснение
источник
p(n) = sum(sigma(n-k) * p(k) for k = 0 to n-1) / n
. Я добавлю объяснение кода позже, когда я считаю, что его нельзя значительно сократить.JavaScript,
125121 байтПопробуйте онлайн!
Предупреждение: сложность времени и пространства экспоненциальна. Работает очень медленно для больших чисел.
источник
Python 2 , 89 байт
-9 байт от Mr.Xcoder -1 байт от notjagan
Попробуйте онлайн!
источник
¯\_(ツ)_/¯
- Кстати, если вы хотите сохранить его полную функцию, вам не понадобится переменная, 94 байтаЖеле , 13 байт
Попробуйте онлайн!
Требуется 5 секунд, чтобы решить n = 1000 на TIO.
источник
Java 8 (229 байт)
Ungolfed:
источник
Желе , 3 байта
Œṗ
Атом недавно был добавлен, и это означает «целое число разделов».Попробуйте онлайн!
источник
Пыть , 2 байта
Объяснение:
источник
JavaScript ES7, 69 байт
JavaScript ES6, 71 байт
Сложность времени O (n ^ n), поэтому будьте осторожны (на моем компьютере появляется очевидная задержка
F(6)
)источник