Інтерпретувати Kipple!


12

Вступ

Kipple - це езотерична мова програмування на основі стека, винайдена Руном Бергом у березні 2003 року.

Kipple має 27 стеків, 4 оператори та структуру управління.

Стеки

Стеки названі a- zі містять 32-бітні цілі числа. Існує також спеціальний стек @, щоб зробити виведення номерів більш зручним. Коли число висувається @, значення ASCII цифр цього числа насправді висуваються натомість. (Наприклад, якщо натиснути 12 @, він нажатиме 49, а потім 50 к @.)

Введення висувається на вхідний стек iперед виконанням програми. Інтерпретатор попросить зберегти значення iперед виконанням. Після завершення виконання все, що на вихідному стеку o, вискакує для виведення у вигляді символу ASCII. Оскільки це єдиний механізм вводу-виводу Kipple, взаємодія з програмою Kipple неможлива.

Оператори

Операнд є або ідентифікатором стека, або підписаним 32-бітовим цілим числом.

Push: >або<

Синтаксис: Operand>StackIndentifierабоStackIndentifier<Operand

Оператор Push відводить операнда вліво і натискає на вказаний стек. Наприклад, 12>aбуде натиснути значення 12 на стек a. a>bз'явиться найвище значення зі стека aі натисне його на стек b. Вискакуючи порожній стек завжди повертається 0. a<bеквівалентно b>a. a<b>cpops найвище значення від bі підштовхує до обох cі a.

Додати: +

Синтаксис: StackIndentifier+Operand

Оператор Add висуває в стек суму найвищого елемента на стеку та операнда. Якщо операнд є стеком, то значення вискакує з нього. Наприклад, якщо найвище значення стека aдорівнює 1, то a+2натисніть на нього 3. Якщо aпорожній, то a+2натисніть на нього 2. Якщо верхні значення стека aі bрівні 1 і 2, то a+bз'явиться значення 2 з стека bі натиснути 3 в стек a.

Віднімайте: -

Синтаксис: StackIndentifier-Operand

Оператор Subtract працює точно так само, як оператор Add, за винятком того, що він віднімає замість додавання.

Ясно: ?

Синтаксис: StackIndentifier?

Оператор Clear очищує стек, якщо його найвищий елемент дорівнює 0.

Перекладач ігноруватиме всі , що не поруч з оператором, тому наступна програма буде працювати: a+2 this will be ignored c<i. Однак правильним способом додавання коментарів є використання #символу. Все, що знаходиться між #символом a та кінцевим рядком, видаляється перед виконанням. Символ ASCII №10 визначається як кінцевий рядок у Kipple.

Операнди можуть бути спільними для двох операторів, наприклад, a>b c>b c?можуть бути записані як a>b<c?.

Програма 1>a<2 a+aпризведе до aвмісту значень [1 4](знизу вгору), а не [1 3]. Так само і для -оператора.

Структура управління

У Kipple є лише одна структура управління: петля.

Синтаксис: (StackIndentifier code )

Поки зазначений стек не порожній, код у відповідних дужках повториться. Петлі можуть містити інші петлі. Наприклад, (a a>b)перемістить усі значення стека aна стек b, хоча порядок буде змінено . Функціонально однаковий, але більш елегантний спосіб це зробити (a>b).

Приклади

100>@ (@>o)

Це виведе 100

33>o 100>o 108>o 114>o 111>o 87>o 32>o 111>o 108>o 108>o 101>o 72>o

Це надрукується "Hello World!". Коли oстек виводиться, він починає виводити символи зверху стека вниз.

#prime.k by Jannis Harder
u<200
#change 200


k<2>m
u-2
(u-1 u>t u>z u<t
  (k>e e+0 e>r)
  (e>k)
  m+1
  m>t
  m>z
  m<t
  t<0>z? t?
  1>g
  (r>b
    m+0 m>a
    b+0 b>w
    (a-1 
      b+0 b>j
      j?
      1>s
      (j<0>s j?)
      s?
      (s<0 w+0 w>b s?)
      a>t
      a>z
      t>a
      b-1
      b>t
      b>z
      t>b
      z<0>t? z?
    a?)
    b?
    1>p
    (b<0 b? 0>p)
    p?
    (p 0>r? 0>p? 0>g)
  )
  g?
  (g m+0 m>k 0>g?)
u?)
(k>@
  10>o
  (@>o)
)

