Я думав, що скористаюся цією можливістю, щоб показати нову функцію Retina: багатоступеневі петлі. Це повинно значно скоротити багато завдань (особливо умовну заміну).
ii
-
+`(.)\1|0
(.)-|(\d)(\d)
-$1$3$2
12
i3
23
i1
31
i2
)`(\d)i
i$1
^\D*$
$&0
Retina - це моя власна мова програмування на основі регулярних виразів. Вихідний код можна згрупувати за етапами: кожен етап складається з двох рядків, де перший містить регулярний вираз (і, можливо, деяку конфігурацію), а другий рядок - рядок заміни. Потім етапи застосовуються до STDIN в порядку, і кінцевий результат друкується в STDOUT.
Ви можете використовувати вищезазначене безпосередньо як вихідний файл за -s
допомогою перемикача командного рядка. Однак я не рахую комутатор, тому що ви також можете просто помістити кожен рядок в окремий файл (тоді ви втрачаєте 15 байт для нових рядків, але додаєте +15 для додаткових файлів).
Пояснення
Нове в цьому рішенні - )
передостанній етап. Це закриває багатоступеневу петлю. Немає відповідності (
, а це означає, що цикл неявно починається на першому етапі. Отже, перші 7 етапів повторюються, поки повний прохід через усі 7 з них не перестане змінювати результат. Ці 7 етапів просто виконують різні перетворення, які поступово зменшують кількість матриць у рядку та поєднують фази. Як тільки ми досягнемо остаточного результату, жоден із семи шаблонів більше не відповідає, і цикл закінчується. Після цього ми додаємо 0, якщо в результаті ще немає цифри (оскільки на вищезазначених етапах просто випадають усі тотожності, включаючи результат).
Ось що роблять окремі етапи:
ii
-
Поєднує всі пари i
в, -
щоб зменшити символи фази.
+`(.)\1|0
<empty>
Тепер, якщо залишилося два послідовних однакових символа, це одна --
чи дві однакові матриці. У будь-якому випадку множення їх дає тотожність. Але нам не потрібні ідентичності, тому ми просто видаляємо їх усі, а також явні ідентичності 0
. Цей етап повторюється сам по собі, +
поки результат не перестане змінюватися. Це гарантує, що такі речі, як 123321
вирішити, повністю, так що наступним кроком можна вважати, що всі пари цифр є різними.
(.)-|(\d)(\d)
-$1$3$2
Це насправді дві окремі трансформації в одну (для гольфу). Зверніть увагу, що якщо перші альтернативні збіги, $2
і $3
порожні, а якщо другі збіги $1
порожні. Отже, це можна розкласти на два етапи:
(\d)(\d)
-$2$1
Це просто замінює всі пари цифр і додає знак мінус. Так як ми видалили всі 0
з і всі однакові пари, то це буде відповідати тільки 12
, 23
, 31
, 21
, 32
, 13
. Цей крок може здатися дивним, але він дозволяє мені перевірити лише половину цих випадків пізніше, тому що ті, які я не можу обробити, будуть замінені тут у наступній ітерації.
Інша частина вищезгаданого етапу була:
(.)-
-$1
Це поступово пересуває -
знаки повністю вліво (по одному положенню за ітерацію). Я роблю це так, що в кінцевому рахунку вони всі поруч і вирішуються на попередньому кроці.
12
i3
23
i1
31
i2
Ці три етапи тепер просто вирішують три пари продуктів. Як я вже говорив вище, це охопить лише половину відповідних випадків, але інша половина буде опікуватися в наступній ітерації, після попереднього кроку замінено всі пари.
)`(\d)i
i$1
Це останній етап циклу. Він схожий на той, що зміщується -
вліво, за винятком i
. Основна відмінність полягає в тому, що цей обмінюється i
лише цифрами. Якби я використовував (.)i
тоді, у випадках, коли я отримав -i
або i-
два, було б замінено на невизначений час, і програма не припиниться. Тож це лише замінює їх праворуч від -
знаків. Цього достатньо - доки всі -
і i
з’являться разом у якийсь момент, їх можна правильно вирішити.
^\D*$
$&0
Заключний крок (поза петлею). Пам’ятайте, що ми завжди видаляли всі ідентичності, тому, якщо результатом є фактично ідентичність (раз фаза), тоді ми більше не матимемо потрібної цифри у висновку, тому додаємо її назад.
Як приклад, ось усі проміжні форми 0223202330203313021301011023230323
(пропускні етапи, які не виконують жодних змін):
0223202330203313021301011023230323
321321312 # Remove identities
-23-31-12-132 # Swap all pairs
-23-31-i3-132 # Resolve 12
-i1-31-i3-132 # Resolve 23
-i1-i2-i3-132 # Resolve 31
-i-1i-2i-3-312 # Move - to the left and swap pairs
-i-1i-2i-3-3i3 # Resolve 12
-i-i1-i2-3-i33 # Move i to the left
-i-i1-i2-3-i # Remove identities
--ii-1i-2-3i # Move - to the left
--ii-i1-2-i3 # Move i to the left
----i1-2-i3 # Resolve ii
i1-2-i3 # Remove identities
i-1-2i3 # Move - to the left
i-1-i23 # Move i to the left
-i-1i-32 # Move - to the left and swap pairs
-i-i1-32 # Move i to the left
--ii-1-23 # Move - to the left and swap pairs
--ii-1-i1 # Resolve 23
----1-i1 # Resolve ii
1-i1 # Remove identities
-1i1 # Move - to the left
-i11 # Move i to the left
-i # Remove identities. Now the loop can't change this any longer.
-i0 # Fix the result by adding in the 0.