Каждое число может быть представлено с помощью бесконечно длинной последовательности остатков. Например, если мы берем число 7 и выполняем 7mod2
, то 7mod3
, тогда 7mod4
и так далее, мы получаем 1,1,3,2,1,0,7,7,7,7,....
.
Однако нам нужна кратчайшая возможная подпоследовательность, которая еще может быть использована, чтобы отличить ее от всех младших чисел. Повторное использование 7 [1,1,3]
является самой короткой подпоследовательностью, потому что все предыдущие подпоследовательности не начинаются с [1,1,3]
:
0: 0,0,0,0...
1: 1,1,1,1...
2: 0,2,2,2...
3: 1,0,3,3...
4: 0,1,0,4...
5: 1,2,1,0...
6: 0,0,2,1...
Обратите внимание, что представление 7 [1,1]
не работает, потому что его также можно использовать для представления 1. Однако вы должны вывести [1]
с вводом 1.
Ввод, вывод
Ваш ввод является неотрицательным целым числом. Вы должны вывести последовательность или список последовательности минимальной длины остатков, как определено выше.
Тестовые случаи:
0: 0
1: 1
2: 0,2
3: 1,0
4: 0,1
5: 1,2
6: 0,0,2
7: 1,1,3
8: 0,2,0
9: 1,0,1
10: 0,1,2
11: 1,2,3
12: 0,0,0,2
30: 0,0,2,0
42: 0,0,2,2
59: 1,2,3,4
60: 0,0,0,0,0,4
257: 1,2,1,2,5,5
566: 0,2,2,1,2,6,6
1000: 0,1,0,0,4,6,0,1
9998: 0,2,2,3,2,2,6,8,8,10
9999: 1,0,3,4,3,3,7,0,9,0
Вот первые 10000 последовательностей , если вам интересно (номера строк выключены на 1).
Это код-гольф , поэтому делайте его как можно короче на своем любимом языке. Поддельные бонусные баллы за любые быстрые ответы!
источник
Ответы:
Mathematica,
6053 байтаНесколько быстро (он обрабатывает 10000 за ~ 0,1 секунды, но, скорее всего, не хватит памяти для 100000).
Код выдает ошибку, но вычисляет результат правильно.
объяснение
Ранее в чате мы обнаружили, что требуемые делители всегда можно определить как самый короткий список,
{1, 2, ..., n}
чье наименьшее общее кратное превышает входное. Короткий аргумент, объясняющий, почему это так: если LCM меньше входного значения, то вычитание LCM из входного значения оставило бы все делители без изменений, поэтому представление не является уникальным. Однако для всех входов, меньших, чем LCM, остатки будут уникальными, в противном случае разница между двумя числами с одинаковыми остатками будет меньше кратных всех делителей.Что касается кода ... как обычно, порядок чтения Mathematica в гольфе немного смешной.
Это дает нам список
[1, 2, 3, ..., n+2]
для вводаn
.+2
Является обеспечение того , что правильно работает0
и1
.Карта
2~Range~#
(синтаксический сахар дляRange[2,#]
) над этим списком, поэтому мы получаемЭто списки кандидатов-делителей (конечно, в общем, это гораздо больше, чем нам нужно). Теперь мы находим первый из них, чей LCM превышает вход с:
Больше синтаксиса:
x_
это шаблон, который соответствует любому из списков и вызывает егоx
./;
Присоединяет условие для этой модели. Это условие,LCM@@x>#
где@@
применяется функция к списку, т.е.LCM@@{1,2,3}
означаетLCM[1,2,3]
.Наконец , мы просто получить все остатки, используя тот факт , что
Mod
естьListable
, то есть он автоматически сопоставляет по списку , если один из аргументов является список (или если оба они представляют собой списки той же длины):источник
Желе , 14 байт
При этом используется тот факт, что решение (если таковое имеется) системы линейных конгруэнций является уникальным по модулю LCM модулей. Попробуйте онлайн! или проверьте все контрольные примеры .
Как это устроено
источник
MATL , 24 байта
Спасибо @nimi за указание на ошибку в предыдущей версии этого ответа (теперь исправлено)
Это исчерпывает память в онлайн-компиляторе для двух крупнейших тестовых случаев (но работает на компьютере с 4 ГБ ОЗУ).
Попробуйте онлайн!
объяснение
Это применяет определение в прямой форме. Для ввода
n
он вычисляет двумерный массив, содержащийmod(p,q)
сp
от0
доn
иq
от1
доn+1
. Каждыйp
является столбцом, и каждыйq
является строкой. Например, при вводеn=7
этот массивТеперь последний столбец, который содержит остатки
n
, поэлементно сравнивается с каждым столбцом этого массива. Это даетгде
1
указывает на равенство. Последний столбец, очевидно, равен самому себе и поэтому содержит все единицы. Нам нужно найти столбец , который имеет наибольшее количество первоначальных , кроме последнего столбца, и принять к сведению , что число первичных единиц,m
. (В данном случае это второй столбец, который содержитm=3
исходные). Для этого мы рассчитываем совокупное произведение каждого столбца:тогда сумма каждого столбца
а затем сортировать не все и принять второе значение, которое есть
3
. Это желаемоеm
, которое указывает, сколько остатков нам нужно выбрать.источник
Желе ,
1311 байтЭто не выиграет очки скорости брауни ... Попробуйте онлайн! или проверьте меньшие контрольные примеры .
Как это устроено
источник
Python 3.5,
1179578 байтТребуется Python 3.5 и sympy (
python3 -m pip install --user sympy
). Благодарим @Dennis, чтобы уведомить меня, что Python 3.5 допускает*l
хитрость с аргументами по умолчанию.источник
M>n and l
доl*(M>n)
.Python 2,
73706965 байтПолная программа. @Dennis сэкономил 4 байта, улучшив способ обработки нуля.
источник
Haskell,
66605150 байтПример использования:
f 42
->[0,0,2,2]
. Это алгоритм, описанный в ответе @Martin Büttner .Я сохраню предыдущую версию для справки, потому что она довольно быстрая:
Haskell, 51 байт
На
f (10^100)
моем пятилетнем ноутбуке это занимает 0,03 секунды .Изменить: @xnor нашел байт для сохранения. Благодарность!
источник
h i=mod i<$>[2..2+sum[1|l<-scanl1 lcm[2..i],l<=i]]
Pyth,
51 Bytes66 BytesПопробуйте!
Гораздо более высокая скорость 39-байтовой версии (не работает для 0-2):
Кажется, работает для абсурдно больших чисел, таких как 10 10 3
Примечание: этот ответ не работает для 0, 1 и 2.Исправлено!источник
JavaScript (ES6),
8177 байтЭто рекурсивно создает ответ до тех пор, пока LCM не превысит исходное число. Конечно, GCD рассчитывается рекурсивно.
Редактировать: 4 байта сохранены благодаря @ user81655.
источник
Рубин, 52 байта
Это решение проверяет все возможные,
m
начиная с 2, которые являются остатком, который делает последовательность уникальной. То, что делает последнийm
уникальный, не сам остаток, а то, что онm
является последним членом наименьшего диапазона,(2..m)
где наименьшее общее кратное (LCM) этого диапазона больше, чемn
. Это связано с китайской теоремой об остатках, где для однозначного определения числаn
с числом остатков значение LCM этих остатков должно быть больше, чемn
(при выбореn
из(1..n)
; при выбореn
изa..b
, значение LCM должно быть только больше, чемb-a
)Примечание: я поставил
a<<n%m
в конце кода, потому чтоuntil n<t=t.lcm(m+=1)
короткое замыкание передa
получило последний элемент, чтобы сделать его уникальным.Если у кого-то есть предложения по игре в гольф, пожалуйста, сообщите мне об этом в комментариях или в чате PPCG .
Ungolfing:
источник
Юлия,
3633 байтаПопробуйте онлайн!
источник
Python 3.5,
194181169152149146 байт:( Спасибо @ Sherlock9 за 2 байта! )
Работает отлично, а также довольно быстро. Расчет на минимальную оставшуюся последовательность
100000
выходов[0, 1, 0, 0, 4, 5, 0, 1, 0, 10, 4, 4]
занял всего около 3 секунд. Он даже смог рассчитать последовательность для ввода1000000
(1 миллион), вывода[0, 1, 0, 0, 4, 1, 0, 1, 0, 1, 4, 1, 8, 10, 0, 9]
и занял около 60 секунд.объяснение
По сути, эта функция в первую очередь создает список
y
со всеми,j mod i
гдеj
каждое целое число в диапазоне0=>7
(включая 7) иi
каждое целое число в диапазоне0=>100
. Затем программа переходит в бесконечныйwhile
цикл и сравнивает одинаковое количество содержимого каждого подсписка в первом-втором-последнем подспискахy
(y[:-1:]
) с тем же количеством элементов в последнем подсписке (y[-1]
) спискаy
. Когда подсписокy[-1]
это отличается , чем любой другой подсписка, цикл нарушается из - за, и правильная минимальная последовательность остаток возвращается.Например, если ввод 3,
y
будет:Затем, когда он входит в цикл while, он сравнивает каждый подсписок в списке
y[:-1:]
с таким же количеством элементов в подспискеy[-1]
. Например, сначала нужно сравнить[[0],[1],[0]]
и[1]
. Поскольку последний подсписок находится в остальной частиy
, он будет продолжаться, а затем будет сравниваться[[0,0],[0,1],[0,2]]
и[1,0]
. Так[1,0]
как теперь НЕ в остальномy
в этом конкретном порядке , это минимальная последовательность напоминаний, и, следовательно,[1,0]
будет возвращено правильно.источник
y[:c:]
же, какy[:c]
C89, 105 байт
Компилирует (с предупреждениями) используя
gcc -std=c89
. Принимает одно число в stdin и выводит последовательность остатков, разделенных пробелами в stdout.источник
C 89 байтов
Компилировать с GCC. Попробуйте онлайн: n = 59 , n = 0 .
источник