Це генератор простих чисел, але я не впевнений, як це працює.

Правила

  • Ви повинні написати програму / функцію, що інтерпретує Kipple. Ця програма / функція може отримати програму Kipple через вихідний файл, або отримати її через STDIN безпосередньо від користувача. Якщо STDIN недоступний, він повинен отримати його з введення з клавіатури та продовжувати отримувати введення, поки не буде введено певний недрукований символ. Наприклад, якщо ваш перекладач записаний у машинному коді x86, він отримає символ програми Kipple за символом з клавіатури, і продовжує це робити, поки esc(або будь-яка інша клавіша, яка не видає символу для друку), не буде натиснута.

  • Якщо є помилка, наприклад, синтаксична помилка або переповнення стека, вона повинна визнати її якимось чином, наприклад, повернувши 10 замість 0 або повідомлення про помилки, що створюються інтерпретатором / компілятором, АМЕ НЕ ПЕЧАТКУВАТИ ПОМИЛКИ ПОМИЛКИ .

  • Будь-які інші регулярні правила кодового гольфу застосовуються до цього виклику.

  • Ваш код буде протестовано на прикладі в архіві зразків Kipple

Це . Найкоротший код у байтах виграє. Щасти!


Зауважте, що в Kipple є необов'язковий оператор ", але він не є частиною специфікації та просто додатковою функцією в офіційному перекладачі. Я не згадував це тут, тому його не потрібно підтримувати у ваших поданнях.

Якщо у вас є якісь сумніви щодо будь-якої частини специфікації, ви можете вивчити її за допомогою офіційного перекладача, написаного на Java . Це завантажить zip-файл, що містить скомпільовану програму та вихідний код. Це ліцензія згідно з GPL.


1
Чи потрібно використовувати 32-бітні цілі числа, підписані чи ми можемо перейти з натуральним цілим типом реалізації хоста? (Найважливіші випадки - це, ймовірно, непідписані 32-бітні цілі числа, підписані або неподписані 8-бітні цілі числа та цілі числа довільної точності.)
Мартін Ендер

ну, це було те, що я знайшов на езотричній вікі. так, оскільки ваш перекладач може бути несумісний з іншими програмами kipple, механізм яких заснований на цій функції

Чи можете ви бути більш конкретними щодо поведінки у випадку помилок? Отже, ми можемо повернути неправильну відповідь або помилку, але ми не можемо надрукувати помилку?
Олексій А.

@ Алекс А. Так, оскільки це може розглядатися як вихід програми, і ви можете зробити програму kipple, яка може мати такий же вихід, як і повідомлення про помилку. Крім того, "дешевше" (використовує менше символів) не мати функції / заяви, яка друкує повідомлення про помилку.

3
Який пробіл може виникнути у вихідній програмі? Як я можу запитати про введення, iякщо я беру програму-джерело від stdin?
orlp

Відповіді:


6

C, 709 702 байт

Оцінка байта з новими рядками (які можна видалити) видаляється, але для зручності читання я розміщую її тут з новими рядками:

#define R return
#define C ;break;case
c[999]={};*P=c;*S[28];M[99999]={};t;*T;
u(s,v){S[s]+=28;*S[s]=v;
if(s>26){for(t=v/10;t;t/=10)S[s]+=28;T=S[s];do{*T=48+v%10;T-=28;}while(v/=10);}}
o(s){t=S[s]-M>27;S[s]-=28*t;R S[s][28]*t;}
I(s){R s<65?27:s-97;}
O(int*p){if(!isdigit(*p))R o(I(*p));
for(;isdigit(p[-1]);--p);for(t=0;isdigit(*p);t*=10,t+=*p++-48);R t;}

