Діалог APL ( 75 73 69 68 символів)
Ось ще одна і п'ята спроба (швидше за все, моя остання); Я провів день, намагаючись написати якийсь фрагмент коду, менший за 80 символів, і цілком відповідав правилам. Цей виклик зробив мій день!
Нарешті я отримав рядок APL, що складається з 75 символів, працюючи з Dyalog APL (але не на сторінці онлайн-перекладача, оскільки використовую функцію ⍎
Execute ), який є наступним:
(N,D)÷D∨N←(⍎'0',1↓I/⍨2=+\P)+(⍎'0',I/⍨2>+\P)×D←D+0=D←⍎'0',⌽2↓⍕¯1+10⊥P←'.'=I← '1.2.3'
Звичайно, я міг би зробити це трохи коротшим, але особливі випадки, коли одне, два чи три поля відсутні. Мій код може навіть обробляти ..
регістр вводу.
Я знаю, що APL важко читати, і оскільки люди із задоволенням розуміють, як фрагмент коду насправді працює, ось кілька пояснень. В основному я обчислюю кінцевий знаменник у змінній D та кінцевий чисельник у змінній N.
APL розбирається справа наліво.
- По-перше, рядок зберігається у змінній I (
I←
).
- Потім він відображається на вектор булевих знаків, що вказує, де знаходиться точка, і цей вектор називається P (
P←'.'=
). Наприклад, "1.2.3" буде відображено в 0 1 0 1 0.
- Цей вектор є цифрами в базі 10 (
10⊥
); зараз '1.2.3' - 1010.
- Потім 1 віднімається від цього числа (або з,
1-⍨
або з ¯1+
, тут я вибрав друге). Зараз '1.2.3' - 1009.
- Потім це число перетворюється у рядок (
⍕
), дві початкові цифри видаляються ( 2↓
), що складає 09 з нашого початкового прикладу '1.2.3'; рядок обернено ( ⌽
).
- Тут, як особливий випадок, я додаю початковий символ 0 перед рядком; мені дуже сумно використовувати чотири символи,
'0',
але я це зробив, щоб уникнути помилки, коли друге і третє поля обоє порожні. Рядок перетворюється назад у число ( ⍎
) і зберігається в D, що є знаменником, за винятком випадків, коли обидва останні поля порожні, тому що в такому випадку D дорівнює 0.
D←D+0=
Шматок коду безлічі D 1 , якщо вона в даний час нульовий, а тепер D містить знаменник (до НОД поділу однак).
- Цей знаменник множиться (
×
) зі змістом початкового рядка I до другої крапки, з (⍎'0',I/⍨2>+\P)
якої починається знову з P (у моєму прикладі 0 1 0 1 0), додає послідовні числа шляхом їх кумуляції (що складає 0 1 1 2 2 у моєму прикладі), перевірте, які значення менші за 2 (створення булевого вектора 1 1 1 0 0), і взяти відповідні символи в I; ще один 0 додається перед рядком для запобігання черговій пастці (якщо два початкових поля порожні) і ціле перетворюється в число.
- Остання частина вхідного рядка додається до попереднього добутку з
(⍎'0',1↓I/⍨2=+\P)
, який приймає P знову, додає, накопичуючи ще раз, перевіряє, які значення дорівнюють 2 (див. Попереднє пояснення), приймає characers, видаляє першу, яка є крапкою , додає попереджувальний початковий символ 0 і перетворюється на число.
- Цей продукт із сумою зберігається в N, який є чисельником.
- Нарешті, GCD обчислюється з D∨N, і обидва числа діляться цим GCD.
редагувати: Ось виправлення для 73 символів:
(N,D)÷D∨N←(⍎'0',1↓P/I)+(⍎'0',I/⍨~P←2=+\P)×D←D+0=D←⍎'0',⌽2↓⍕¯1+10⊥P←'.'=I←
Ідея цього хака - обчислити спочатку випадок, коли сукупне додавання має значення, що дорівнюють 2, зберігаючи їх для подальшого та інвертуючи цю розрядну маску для отримання першого випадку; таким чином для обчислення наступного випадку потрібно менше символів.
редагувати: Ось чергове виправлення для 69 символів:
(N,D)÷D∨N←(⍎'0',1↓P/I)+(⍎'0',I/⍨~P←2=+\P)×D←⍎'1⌈0',⌽2↓⍕¯1+10⊥P←'.'=I←
Ідея цього злому полягає в тому, щоб вбудувати найскладніший спеціальний випадок як код APL у рядку, який слід оцінювати (на етапі перетворення рядка в число).
редагувати: Ось чергове виправлення для 68 символів:
(N,D)÷D∨N←(⍎'0',1↓P/I)+(⍎'0',I/⍨~P←2=+\P)×D←⍎'1⌈0',⌽3↓⍕1-10⊥P←'.'=I←
Ідея цього хаку полягає в заміні додавання -1 до значення для підняття 1 до цього значення операцією, що підкреслює це значення 1, а потім видалити пізніше на один символ більше (що буде знаком мінус).
редагувати: Косметичні зміни:
(N,D)÷D∨N←(⍎'0',1↓P/I)+(⍎'0',I/⍨~P←2=+\P)×D←1⌈⍎'0',⌽3↓⍕1-10⊥P←'.'=I←
Не поліпшення розміру, але більш задоволене, щоб отримати максимальну функцію з коду, що оцінюється.
9/99
?