Коротка історія 2D мов програмування: 16 (+2) років
v19977/2{@{{4{\_______>/02&&&#???? * P+++++1P1P-1P+1E * *
\'\02'oo100@n590@n; * * *
>"8991",,,;5-;,@ * * *
* * * *
\ * ++++++++++++++++++++++++ ++++++++++++++++++++++++ ++O--OO++++++++OX******* *
* #2018O@ * * * * * * *
* * * * * * * *
* * * * * * * *
* **** **** * **** **** * **** **** * **** *****
* * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * *
* * * **** * * * * **** * * * * **** * * * * ****
* * * * * * * * * * * * * * * *
R"2014"; ***** ******* ****** ******* ****** ******* ****** *******
x
x%"2010"x
x
$'main' \/\/\/\
\-[2005]o-# \++++++\
/++++++/
\++++++\
/++++++/
\/\/\/\++.--..+++.#
S1^2^2^6^8MAOUOAOOF
/K:0:1:@
> "7102"4&o@
| }+++++[>++++++++++<-]>.--..++++++.@
Я згадав, що мені подобаються 2D мови програмування?
Мова, яка (нібито, див. Останній розділ) почала все це. У Befunge ви можете перенаправляти керуючий потік за допомогою <v>^
, але тепер всюдисущих дзеркал \
і /
ще нічого не було. Інтерпретатор Befunge, який використовується на Anarchy Golf, ігнорує невідомі команди. Ми можемо скористатися цим, щоб відрізнити родину Бефунге від родини> <>. Отже, код, виконаний Befunge, такий:
v
\
>"8991",,,;5-;,@
"8991"
Розсовує окремі символи в стек. ,,,
друкує перші три з них. Тоді ;
невідомо (що ми будемо використовувати для того, щоб відрізнити його від Befunge 98), 5-
перетворює 8
на a 3
і ,
друкує, що ще до @
завершення програми.
Написання цієї частини рішення зайняло мене, ймовірно, до тих пір, як написати всі інші та прилаштувати їх разом ...
Wierd знає лише два символи: простір та все інше. Вказівник вказівки намагається прослідкувати шлях, утворений непробільними символами, починаючи діагонально з верхнього лівого кута і завжди намагаючись пройти якомога прямо. Згини в контурі утворюють фактичні вказівки (із градусами повороту, що визначають, яку інструкцію виконати). Отже, код, який бачив Wierd, такий:
v1997 * * *
' * * *
8 * * *
* * * *
* ++++++++++++++++++++++++ ++++++++++++++++++++++++ ++O--OO++++++++OX******* *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* **** **** * **** **** * **** **** * **** *****
* * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * *
* * * **** * * * * **** * * * * **** * * * * ****
* * * * * * * * * * * * * * * *
***** ******* ****** ******* ****** ******* ****** *******
1997
На самому верху на насправді не виконується, але Wierd дозволяє нам читати його з вихідного коду, який є набагато коротше , ніж намагатися будувати коди символів для себе чотирьох цифр (навіть якщо він не схожий на нього .. .). Мені не подобається зламати всю цю річ, але ви чітко бачите чотири повторювані розділи. Це означає, що ми спочатку зберігаємо 1
на стеці, а потім збільшуємо кожен із цих чотирьох розділів 1
, а потім гілки. Нижня гілка штовхає іншу1
, отримує вихідний символ за цими координатами і друкує його, тоді як верхня гілка перенаправляється до наступного розділу. Вам може бути цікаво, чому кінці шляхів настільки непотрібні довгі, але це тому, що, коли Wierd потрапляє в кінець шляху, він намагається перейти на сусідній шлях, перш ніж вирішити, що він повинен припинити поточну гілку. Щоб цього уникнути, нам потрібно перемістити ці кінці досить далеко від будь-якого іншого коду.
Befunge отримав досить відоме оновлення в 1998 році з дуже жорсткою специфікацією, яку можна узагальнити до довільних розмірів (і, думаю, також довільних топологій). Це значною мірою назад сумісно з Befunge, що робить його досить простим на поліглот. У цьому Befunge досі не було дзеркал, тому виконаний шлях такий же, як і для Befunge 93:
v
\
>"8991",,,;5-;,@
Різниця в тому, що Befunge 98 не ігнорує ;
. Натомість це трохи нагадує коментар у тому, що всі команди до наступної ;
ігноруються. Таким чином, ми не зменшуємо , що 8
до 3
і друкувати 1998
як є.
2001: Космічний од ... PingPong
2001 рік - рік Піта, але я справді не відчував, як поліглотувати файл зображення з усіма іншими програмами, тому ось менш відома 2D мова. Здається, має досить багато функцій (якими ми не збираємось користуватися). Спасибі Sp3000 за те, що він знайшов оригінального перекладача (який є єдиним мертвим посиланням на архівній версії офіційного веб-сайту).
PingPong дещо незвично тим, що в ньому є лише дзеркала та відсутні <v>^
перенаправлення. Таким чином, це рухається по початку v19977
на початку, а потім потрапляє в дзеркало, яке обгортає його донизу. Тоді відповідний код:
v19977/
...
/K:0:1:@
...
Фактичний код досить простий: K
натискає 20
, цифри натискають на себе, :
друкує ціле число та @
припиняє програму.
Це перша мова, де все стає простіше, оскільки SNUSP підтримує явну точку входу. Ця точка входу позначена символом $
. Судячи з деяких статей про езоланг, ця мова надихнула декількох інших, але, на жаль, наприкінці дня це лише похідне Brainfuck. З цього приводу, я думаю, що спосіб встановлення поточної комірки до 48 є досить акуратним (і був викрадений із статті esolangs). Ось відповідна частина коду:
$'main' \/\/\/\
\++++++\
/++++++/
\++++++\
/++++++/
\/\/\/\++.--..+++.#
Це 24 +
с, і дзеркала надсилають IP через кожне рівно двічі.
З якої - то причини, ця мова дійсно є <^>
редиректори , але замість звичайного v
він використовує %
. Отже, це просто переміщується через перший рядок. Відповідний код:
v19977/2{@{{4{\
Для початку натискаємо кілька цифр, виконуємо ділення. Потім 2{
друкує 2
, @
очищає стек. {{
друкує два (неявні) 0
s. 4{
друкує 4
та \
припиняє програму.
2005 рік був важким вибором. В жодному іншому році я не знайшов стільки 2D мов, і є ADJUST та Archway, обидва вони починаються в нижньому лівому куті (що полегшило б їх доповнення). Мені подобається Rail, але, оскільки він має чітку точку входу, теж не важко додати. Rail шукає лінію, що починається, $'main'
і починає рухатися на південний схід від $
. Це означає, що відповідний код:
$'main'
\-[2005]o-#
The \
і -
є лише треками (no-ops). Це [2005]
рядковий літерал, який o
друкується до #
завершення програми.
Двомірний Brainfuck. Є ще одна цікава мова цього року під назвою Black, яка починається з координати (3,3)
(на основі 1), яка також зробила б використання цього в поліглоті також цікавим. Я не зміг знайти перекладача. Тож нам доведеться працювати з іншою похідною BF ...
Цікавим у цьому є те, що він не форматує сітку у рядки із стрічковими каналами, як у більшості інших двовимірних мов. Замість цього |
використовується як роздільник рядків. Оскільки я не використовував |
жодні інші мови, я міг просто поставити |
на останній рядок, що робить всю решту програми єдиною лінією, що стосується BF.js. Відповідним кодом є такий (перетворюючи |
на фактичну стрічку):
v19977/2{...
}+++++[>++++++++++<-]>.--..++++++.@
BF.js не використовує <v>^
ні дзеркала. Єдиний спосіб перенаправити керуючий потік - {}
це повернути напрямок IP на 90 °. Тож ці брекети переміщують IP на другий рядок. Залишок - це звичайне рішення Brainfuck (не особливо добре гольф), яке встановлює клітинку 50
(кодова точка 2
), а потім друкує 2006
, зміщуючи значення на трохи. @
припиняє програму.
В цьому році я дійсно хотів би використовувати DOBELA , який використовує кілька точок входу і виглядає як Lovechild з РОЗПОДІЛУ і Ziim . На жаль, мені не вдалося змусити перекладача працювати. Отже ось ще одна похідна BF (остання, обіцяю).
На відміну від останнього, це один знає , як <v>^
і дзеркала, так що відповідний код:
v
\'\
8
\ * ++++++++++++++++++++++++ ++++++++++++++++++++++++ ++O--OO++++++++OX
У цьому немає звичайного []
циклу в стилі BF (замість цього вам потрібно буде сформувати фактичний цикл 2D), тому я просто вирішив жорстко ввімкнути, 50
оскільки у мене все-таки було багато символів підряд від Wierd. Зауважте, що '
і 8
ігнорується, *
це умовний батут, який ми можемо ігнорувати, і O
це Brainfuck's .
. X
Завершує програму.
Мабуть, найпопулярніший Fungeoid (крім самого Befunge) принаймні навколо цих частин. > <> має <v>^
і дзеркала, але і рядкові літерали, тому виконаний код такий:
v
\'\02'oo100@n590@n;
Буквальний рядок здебільшого служить для пропуску \
ми, які ми використовували для BrainSpace 1.0, але, поки ми знаходимося на цьому, ми можемо також натиснути перші два символи. oo
друкує їх. Потім 100
натискає три цифри, підсуває @
верхню донизу і n
друкує 0
знизу. Знову робимо те ж саме, з 590
яким друкується 9
. Якщо вам цікаво, чому я не просто друкую так, 2009
як є, зачекайте на 2015 рік. ;
Закінчується програма.
Це було просто, тому що він має чітку точку входу на %
. Однак цей створює 4 IP-адреси в усіх напрямках (звідси, гадаю, назва мови), і нам потрібно позбутися 3-х з них. Ось відповідний код:
x
x%"2010"x
x
Ну так. (У кардиналі рядковий режим друкується безпосередньо замість натискання символів на стек.)
2011 р .: RunR
Ще одна мова з чіткою точкою входу ( Девід Кетт, який створив кілька інших дуже приємних езолангів), на цей раз о S
. Це робить відповідний код цією частиною:
S1^2^2^6^8MAOUOAOOF
RunR трохи цікаво, тому що більшість операцій працює з таким реєстром і значення повинні бути переміщені в стек явно для двійкових операцій. Цифри встановлюють значення регістру для себе і ^
виштовхує поточний регістр до стеку. Тоді M
відбувається множення (реєструвати значення часу, вискочене з стека), U
віднімання, A
додавання, O
виводиться. F
припиняє програму.
2012 рік: Ropy
Як і Вердер, Ропі намагається слідувати розділам непробільних символів, але тут вигини не визначають команди. Насправді виявляється, що Ропі більше схожий на мій власний Лабіринт тим, що обраний напрямок залежить від вершини стека. Однак нам насправді не потрібно про це турбуватися, тому що Ропі просто рухається по першій лінії:
v19977/2{@{{4{\_______>/02&&&#????
Є багато речей, які ми можемо ігнорувати >
. Все, що нам потрібно знати, - це те, що верхня частина стека в цьому місці буде a, 4
а там буде 2
внизу.
>
дублює 4
, /
є поділ, перетворюючи його на a 1
. Потім натискаємо 02
. &&&
приєднується до чотирьох перших чисел стека у зворотному порядку, надаючи 2012
. #
виводить його. ????
просто очищає стек, оскільки в іншому випадку також виводиться верхня частина стека.
Один із цікавих моментів полягає в тому, що другий 7
в 19977
доданий через Ропі. Розділ /
у Ropy робить top / second
(навпаки звичайному порядку в багатьох мовах, що базуються на стеках ), де можна 7 / 9
було б дати 0
. Якби у нас був нуль на вершині штабеля, Ропі робив би якісь дикі речі зі своїм напрямком руху, тому нам потрібно штовхнути іншого, 7
щоб переконатися, що вершина штабу залишається позитивною, а Ропі продовжує рухатися на схід.
З його чіткими точками входу це легко. RDLU
створити атоми (покажчики інструкцій) у відповідному напрямку, тож відповідний біт саме такий:
R"2014";
Зауважте, що U
в вихідному коді також є, але цей атом врешті-решт потрапляє на один *
з Wierd, який припиняє програму (а цей атом займає набагато більше часу, ніж R
потрібно друкувати 2014
).
Потужніша <>> похідна Sp3000. Він значною мірою назад сумісний з> <>, тому виконаний код все ще:
v
\'\02'oo100@n590@n;
Однак напрямок обертання @
змінено, що є стандартним трюком для розрізнення> <> і Gol> <> у поліглотах, тому цей друкується 15
замість 09
. Звідси дивність у другій половині програми.
CSL дуже цікавий тим, що команди виконуються не відразу. Натомість кожна команда висувається на командний стек e
і E
може використовуватися для виконання команд з неї. Відповідним кодом стає:
v19977/2{@{{4{\_______>/02&&&#???? * P+++++1P1P-1P+1E
Так E
виконується весь стек команд, а це означає, що матеріал перед ним виконаний у зворотному порядку. Нам потрібно лише придивитися до *
:
1+P1-P1P1+++++P*
В 1
s випинати себе на стек даних. +
і -
є декрементом / збільшенням. P
друкує верхню частину стека. Потім *
намагається помножити два перших значення стека. Однак стек порожній, тому програма припиняє роботу.
У цей момент ми переходимо до мов, які були випущені після публікації цього виклику, тому я насправді не рахую їх за рахунок, тим більше, що я створив їх сам (не маючи на увазі цього виклику). Однак у них є якась нова семантика руху ІР, завдяки якій було легко вписати їх у поліглот, а також додати щось цікаве до цієї вітрини 2D мов.
Аліса була розроблена як багатофункціональний Fungeoid. Одне цікаве відмінність більшості (але не всіх) інших 2D мов полягає в тому, що IP може переміщуватися або ортогонально, або по діагоналі. Перемикання між ними також змінює семантику майже всіх команд у мові. Крім того, Alice підтримує як традиційні налаштування <^>v
напрямку, так і \/
дзеркала, але дзеркала мають дуже унікальну поведінку в Alice (що дозволяє легко привести IP Alice до поки що невикористаної частини коду).
Хоча більшість мов трактують \
і /
як би дзеркала під кутом 45 °, а ІР - як промінь світла, що відбивається від нього, Аліса розглядає їх як кут 67,5 ° (що ближче до кута фактичних косих глифів) , і IP також рухається через дзеркало (звідси назва мови). Завдяки цьому куту дзеркала перемикаються між рухом по ортогональному або діагональному напрямкам. Крім того, перебуваючи в звичайному режимі (тобто в той час, коли IP рухається по діагоналях), сітка не загортається, і натомість IP відскакує від країв (тоді як у режимі Кардинала вона обертається навколо).
Загалом, код, виконаний Алісою, такий:
v19
\ \
...
> "7102"4&o@
...
IP починається у верхньому лівому куті, як зазвичай, v
надсилає його на південь. Тепер \
відображається IP для переміщення на північний захід, де він негайно відскакує від лівого краю сітки (і замість цього рухається на північний схід). 1
можна ігнорувати, IP відскакує від верхнього краю, щоб перейти на південний схід далі. Ми потрапили на інший, \
який відображає північ IP. 9
можна також ігнорувати, і тоді IP перегортається до нижньої частини сітки. Через пару ліній ми перенаправляємо його на схід >
для зручності. Потім "7102"
натискає кодові точки 2017
, 4&o
друкує ці чотири символи та @
припиняє програму.
Wumpus - це перша двовимірна мова в трикутній сітці, яка робить рух по коду зовсім іншим (і знову дозволяє нам легко дістатися до невикористаної частини коду). Тож замість того, щоб мислити кожного символу в сітці як про маленький квадрат, слід думати про них як про чергування трикутників вгору та вниз. У верхньому лівому куті завжди є висхідний трикутник.
У Wumpus немає встановлених напрямків <^>v
, але у них є дзеркала \/
. Однак завдяки трикутній сітці вони працюють відмінно від більшості інших мов. ІР відштовхується від них, як промінь світла (як зазвичай), але ви повинні думати про них як кут 60 °. Таким чином, IP, що рухається на схід, в кінцевому підсумку рухатиметься по північно-західній осі мережі.
Як ще одна відмінність від більшості інших мов, краї сітки не обертаються, але IP-адреса замість цього відскакує від країв (як якщо б ці клітинки краю містили відповідні дзеркала). Ще одна прикольна маленька деталь - те, що діагоналі через трикутну сітку насправді виглядають як сходи у вихідному коді.
Зважаючи на це, код, виконаний Wumpus, наступний (де я замінив пробіли .
на ясність:
v19977/
02
89
..
..
.....*...#2018O@
Це v19977
лише мотлох, який ми можемо ігнорувати. /
передає IP на північний захід, де він рухається через 977
(праворуч) знову, відхиляючись від верхнього краю. Потім IP пересувається на південний захід через 2089
пробіл і купу, перш ніж він потрапить на лівий край, щоб знову відобразити схід. *
також є мотлохом. Потім нарешті #2018
натискає 2018
, O
роздруковує його і @
припиняє програму.
Пропали роки
Нарешті, кілька записок про роки я не висвітлював.
Під час дослідження 2D мов, щоб знайти підходящі мови протягом багатьох років, які можна було б використовувати в поліглоті, я виявив, що всупереч поширеній думці, Befunge не була першою двовимірною мовою. Таку назву, схоже, займає Біота, яка була створена в 1991 році. На жаль, мова не має жодного виводу, тому я не зміг використати її для цього завдання.
Наскільки я можу сказати, жодні 2D мови не були створені у 1992 та 1995 роках. Це залишає кілька років, які я не охоплював:
- 1994: Ортагонал був створений незалежно від Бефунге. Насправді мови є семантично досить схожими, але ортогонал насправді не викладає вихідний код у 2D. Натомість кожен рядок -
(x, y, instruction)
кортеж. Я навіть отримав специфікацію мови та оригінального перекладача від творця Джеффа Еплера, але, врешті-решт, той факт, що синтаксис не 2D, зробив мову непридатною для цього поліглоту.
- 1996: Ортогонал , наступник Ортагоналу (створений кимось іншим), був створений, але для цілей цього поліглота виникає ті ж проблеми, що і Ортагонал.
- 1999 рік: Єдиною мовою, яку я міг знайти, був стільниковий автомат Кріса Пресі РЕДГРЕН . На жаль, на відміну від свого попередника RUBE, він, схоже, не має семантики вводу / виводу.
- 2000 рік: Є ще один стільниковий автомат Кріса Пресі, який називається noit o 'mnain worb, але він також не має жодного вводу-виводу. Є також Numberix, який я не намагався запустити, і я не впевнений, чи не буде він ігнорувати не шістнадцяткові символи у вихідному коді.
- 2002: Там є Clunk без вводу / виводу та ZT , специфікація якої мене лякає.
- 2007: Тут я знайшов три мови. Zetaplex базується на зображенні (так що ні), і RubE On Conveyor Belts, схоже, вимагає заголовка з досить строгим форматом, який би переплутався з першим рядком програми. Також є Cellbrain від Quintopia, але, здається, він вимагає і конкретного заголовка.
- 2013 рік: Я знову знайшов три мови. Риболовля може бути можливою при значній кількості реструктуризації, але це вимагатиме початку програми з дійсного доку. Quipu , з пам’яті, занадто суворий щодо свого синтаксису, щоб дозволити багато поліглотування. А Swordfish - ще один член сім'ї> <>, але, на жаль, мені не вдалося знайти перекладача. В іншому випадку це, мабуть, буде досить легко додати.
Якщо когось цікавить, ось повний перелік впроваджених 2D мов, відсортованих за роками , наскільки я міг їх знайти (на той момент, коли ця відповідь була розміщена). Якщо у цьому списку відсутні будь-які, будь ласка, повідомте мене в чаті, оскільки я був би дуже зацікавлений у повному списку.