Haskell , 1080 1033 байт
;
f=
g
ij=f
a =hi
hi = g
hij= ij
g ' ' =0
g '"' =0;
g '$' =0;
g '&' =0-0
g '(' =0-0-0
g '*' =0-0-0;
g ',' =0-0-0;
g '.' =0-0-0-0
g '0' =0-0-0-0-0
g '2' =0-0-0-0-0;
g '4' =0-0-0-0-0;
g '6' =0; g '8' =0
g ':' =0; g '<' =0-0
g '>' =0; g '@' =0-0;
g 'B' =0; g 'D' =0-0;
g 'F' =0; g 'H' =0-0-0
g 'J' =0; g 'L' =0-0-0-0
g 'N' =0; g 'P' =0-0-0-0;
g 'R' =0; g 'T' =0-0-0-0;
g 'V' =0; g 'X' =0-0-0-0-0
g 'Z' =0; g '^' =0; g '`' =0
g 'b' =0; g 'd' =0; g 'f' =0;
g 'h' =0; g 'j' =0; g 'l' =0;
g 'n' =0; g 'p' =0; g 'r' =0-0
g 't' =0; g 'v' =0; g 'x' =0-0-0
g 'z' =0; g '\92' =0-0; g '|' =0;
g '~' =0; g y = 1 ;z=0; i(-0)z=z;
i m('\10':y ) ="y"; ; ; ; ; ; ; ;
i m(mnmnmnmnm:y ) = i(m - 1 ) y ; ;
i k m ="y"; ; k i [ ] =01<1010101010;
k m('\10':y ) = k(m + 1 )(i m y ) ; ;
k m y =01>10; m o = k 1$'\10':o ; ; ;
o i('\10':y ) = o i y ; ; ; ; ; ; ; ; ;
o i(k:y )|g k<i = o(1 - i ) y ; ; ; ; ; ;
o i(k:y )|g k>i = o(1 - i ) y ; ; ; ; ; ;
o i [ ] =01<10; o i y =01>10;v=01>10101010
s y|o 1 y = m y|o(-0) y = m y ; s y =v; ; ;
Спробуйте в Інтернеті!
Пояснення
Це було досить цікавим завданням для Haskell.
Паритет
Для початку нам потрібен певний спосіб визначити, чи має персонаж парну чи непарну кодову точку. Звичайний спосіб зробити це - отримати точку коду та модифікувати її на 2. Однак, як можна знати, отримання кодової точки символу вимагає імпорту, що через обмеження джерела означає, що воно не може бути б / в. Більш досвідчений Haskeller подумає використовувати рекурсію. Char
є частиною класу Enum
типу, щоб ми могли отримати своїх попередників та наступників. Однак pred
і succ
також як непридатна , тому що вони не роблять альтернативні парності байтів.
Таким чином, це залишає нас досить застряглими, ми майже не можемо жодних маніпуляцій із символами. Рішення цього полягає в жорсткому коді всього. Ми можемо представити (більшість) парних символів як буквальні, шанси, з якими ми маємо проблеми, тому що '
це непарно, тому це не може бути поруч із самим знаком, що робить буквальне неможливим виразити більшість непарних знаків. Тож ми жорстко кодуємо всі парні байти, а потім додаємо улов усі для непарних байтів наприкінці.
Проблема байтів
Ви можете помітити, що є кілька парних байтів, для яких літерали неможливо зробити, обернувши їх в одиничні лапки. Вони є недрукованими, новинками та \
. Нам не потрібно турбуватися про недруковані версії, оскільки поки ми не використовуємо жодну з них, нам не потрібно перевіряти. Насправді ми все ще можемо використовувати непарні друковані версії, як-от вкладка, я просто не закінчую цього. Новий рядок може бути ігноровано, тому що він все одно буде відрізаний від програми. (Ми можемо включити новий рядок, оскільки це кодова точка досить зручна, але нам цього не потрібно). Це залишає \
, тепер \
має кодову точку 92, яка зручно є непарним числом, за яким слідує парне число, тому \92
чергується між рівнами і коефіцієнтами'\92'
цілком справедливий. Пізніше, коли нам потрібно представити новий рядок, ми помітимо, що він, на щастя, має таку саму властивість '\10'
.
Проблеми з інтервалом
Тепер для того, щоб почати писати фактичний код, нам потрібно вміти розміщувати значну кількість символів на одному рядку. Для цього я написав шапку:
;
f=
g
ij=f
a =hi
hi = g
hij= ij
Ковпак не робить нічого, крім дійсного Haskell. Спочатку я сподівався зробити визначення, які допоможуть нам у коді пізніше, але це не вдалося. Існують також більш прості способи зробити обробку, наприклад, пробіли та крапки з комою, але вони не економлять байти таким чином, тому я не намагаюся її змінити.
Hardcoder
Тому тепер, коли мені достатньо місця в рядку, я починаю значення жорсткого кодування. Це в основному досить нудно, але є кілька цікавих речей. Один раз, коли рядки стають ще довші, ми можемо використовувати ;
для розміщення декількох декларацій на рядку, що економить нам тонну байтів.
Друга полягає в тому, що оскільки ми не завжди можемо починати рядок з g
кожного так часто, нам доведеться трохи відступити рядки. Тепер Haskell дійсно піклується про відступ, тому він скаржиться на це. Однак якщо останній рядок перед відступним рядком закінчується крапкою з комою, це дозволить. Чому? Я не найменший, але це працює. Тож нам просто потрібно пам’ятати, щоб ставити крапки з комою в кінці рядків.
Функціональні блоки
Після того, як жорсткий кодер буде зроблено, він плавно пливе до кінця програми. Нам потрібно побудувати кілька простих функцій. Спочатку будую версію drop
, що називається i
. i
відрізняється drop
тим, що якщо ми намагаємося пропустити повз кінець рядка, він просто повертається "y"
. i
відрізняється від drop також тим, що якщо він спробує скинути новий рядок, він повернеться. "y"
Вони будуть корисні тим, що пізніше, коли ми перевіримо, що програма є трикутником, це дозволить нам повернутися, False
коли останній рядок не завершений, або коли лінія закінчується рано.
k
k
нссTrue
нk
n + 1False
Потім зробити псевдонім k
, m
. m
тільки k
з 1
першим аргументом, і символ нового рядка передує до другого аргументу.
Далі маємо o
. o
бере число і рядок. Він визначає, чи байти рядків (ігноруючи нові рядки) чергуються в паритеті (використовуючи наш g
), починаючи з вхідного числа.
Нарешті, у нас є те, s
що працює o
з обома, 1
і 0
, якщо це вдається, відкладається m
. Якщо не вдасться обох, він просто повертається False
. Це функція, яку ми хочемо. Він визначає, що вхід трикутний і змінний.