Я думав, що скористаюся цією можливістю, щоб показати нову функцію 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.