main(i,a){for(i=0;i<28;++i)S[i]=M+i;
for(;~(*++P=getchar()););P=c+1;
for(;;){i=I(P[-1]);switch(*P++){
case 35:for(;*P++!=10;)
C'<':u(i,O(P))
C'>':u(I(*P),O(P-2))
C'+':u(i,*S[i]+O(P))
C'-':u(i,*S[i]-O(P))
C'?':if(!*S[i])S[i]=M+i
C'(':for(i=1,T=P;i;++T)i+=(*T==40)-(*T==41);if(S[I(*P)]-M<28)P=T;else u(26,P-c)
C')':P=c+o(26)-1
C-1:for(;i=o(14);)putchar(i); R 0;}}}

Компілюйте з gcc -w golf.c( -wзамовчує застереження для вашого розуму).

Підтримує все, крім iвхідних даних, оскільки запитувач ще не відповів на мій запит, як це зробити, якщо ви берете код з stdin. Він не повідомляє про синтаксичні помилки.


я відповів на ваше запитання щодо "i" стека в коментарях головної публікації.

btw як він читає програми kipple? через командні аргументи? як я повинен його використовувати?

@GLASSIC Він очікує, що програма на stdin.
orlp

Допоки ? Як почати виправдання?

@GLASSIC Просто передайте програму на stdin. Напр ./a.out < prime.k.
orlp

3

Ruby, 718 байт (наразі неконкурентоспроможний)

я дуже втомлений

Файл завантажується як аргумент командного рядка, а вхід надсилається через STDIN. Крім того, передайте файл в STDIN, якщо вам не потрібно вводити свій iреєстр.

Через деяку плутанину щодо специфікації, поточна версія не обробляє a<b>cналежним чином, а тому не конкурує, поки вона не буде виправлена.

a<b>cвиправлено зараз. Однак він все одно повертає неправильний результат при виконанні функції праймес, тому він як і раніше залишається неконкурентною відповіддю.

(f=$<.read.gsub(/#.*?\n|\s[^+-<>#()?]*\s/m,' ').tr ?@,?`
t=Array.new(27){[]}
t[9]=STDIN.read.bytes
k=s=2**32-1
r=->c{c=c[0];c[0]==?(?(s[c[1..-2]]while[]!=t[c[1].ord-96]):(c=c.sub(/^(.)<(\D)>(.)/){$1+"<#{t[$2.ord-96].pop||0}>"+$3}.sub(/(\d+|.)(\W)(\d+|.)?/){_,x,y,z=*$~
a=x.ord-96
b=(z||?|).ord-96
q=->i,j=z{j[/\d/]?j.to_i: (t[i]||[]).pop||0}
l=t[a]
y<?-?(x==z ?l[-1]*=2:l<<(l.pop||0)+q[b]
l[-1]-=k while l[-1]>k/2):y<?.?(x==z ?l[-1]=0:l<<(l.pop||0)-q[b]
l[-1]+=k while l[-1]<-k/2-1):y<?>?t[a]+=a<1?q[b].to_s.bytes: [q[b]]:y<???
(t[b]+=b<1?q[a,x].to_s.bytes: [q[a,x]]): l[-1]==0?t[a]=[]:0
z||x}while c !~/^(\d+|.)$/)}
s=->c{(z=c.scan(/(\((\g<1>|\s)+\)|[^()\s]+)/m)).map &r}
s[f]
$><<t[15].reverse.map(&:chr)*'')rescue 0

+1 у будь-якому випадку Ви спробували програму FV?
edc65

@ edc65 Програма послідовності Фібоначчі також друкує неправильну річ: 0 1 1 2 4 8 16...мені цікаво, чи це помилка специфікації
Value Ink

Ні, програма Фібоначчі лайна, наприклад, рядок a+0- це нісенітниця
edc65

Я думаю, що проблема простих чисел полягає в тому, що він не обробляє вкладені структури управління, але я не знаю багато про рубіні, я сумніваюся, що моя здогадка є правильною.

Ця програма повинна належним чином обробляти вкладені набори паренів через рекурсивний збіг регулярних виразів, /(\((\g<1>|\s)+\)|[^()\s]+)/mякий він використовує для розділення на лексеми та групи лексем. ( Перевірте його на regex101 ). Це, мабуть, помилка в решті мого розбору, але я не знаю, де.
Значення чорнила
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.