Обильный номер представляет собой любое число , где сумма его делителей больше , чем исходное число. Например, правильные делители 12:
1, 2, 3, 4, 6
И суммируя эти результаты в 16. Поскольку 16 больше, чем 12, 12 в изобилии. Обратите внимание, что это не включает «Совершенные числа», например, числа, которые равны сумме его собственных делителей, таких как 6 и 28.
Ваша задача на сегодня - написать программу или функцию, которая определяет, является ли число большим или нет. Ваша программа должна принимать одно целое число в качестве входных данных и выводить истинное / ложное значение в зависимости от того, является ли оно обильным или нет. Вы можете предположить, что входные данные всегда будут действительными и будут больше 0, поэтому для некорректных входных данных подходит неопределенное поведение.
Вы можете принимать входные и выходные данные в любом приемлемом формате, например, STDIN / STDOUT, файлы или аргументы / возвращаемые значения будут приемлемыми.
Для справки, вот многочисленные цифры до 100:
12,
18,
20,
24,
30,
36,
40,
42,
48,
54,
56,
60,
66,
70,
72,
78,
80,
84,
88,
90,
96,
100
И еще можно найти на A005101
Поскольку это код-гольф , стандартные лазейки запрещены, и постарайтесь написать как можно более короткий код на любом языке, который вы выберете!
источник
Ответы:
ECMAScript Regex,
1085855597536511508504 байтаСовпадение обильных чисел в регулярном выражении ECMAScript - это совершенно другой зверь, чем в любом другом варианте регулярного выражения. Отсутствие прямых / вложенных обратных ссылок или рекурсии означает, что невозможно напрямую подсчитать или сохранить промежуточный итог чего-либо. Отсутствие осмотрительности часто затрудняет работу даже при наличии достаточного пространства для работы.
Многие проблемы должны решаться с совершенно иной точки зрения, и вам будет интересно, решаются ли они вообще. Это заставляет вас создавать более широкую сеть, чтобы определить, какие математические свойства чисел, с которыми вы работаете, могут быть использованы для решения конкретной задачи.
Еще в марте-апреле 2014 года я построил решение этой проблемы в регулярном выражении ECMAScript. Сначала у меня были все основания подозревать, что проблема совершенно невозможна, но затем математик Теукон набросал идею, которая в конце концов обнадеживающе повлияла на то, чтобы она выглядела разрешимой, - но он дал понять, что не собирается строить регулярное выражение (он Я участвовал в соревнованиях / сотрудничал с моими в создании / игре предыдущих регулярных выражений, но к этому моменту достиг своего предела и был доволен, чтобы ограничить свой дальнейший вклад в теоретизирование).
Как и в случае с моим регулярным выражением, опубликованным пару дней назад, я дам предупреждение: я настоятельно рекомендую научиться решать унарные математические задачи в регулярном выражении ECMAScript. Для меня это было увлекательное путешествие, и я не хочу испортить его тем, кто потенциально может попробовать его сами, особенно тем, кто интересуется теорией чисел. См. Этот пост для списка последовательно рекомендованных спойлером проблем, решаемых один за другим.
Так что не читайте дальше, если вы не хотите, чтобы какая-то глубокая унарная магия испортилась для вас . Мой предыдущий пост был просто маленьким вкусом. Если вы действительно хотите сами разобраться в этой магии, я настоятельно рекомендую начать с решения некоторых проблем в регулярном выражении ECMAScript, как описано в этом посте, связанном выше.
Перед тем как разместить свое ECMAScript регулярное выражение, я думал , что это было бы интересно проанализировать Мартина Эндера решение .NET чисто регулярное выражение ,
^(?!(1(?<=(?=(?(\3+$)((?>\2?)\3)))^(1+)))*1$)
. Оказывается, очень просто понять это регулярное выражение, и оно элегантно в своей простоте. Чтобы продемонстрировать контраст между нашими решениями, вот закомментированная и довольно напечатанная (но не измененная) версия его регулярного выражения:Попробуйте регулярное выражение .NET онлайн
Теперь вернемся к моему регулярному выражению ECMAScript. Во-первых, вот он в необработанном формате без пробелов и комментариев:
^(?=(((?=(xx+?)\3+$)(x+)\4*(?=\4$))+(?!\3+$)(?=(xx(x*?))\5*$)x)(x+))(?=\1(x(x*))(?=\8*$)\6\9+$)(?=(.*)((?=\8*$)\5\9+$))(?=(x*?)(?=(x\11)+$)(?=\12\10|(x))(x(x*))(?=\15*$)(?=\11+$)\11\16+$)(?=(x(x*))(?=\17*$)\7\18+$)((?=(x*?(?=\17+$)(?=\17+?(?=((xx(x*))(?=\18+$)\22*$))(x+).*(?=\17$)\24*(?=\24$)(?!(xx+)\25*(?!\22+$)\25$)\22+$)((?=(x\7)+$)\15{2}\14|)))(?=.*(?=\24)x(x(x*))(?=\28*$)\23\29*$)(?=.*(x((?=\28*$)\22\29+$)))(.*(?!\30)\20|(?=.*?(?!x\20)(?=\30*$)(x(x*))(?=\33*$)(?=\31+$)\31\34+$).*(?=\33\21$)))+$
(изменить ,
\14
чтобы\14?
для совместимости с PCRE, .NET, и практически любой другой регулярным выражением вкуса , который не ECMAScript)Попробуйте онлайн!
Попробуйте онлайн! (быстрее, 537-байтовая версия регулярного выражения)
А теперь краткое изложение истории, стоящей за этим.
Сначала было очень неочевидно, по крайней мере для меня, что в общем случае можно было даже сопоставить простые числа. И после решения этого то же самое применимо к степеням 2. А затем к степеням составных чисел. А потом идеальные квадраты. И даже после решения этой задачи поначалу казалось, что обобщенное умножение невозможно.
В цикле ECMAScript вы можете отслеживать только один изменяющийся номер; это число не может превышать входное значение и должно уменьшаться на каждом шаге. Мое первое рабочее регулярное выражение для сопоставления правильных операторов умножения A * B = C было 913 байтов и работало путем деления A, B и C на их основные степени - для каждого простого множителя многократно делим пару простых коэффициентов мощности A и C по их первичной базе, пока та, которая соответствует А, не достигнет 1; затем значение, соответствующее C, сравнивается с основным коэффициентом мощности B. Эти две степени одного и того же простого числа были "мультиплексированы" в одно число путем сложения их вместе; это всегда будет однозначно отделимо на каждой последующей итерации цикла по той же причине, по которой работают позиционные системы счисления.
Мы получили умножение до 50 байт с использованием совершенно другого алгоритма (который мы с teukon смогли получить независимо, хотя ему потребовалось всего несколько часов, и он пошел прямо к нему, тогда как мне потребовалось несколько дней, даже после того, как привлек мое внимание к тому, что существовал короткий метод): для A≥B A * B = C, если есть, только если C - наименьшее число, которое удовлетворяет C≡0 mod A и C≡B mod A-1. (Удобно, что исключение A = 1 не требует специальной обработки в регулярном выражении, где 0% 0 = 0 дает совпадение.) Я просто не могу понять, насколько аккуратно, что такой элегантный способ выполнения умножения существует в таком минимальное регулярное выражение. (И требование A≥B может быть заменено требованием, чтобы A и B были простыми степенями одинаковой степени. Для случая A≥B это можно доказать с помощью китайской теоремы об остатках.)
Если бы оказалось, что не было более простого алгоритма для умножения, регулярное выражение с большим числом, вероятно, было бы порядка десяти тысяч байтов или около того (даже с учетом того, что я использовал алгоритм 913 байтов до 651 байта). Это делает много умножения и деления, и регулярное выражение ECMAScript не имеет подпрограмм.
Я начал работать над проблемой изобилия чисел тангенциально в 23 марта 2014 года, построив решение для того, что в то время казалось подзадачей: определить главный фактор наибольшей кратности, чтобы его можно было разделить на N в начале, оставляя место, чтобы сделать некоторые необходимые вычисления. В то время это казалось многообещающим маршрутом. (Мое первоначальное решение оказалось довольно большим - 326 байт, позднее - до 185 байт.) Но остальная часть набросанного teukon метода была бы чрезвычайно сложной, поэтому, как оказалось, я выбрал довольно другой маршрут. Этого оказалось достаточно, чтобы разделить наибольший простой коэффициент мощности N, соответствующий наибольшему простому коэффициенту на N; выполнение этого для простоты наибольшей кратности добавило бы ненужное сложность и длину к регулярному выражению.
То, что осталось, рассматривало сумму делителей как произведение сумм вместо прямой суммы. Как объяснил Теукон 14 марта 2014 года:
Это поразило меня, когда я увидел это. Я никогда не думал о факторизации суммы аликвот таким образом, и именно эта формула больше, чем что-либо еще, делала правдоподобной возможность сопоставления многочисленных чисел в регулярном выражении ECMAScript.
В конце концов, вместо того, чтобы проверять результат сложения или умножения, превышающего N, или проверять, что такой результат, предварительно разделенный на M, превышает N / M, я пошел с тестированием, если результат деления меньше 1. Я пришел к первая рабочая версия 7 апреля 2014 г.
Полная история моих оптимизаций в области гольфа для этого регулярного выражения находится на github. В определенный момент одна оптимизация закончилась тем, что регулярное выражение стало намного медленнее, поэтому с этого момента я сохранил две версии. Они есть:
регулярное выражение для сопоставления обильных чисел .txt
регулярное выражение для сопоставления обильных чисел - shorttest.txt
Эти регулярные выражения полностью совместимы как с ECMAScript, так и с PCRE, но недавняя оптимизация включала использование потенциально не участвующей группы
\14
перехвата, так что за счет снижения совместимости с PCRE и перехода\14?
на\14
них можно уменьшить их на 1 байт.Вот наименьшая версия с примененной оптимизацией (сделав ее только для ECMAScript), переформатированная, чтобы уместиться в блок кода StackExchange без (в основном) горизонтальной прокрутки (не требуется):
источник
Python 2 ,
4140 байтВывод осуществляется через код выхода , поэтому 0 соответствует действительности, а 1 - неверно.
Попробуйте онлайн!
Как это работает
После установки всех п , к , и J на вход из STDIN, мы вводим в то время как цикл. Упомянутый цикл обрывается, как только -k - 1 = ~ k ≥ 0 , т. Е. K ≤ -1 / k <0 .
На каждой итерации мы сначала уменьшаем j, чтобы рассмотреть только собственные делители n . Если j - делитель n , то
n%j
получается 0 и j >> n% j * n = j / 2 0 = j вычитается из k . Однако, если J вовсе не делит п ,n%j
является положительным, такn%j*n
, по крайней мере п> войти 2 J и J >> п% J * п = у / 2 п% J * п = 0 вычитают из к .Для больших чисел k достигнет отрицательного значения до или когда j станет 1 , так как сумма n делителей строго больше, чем n . В этом случае, мы нарушаем из в то время как петли и программа нормально завершается.
Однако, если п является не обильным, J в конце концов достигает 0 . В этом случае,
n%j
бросает ZeroDivisionError и программа завершается с ошибкой.источник
~k<0
это модно, но я думаю, что-1<k
тоже делаетБрахилог , 5 байт
Попробуйте онлайн!
объяснение
источник
Желе , 3 байта
Попробуйте онлайн!
Как это работает
источник
Python , 44 байта
Попробуйте онлайн!
источник
range(n)
. Это надоедливый модуль на нольMathematica, 17 байт
объяснение
источник
AbundantNumberQ
, поэтому он бы сэкономил пару байтов :)05AB1E ,
54 байта-1 байт благодаря Скоттинету
Попробуйте онлайн! или попробуйте от 0 до 100
источник
Сетчатка ,
50-45 байтВвод в унарном порядке , вывод
1
для больших чисел, в0
противном случае.В этом решении нет ничего специфичного для Retina. Выше приведено чистое регулярное выражение .NET, которое соответствует только многочисленным числам.
Попробуйте онлайн! (Набор тестов, который фильтрует десятичный ввод с помощью приведенного выше регулярного выражения.)
источник
Сетчатка , 34 байта
Число байтов предполагает кодировку ISO 8859-1.
Ввод в унарном порядке , вывод
1
для больших чисел, в0
противном случае.Попробуйте онлайн!
объяснение
Мы начнем с получения всех делителей ввода. Для этого мы возвращаем (
!
) все совпадения (&
) совпадений ()M
) регулярного выражения(1+)$(?<=^\1+)
. Регулярное выражение соответствует некоторому суффиксу входных данных, при условии, что весь ввод кратен этому суффиксу (что мы обеспечиваем, пытаясь достичь начала строки, используя только копии суффикса). Из-за того, как механизм регулярных выражений ищет совпадения, это приведет к появлению списка делителей в порядке убывания (разделенных переводами строк).Сама сцена просто соответствует linefeeds (
¶
) и удаляет их. Однако1>
это предел, который пропускает первый матч. Таким образом, это эффективно складывает все делители, кроме самого ввода. В итоге мы получим ввод в первой строке и сумму всех правильных делителей во второй строке.Наконец, мы пытаемся сопоставить по крайней мере еще одно значение
1
во второй строке, чем у нас в первой строке. Если это так, сумма правильных делителей превышает входные. Retina подсчитывает количество совпадений этого регулярного выражения, которое будет1
для многочисленных чисел и в0
противном случае.источник
8086 Ассамблея,
23282524 байтаразобранное:
Пример тестовой программы, тестирование N = [12..1000]:
Выход [2..1000]
Выход [12500..12700]
Выход [25100..25300]
Обновления:
источник
JLE
сJBE
двойной диапазон номеров этого теста , прежде чем начать переполняется , заставляя его давать ложные негативы. Тогда вместо того, чтобы начать терпеть неудачу в 12600 (аликвотная сумма 35760), он начнет терпеть неудачу в 25200 (аликвотная сумма 74744). Еще лучше было бы также обнаружить флаг переноса и рассматривать его как избыточное число без необходимости вычислять фактическую сумму> 16 бит.JC
илиJNC
действовать в зависимости от того, является ли номер обильным или нет.На самом деле 5 байтов
Попробуйте онлайн!
источник
05AB1E , 4 байта
Попробуйте онлайн!
Как это работает
Извините, что опубликовал старый вопрос, я просто просматривал старые сообщения для практики и заметил, что мое решение короче, чем следующее лучшее решение 05AB1E.
источник
Sorry to post in old question
Не беспокойся об этом! Я всегда рад видеть ответы на мои старые проблемы, и это на самом деле поощряется здесь . :)PARI / GP , 15 байт
Вариант
n->sigma(n,-1)>2
, к сожалению, длиннее.источник
Java 8, 53 байта (намного больше, если включить церемониальный код)
Попробуйте онлайн
Пояснение:
источник
return
если я не ошибаюсь, так что это будет еще короче:n->IntStream.range(1,n).filter(e->n%e<1).sum()>n
(не 100%, если это правильно, я почти никогда не программирую на Java 8). Добро пожаловать в PPCG!n->java.util.stream.IntStream.range(1,n).filter(e->n%e<1).sum()>n
для 65 байтов (при условии, что я получил пакет прямо с головы)Powershell,
5149 байтЯ хотел бы снять некоторые скобки.
-2 благодаря AdmBorkBork, вместо того, чтобы не считать входные данные в начальном диапазоне, мы просто учитываем их при окончательной проверке.
Пролистать диапазон
1..
до$i
nput, минус 1, найти где (?
) обратный модуль ввода текущего значения равен$true
(иначе всего 0) - затем-join
все эти числа вместе+
иiex
результирующая строка для его вычисления, а затем посмотреть, если сумма этих частей больше, чем вход.источник
param($i)((1..$i|?{!($i%$_)})-join"+"|iex)-gt2*$i
MATL, 6 байтов
Выходы 1 для обильных чисел, 0 в противном случае.
Как это работает
источник
QBIC , 22 байта
Это адаптация к тесту первичности QBIC . Вместо того, чтобы подсчитывать делители и проверять, меньше ли это трех, это суммирует правильные делители. Это выполняется только вдоль половины
1 to n
, где тест на первичность проходит1 to n
полностью.Объяснение:
источник
JavaScript (ES6), 33 байта
источник
Japt ,
9 76 байтСохранено 2 байта благодаря ETHproductions. Сохранено 1 байт благодаря obarakon.
Попробуйте онлайн!
источник
â
это 1 байт, по крайней мере, в Unicode (0xE2).â
используется один байт.â
задан верный аргумент, фактическое число будет удалено из оставшегося списка, так что вы можетеâ1 x >U
сохранить пару байтов :-)<Uâ1 x
чтобы сохранить байт. Japt добавляетU
перед программой.Cubix , 38 байт
Попробуй здесь
0I:
- устанавливает стек с 0, n, n (s, n, d)^
- начало цикла)?
- декремент d и проверка на 0. 0 выходит из цикла loop%?
- mod против n и проверяет. 0 вызывает;rrw+s;rU
вращение s в верхнюю часть и добавление d, вращение s в нижнюю часть и воссоединение с циклом;<
- Очистить и восстановить цикл.В выходящем цикле
;<
- Удалить d из стека и перенаправить-?
- Удалить n из s и проверить, 0LOU@
оборотов влево, выходы и выходы, отрицательные значения -0O@
ноль, выход и выход. положительные;O
убрать разницу и выходы n. Затем путь проходит до левого поворота, который перенаправляет на@
выходисточник
Чистый Баш, 37 байт
Спасибо @Dennis за перестановку кода - сохранение 6 байтов и исключение побочного вывода в stderr.
Ввод передается в качестве аргумента.
Выход возвращается в коде выхода: 0 для обильного, 1 для не обильного.
Вывод в stderr должен игнорироваться.
Тестовые прогоны:
источник
RProgN , 8 байт
Разъяснения
Попробуйте онлайн!
источник
Пакетная, 84 байта
Выходы
-1
для обильного числа, в0
противном случае. Работает, вычитая все факторы2n
и затем сдвигая результат на 31 позицию, чтобы извлечь знаковый бит. Альтернативная формулировка, также 84 байта:Выходы
1
на обильное количество. Работает, вычитая все факторы из,n
а затем сравнивая результат с-n
. (set/a
это единственный способ выполнения арифметики в пакетном режиме, поэтому я не могу легко настроить цикл.)источник
Perl 6,
7224 байта1..a
.a
.a
.Благодаря @ b2gills.
источник
$^a
после первого можно сократить до всего$a
. но это еще короче, если вы напишите его как «{$_ <sum grep $_%%*,^$_}
Также, глядя на более раннюю версию,[+](LIST)
работает (без пробелов)»J, 19 байт
Спасибо Конору О'Брайену за сокращение его до 19 байт!
<[:+/i.#~i.e.]%2+i.
Предыдущая: (34 байта)
f=:3 :'(+/((i.y)e.y%2+i.y)#i.y)>y'
Возвращает 1, если его много, и 0, если его нет.
Выход:
источник
f=:
как часть вашего количества байтов. Кроме того, вы можете получить до 19, превратив в молчаливый глагол:<[:+/i.#~i.e.]%2+i.
(f g h) y' is the same as
(fy) g (hy). When
f` - шапка,([: g h) y
примерно такая же, какg h y
. Что касается~
, это переключает левый и правый аргументы. Важно знать, что~
это не глагол, а на самом деле наречие. Это изменяет глагол. Например, мы могли бы иметь что-то вроде2 %~ 8
. Здесь~
модифицирует,%
чтобы переключать свои аргументы, поэтому выражение эквивалентно8 % 2
.#~
Pyth, 11 байт
Старый:
Я не могу использовать
!%
как PFN для#
, потому что это две функции. Заставляет меня грустить :(.источник
>sPf!%QTS
k ,
19 1615 байтВозвращает
1
как истинное, так и0
ложное.Попробуйте онлайн!
источник
PowerShell , 43 байта
Попробуйте онлайн!
источник
Common Lisp, 63 байта
Попробуйте онлайн!
источник
F #, 51 байт
Попробуйте онлайн!
Отфильтровывает все числа, которые не делятся поровну
n
, а затем суммирует их и сравнивает ихn
.источник