Perl 69 байт
s;.;y/XVI60-9/CLXVIX/dfor$a[$_].="32e$&"%72726;gefor 1..100;print"@a"
Работает по волшебной формуле. Выражение "32e$&"%72726
преобразует каждую цифру следующим образом:
0⇒32, 1⇒ 320, 2⇒ 3200, 3⇒ 32000, 4⇒29096, 5⇒56, 6⇒560, 7⇒5600, 8⇒56000, 9⇒50918
После применения перевода y/016/IXV/
мы получаем это:
0⇒32, 1⇒32 I , 2⇒32 II , 3⇒32 III , 4⇒29 I 9 V , 5⇒5 V , 6⇒5 VI , 7⇒5 VII , 8⇒5 VIII , 9⇒5 I 9 X 8
Остальные цифры ( 2-57-9
) удаляются. Обратите внимание, что это можно улучшить на один байт, используя формулу, которая переводит 012
вместо 016
упрощения /XVI60-9/
в /XVI0-9/
. Я не смог найти его, но, возможно, вам повезет больше.
Как только одна цифра была преобразована таким образом, процесс повторяется для следующей цифры, добавляя результат и переводя предыдущие XVI
s CLX
в то же самое время, когда происходит перевод новой цифры.
Обновление
Исчерпывающий поиск не выявил ничего более короткого. Однако я нашел альтернативное 69-байтовое решение:
s;.;y/XVI0-9/CLXIXV/dfor$a[$_].="57e$&"%474976;gefor 1..100;print"@a"
Этот использует 0-2
замену IXV
, но имеет модуль, который на одну цифру длиннее.
Обновление: 66 65 байт
Эта версия заметно отличается, поэтому я должен сказать несколько слов об этом. Формула, которую он использует, на самом деле на один байт длиннее!
Не в силах сократить формулу больше, чем она есть, я решил проиграть то, что у меня было. Прошло совсем немного времени, пока я не вспомнил своего старого друга $\
. Когда print
выдается отчет, $\
он автоматически добавляется в конец вывода. Мне удалось избавиться от неудобной $a[$_]
конструкции для двухбайтового улучшения:
s;.;y/XVI60-9/CLXVIX/dfor$\.="32e$&"%72726;ge,$\=!print$"for 1..100
Намного лучше, но это $\=!print$"
все еще выглядело немного многословно. Затем я вспомнил альтернативную формулу равной длины, которую я нашел, которая не содержала число 3
ни в одном из своих преобразований цифр. Таким образом, можно использовать $\=2+print
вместо этого и заменить полученное 3
место пробелом:
s;.;y/XVI0-9/CLXIIX V/dfor$\.="8e$&"%61535;ge,$\=2+print for 1..100
Также 67 байтов, из-за необходимого пробела между print
и for
.
Редактировать : это может быть улучшено одним байтом, перемещая print
вперед:
$\=2+print!s;.;y/XVI0-9/CLXIIX V/dfor$\.="8e$&"%61535;gefor 1..100
Поскольку подстановка должна быть полностью оценена до print
, присваивание по- $\
прежнему будет выполняться последним. Удаление пробела между ge
и for
выдаст предупреждение об устаревании, но в остальном действует.
Но, если бы формула , которая не использовать в 1
любом месте, $\=2+print
становится $\=print
еще два байта на сумму экономии. Даже если бы он был на один байт длиннее, это все равно было бы улучшением.
Как оказалось, такая формула существует, но она на один байт длиннее оригинальной, в результате чего итоговая оценка составляет 65 байт :
$\=print!s;.;y/XVI60-9/CLXXI V/dfor$\.="37e$&"%97366;gefor 1..100
методология
Был задан вопрос, как можно найти такую формулу. В общем, поиск волшебной формулы для обобщения любого набора данных является вопросом вероятности. То есть вы хотите выбрать форму, которая с наибольшей вероятностью даст что-то похожее на желаемый результат.
Изучая первые несколько римских цифр:
0:
1: I
2: II
3: III
4: IV
5: V
6: VI
7: VII
8: VIII
9: IX
есть некоторая закономерность, которую можно увидеть. В частности, с 0-3, а затем снова с 5-8 каждый последующий член увеличивается в длине на одну цифру. Если бы мы хотели создать отображение из цифр в цифры, мы бы хотели иметь выражение, которое также увеличивается в длине на одну цифру для каждого последующего члена. Логическим выбором является k • 10 d, где d - соответствующая цифра, а k - любая целочисленная константа.
Это работает для 0-3 , но 4 должен сломать образец. То, что мы можем сделать здесь, это прибавить по модулю:
k • 10 d % m , где m находится где-то между k • 10 3 и k • 10 4 . Это оставит диапазон 0-3 нетронутым и изменит 4 так , чтобы он не содержал четыре I
с. Если мы дополнительно ограничим наш алгоритм поиска таким образом, чтобы модульный остаток 5 , назовем его j , был меньше m / 1000 , это также обеспечит регулярность 5-8 . Результат примерно такой:
0: k
1: k0
2: k00
3: k000
4: ????
5: j
6: j0
7: j00
8: j000
9: ????
Как вы можете видеть, если мы заменим 0
с I
, 0-3 и 5-8 все гарантированно будет отображаться правильно! Значения 4 и 9 должны быть грубыми. В частности, 4 должен содержать один 0
и один j
(в этом порядке), а 9 должен содержать один 0
, за которым следует еще одна цифра, которая больше нигде не появляется. Конечно, есть ряд других формул, которые по стечению обстоятельств могут привести к желаемому результату. Некоторые из них могут быть даже короче. Но я не думаю, что есть такие, кто может добиться успеха так же, как этот.
Я также экспериментировал с множественными заменами I
и / или V
с некоторым успехом. Но увы, ничего короче того, что у меня уже было. Вот список самых коротких решений, которые я нашел (количество решений на 1-2 байта больше, слишком много, чтобы перечислять):
y/XVI60-9/CLXVIX/dfor$\.="32e$&"%72726
y/XVI0-9/CLXIXV/dfor$\.="57e$&"%474976
y/XVI0-9/CLXIVXI/dfor$\.="49e$&"%87971
y/XVI0-9/CLXIIXIV/dfor$\.="7e$&"%10606 #
y/XVI0-9/CLXIIXIV/dfor$\.="7e$&"%15909 # These are all essentially the same
y/XVI0-9/CLXIIXIV/dfor$\.="7e$&"%31818 #
y/XVI0-9/CLXIIX V/dfor$\.="8e$&"%61535 # Doesn't contain 3 anywhere
y/XVI60-9/CLXXI V/dfor$\.="37e$&"%97366 # Doesn't contain 1 anywhere