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