2.}<@>%?<{>$"/\M!8;
Читає:
2 . }
< @ > %
? < { > $
" / \ M
! 8 ;
Спробуйте в Інтернеті!
Напевно, це може бути байт або два байти, але це може потребувати справді геніального макета, який може бути легше знайти через грубу силу (навіть якщо це може зайняти досить багато часу, щоб знайти його).
Пояснення високого рівня
Програма здебільшого відповідає цьому псевдокоду:
while (read number is not zero)
{
if (number is even)
print number;
}
Що зловживає тим, як Гексагоні намагається прочитати число, коли STDIN порожній (він повертає нуль). Велика подяка Мартіну за допомогу в розробці такого підходу.
Повне пояснення
Я досі не спіткався з Моно, щоб отримати Тімві запустити фантастичний езотеричний IDE Тімві, тому я сперся на Мартіна, щоб надати мені кілька корисних гарних фотографій!
По-перше, трохи грунтовки на базовий контрольний потік у Гексагонії. Перший вказівник інструкції (IP), який є єдиним, що використовується в цій програмі, починається вгорі ліворуч від шестигранного вихідного коду і починає рухатися вправо. Щоразу, коли IP залишає край шестикутника, він рухаєтьсяside_length - 1
рядки до середини шестикутника. Оскільки ця програма використовує бічну довжину три шестикутника, IP завжди буде рухатись у два ряди, коли це станеться. Єдиний виняток - якщо він переміщується із середнього ряду, де умовно рухається до верхнього або нижнього шестикутника, залежно від значення краю поточної пам’яті.
Тепер трохи про умовні умови. Єдиними умовами гексагонії для контрольного потоку є >
:<
а середній край шестикутника. Усі вони відповідають постійному правилу: якщо значення поточного краю пам'яті дорівнює нулю або негативний потік керування переміщується ліворуч, а якщо додатний - управління тече вправо. Більші та менші дужки перенаправляють IP під кутом шістдесяти градусів, тоді як край шестикутника контролює, до якого ряду переходить IP-адреса.
У шестикутника також є спеціальна модель пам'яті, де всі дані зберігаються на краях нескінченної шестикутної сітки. Ця програма використовує лише три ребра: один для зберігання двох, один для числа, що читається в даний час, і один для модуля два. Це виглядає приблизно так:
Mod \ / Input
|
2
Я не збираюся ретельно пояснювати, де ми знаходимося в пам'яті в кожній точці під час пояснення програми, тому повертайтеся сюди, якщо ви заплутаєтесь у тому, де ми в пам’яті.
Коли все це не вийде, власне пояснення може початися. По-перше, ми заповнюємо край "2" в пам'яті двома, потім виконуємо безапеляційний режим і переміщуємо вказівник пам'яті вправо ( 2.}
).
Далі ми починаємо основний цикл програми. Ми читаємо перше число зі STDIN, а потім потрапляємо до умовного ( ?<
). Якщо в STDIN не залишилося жодних цифр, це зчитує нуль у поточній межі пам’яті, тому ми повертаємо ліворуч на те @
, що закінчує програму. В іншому випадку ми відскакуємо від дзеркала, переміщуємо вказівник пам'яті назад і вліво, обмотуємо навколо шестикутника, щоб обчислити залишок ділення введення на 2, а потім натиснемо на інший умовний ( /"%>
).
Якщо залишок був один (тобто число було непарним), повертаємо право, слідуючи за синім контуром вище, починаючи, знову виконуючи неоперацію, потім загортаємо до нижньої частини шестикутника, множимо поточний край на 10 і потім додаємо вісім, відмовтеся від декількох дзеркал, повторіть те саме множення та додавання ще раз, отримавши 188 на поточному краю, загорнувшись до вершини шестикутника, знову виконавши но-оп і нарешті закінчивши програму ( .8/\8.@
). Цей згорнутий результат був щасливою випадковістю, я спочатку написав набагато простішу логіку, але помітив, що можу зняти це на користь но-оп, що, на мою думку, було більше в дусі Гексагонії.
Якщо залишок дорівнював нулю, ми замість цього повертаємо ліворуч, слідуючи червоною стежкою вгорі. Це змушує пересунути вказівник пам'яті ліворуч, а потім надрукувати там значення (вхідне значення) як число. Дзеркало, з яким ми стикаємось, діє як неоперативний через напрямок, в якому рухаємось ( {/!
). Тоді ми натискаємо на край шестикутника, який є умовним лише з одним результатом, оскільки вхідне значення раніше було перевірене як позитивне, тому ми завжди рухаємося вправо (якщо ви уявляєте себе, зверненим у напрямку IP) . Потім ми множимо введення на 10 і додаємо два, тільки щоб змінити напрямок, обернемось і перезапишемо нове значення зі значенням ascii з великої літери М, 77. Потім натиснемо кілька дзеркал і вийдемо через край середини шестикутник з батутом (2<M\>$
). Оскільки 77 є позитивним, ми рухаємось праворуч у нижній частині шестикутника і через батут пропускаємо першу інструкцію ( !
). Потім множимо поточний край пам'яті на 10 і додаємо 8, отримуючи 778. Потім виводимо це значення мод 256 (10) як символ ASCII, який, як буває, є новим рядком. Нарешті, ми виходимо з шестикутника і обертаємось назад до першого, ?
що перевершує 778 на наступне вхідне значення.