Простий перекладач з гольфу


13

Виклик:

Ваше завдання - створити простий перекладач простої мови для гольфу.


Вхід:

Введення буде у вигляді рядка, розділеного пробілами.

Ви можете замінити простір тим, що вам потрібно


Вихід:

Виведіть результат (число або рядок), отриманий після виконання всіх операцій. Якщо є більше одного виходу, об'єднайтеся разом, щоб дати єдиний результат (немає роздільників). Початкове значення змінної завжди дорівнює нулю. тобто: Це починається з0


Синтаксис мови:

Мова має наступних операторів:

inc  ---> add one to variable
dec  ---> remove one from variable
mult ---> multiply variable by 2
half ---> divide the variable by 2
Pri  ---> print the variable to console (or whatever your language has)
exit ---> end the program (anything after this is ignored)

Приклади:

inc inc inc dec Pri exit                 ---> 2
dec inc mult inc inc Pri                 ---> 2
inc inc inc mult half Pri exit inc       ---> 3
inc Pri inc Pri inc Pri exit half mult   ---> 123
Pri exit                                 ---> 0
inc half Pri exit                        ---> 0.5 

Обмеження:

Це код-гольф, тому найкоротший код у байтах для кожної мови виграє.


Примітка:

  • Введення завжди буде дійсним. (рядок операторів, розділених пробілом)
  • Ви можете округлити до найближчого цілого числа, якщо ви не хочете десяткових знаків.

3
Чи можу я взяти список рядків? Чи можу я використати іншу капіталізацію?
користувач202729

Додати футляр виходу? вихід повинен мати значення
l4m2

1
@Kaldo: Ви можете відокремитись за допомогою нових рядків
Мухаммед Салман

3
Гм, я б не назвав цю мову "мовою для гольфу".
Paŭlo Ebermann

1
Це Deadfish з подвійними та половинними замість квадратних та довших імен команд
Jo King

Відповіді:


8

Баш , 61 байт

sed '1i0
s/.//2g;y"idmhe"+-*/q";/+\|-/i1
/*\|\//i2
/P/cdn'|dc

Спробуйте в Інтернеті!

Перетворює програму в програму dc, потім оцінює її як код dc. Це займає введення, розділене новими рядками. Зауважте, що dc заснований на стеці та використовує зворотні польські позначення.

Спочатку вхід подається на sed

1i0 на першому рядку введення вставте (додайте) 0, це буде акумулятором

s/.//2g видаліть усе, крім першого символу в кожному рядку

y"idmhe"+-*/q"транслітерації idmheв +-*/qвідповідно, + - * / є арифметичні команди і д завершує роботу програми

/+\|-/у кожному рядку, що містить + або -, i1вставити 1

/*\|\//у кожному рядку, що містить * або /, i2вставити 2

/P/у кожному рядку, що містить P, cdnзмініть його на dn, еквівалентний дублікату та виводу без нового рядка в постійному струмі

Тепер це оцінюється як вираз постійного струму.


2
Я вважаю, що нерозумно очікувати, що sedсинтаксис стане ще більш чужим, ніж раніше вважалося можливим, коли гольф вступає в гру.
Матін Ульхак

6

Желе , 21 байт

ḲḢ€O%11ị⁾’‘j“IȮḤH”¤VI

Спробуйте в Інтернеті!


Зауважимо, що значення ASCII перших символів ( idmhPe) модуля 11 є унікальним модулем 6.


Використання модуля 16:

Желе , 21 байт

ḲḢ€O%⁴ị“ḢwġḞkz’ṃØJ¤VI

Спробуйте в Інтернеті!

Рядок, який використовується для індексації, є ḤH‘’IȮв цьому випадку. Ті ‘’вже не на кордонах.


Використання 11 байт для представлення 6-байтового рядка - це дуже погано. Але ... “”бере 2 байти, ¤займає 1 байт, самі дані займають 6 байт, залишилося 2 байти, щоб щось зробити. В даний час це і є j, але ịØJабо ṃØJнабагато гірше, і не працює (тому що Unicode).
користувач202729

Концепція рядка jli ("Рядок - це список цілих чисел зі спеціальним прапором, що впливає на друк") чудово.
користувач202729

5

R , 128 125 байт

Reduce(function(x,y)switch(y,i=x+1,d=x-1,m=x*2,h=x/2,P={cat(x);x}),substr(el(strsplit(gsub("e.*$","",scan(,""))," ")),1,1),0)

Спробуйте в Інтернеті!

Потрібно викликати, source(echo=FALSE)щоб запобігти автоматичному друкуванню повернутого значення. Альтернативою було б обернути все,invisible але це набагато менше гофрованого (і руйнує мій [ще] приємний рахунок байтів).


3

05AB1E , 25 байт

΀¬"idmhPe"S"><·;=q"S‡J.V

Спробуйте в Інтернеті!

Відображає кожну з мовних функцій відповідною функцією 05AB1E (використовуючи першу таблицю кожної функції), а потім виконує отриманий рядок як код 05AB1E.



2

Python 2 , 131 125 122 121 118 117 115 байт

v=0;o=""
for x in input().split("x")[0].split():
 if"Q">x:o+=`v`
 else:v+=(1,-1,v,-v/2.)['idmh'.find(x[0])]
print o

Спробуйте в Інтернеті!

-6 і -3 завдяки @Rod

-3 і -2 завдяки @etene

-1 замінивши "Pri"==xна"P"in x


Ви можете splitувімкнути "exit"та отримати 1-й блок, замість breakтого , щоб зберегти 4 байти
стрижень

1
Ви можете видалити круглі дужки навколо 'idmh'та використовувати findзамість них index, що дозволить заощадити кілька байтів
etene

@Rod - насправді можна зробити це трохи далі і розділити, exщоб зберегти ще 2
ElPedro

Ви можете замінити v=(v+1,v-1,v*2,v/2.)з , v+=(1,-1,v,-v/2.)він повинен працювати, не проходять , хоча
Rod

@Rod - думав про це, але не міг розробити, як це зробити half. Так просто! Спасибі.
ElPedro

2

Пітон 3 , 110 91 82 байт

exit призведе до виходу програми з помилкою.

x=0
for c in input():c=='P'==print(x,end='');x+=(1,-1,x,-x/2,c,0)['ndmhx'.find(c)]

Спробуйте в Інтернеті!


Скоротіть імена змінних, щоб зберегти 9 байт. i='x+=1';d='x-=1';...а потім у своєму execдзвінку змініть це наexec(eval(c[0]))
mypetlion

@mypetlion Дякую, але я знайшов кращий спосіб.
mbomb007

Я думаю, що це дійсно: 82 байти
Лінн

@Lynn Це чудово! Я не міг придумати хороший спосіб короткого замикання на printзаяву!
mbomb007

2

JavaScript (ES6), 83 79 байт

Збережено 4 байти завдяки @ l4m2

Ітеративно замінює інструкції або вихідними, або порожніми рядками.

s=>s.replace(/\S+./g,w=>m<s?'':w<{}?m:(m+={d:-1,e:w,i:1,m}[w[0]]||-m/2,''),m=0)

Спробуйте в Інтернеті!

Прокоментував

s =>                       // given the input string s
  s.replace(/\S+./g, w =>  // for each word w in s:
    m < s ?                //   if m is a string:
      ''                   //     ignore this instruction
    :                      //   else:
      w < {} ?             //     if w is 'Pri' ({} is coerced to '[object Object]'):
        m                  //       output the current value of m
      : (                  //     else:
          m +=             //       add to m:
            { d: -1,       //         -1 if w is 'dec'
              e: w,        //         w  if w is 'exit' (which turns m into a string)
              i: 1,        //         1  if w is 'inc'
              m            //         m  if w is 'mult'
            }[w[0]]        //       using the first character of w to decide
            || -m / 2,     //       or add -m/2 (for 'half') if the above result was falsy
        ''),               //       do not output anything
    m = 0                  //   m = unique register of our mighty CPU, initialized to 0
  )                        // end of replace()

s=>s.replace(/\S+./g,w=>k<s?'':w<{}?k:(k+={d:-1,e:w,i:1,m:k}[w[0]]||-k/2,''),k=0)
l4m2

@ l4m2 Це w<{}чисто зло: p
Арнольд

s=>s.replace(/\S+./g,e=>m<s?'':e<{}?m:(m+={d:-1,e,i:1,m}[e[0]]||-m/2,''),m=0)також робота
l4m2

2

Вугілля деревне , 37 35 байт

≔⁰ηF⎇№θx…θ⌕θxθ≡ιn≦⊕ηd≦⊖ηm≦⊗ηh≦⊘ηrIη

Спробуйте в Інтернеті! Посилання на багатослівну версію коду. Натхненний відповіддю @ RickHitchcock Пояснення:

≔⁰η

Очистити змінну.

F⎇№θx…θ⌕θxθ≡ι

Скоротіть вхід у випадку, xякщо такий є, а потім переведіть петлю і переключіть кожен символ (залишок) вводу.

n≦⊕η

nя n створює змінну.

d≦⊖η

d d ecrements змінної.

m≦⊗η

m m виводить змінну на два (тобто подвоєння).

h≦⊘η

h h alves змінна.

rIη

rp r вводить змінну, передану на рядок.


1
@RickHitchcock Вибачте, не перевірив це досить ретельно. Я знайшов вирішення, але це коштувало мені байта.
Ніл

2

JavaScript (ES6), 77 75 байт

(Позичена ( викрадена ) @ хитрість Арнольда використовувати mяк ім'я змінної, економлячи 2 байти.)

f=([c,...s],m=0)=>c<'x'?(c=='P'?m:'')+f(s,m+({h:-m/2,d:-1,n:1,m}[c]||0)):''

Рекурсивно ходить по рядку, шукаючи виразних літер за інструкцією та ігноруючи решту:

  • n: вкл
  • d: груд
  • м: мул
  • год: половина
  • П: При
  • x: вихід

Приймає перевага в тому , що НЕ undefinedє ні більше , ні менше , ніж 'x', в результаті чого рекурсії до зупинки в кінці рядка або коли він зустрічає 'x'в виході .


1
Після вашого видаленого коментаря, на який я, звичайно, більше не можу відповісти, я забув вставити посилання на виправлений код (d'oh!), Але я знайшов новий підхід, який на 2 байти коротший від моєї первісної спроби.
Ніл


1

JavaScript (Node.js) , 91 байт

_=>_.split` `.map(o=>o<{}>!_?S+=+i:o<"e"?i--:o<"f"?++_:o<"i"?i/=2:o<"j"?i++:i*=2,i=S="")&&S

Спробуйте в Інтернеті!

JavaScript (Node.js) , 96 байт

_=>_.split` `.map(o=>F?0:o<"Q"?S+=i:o<"e"?i--:o<"f"?F=1:o<"i"?i/=2:o<"j"?i++:i*=2,F=i=0,S="")&&S

Спробуйте в Інтернеті!

JavaScript (Node.js) , 99 байт

s=>s.split` `.map(_=>eval('++i7--i7++e7u+=+i7i*=27i/=2'.split(7)[Buffer(e+_)[0]%11%6]),e=i=u='')&&u

Спробуйте в Інтернеті!


1

JavaScript, 107 байт

s=>eval('x=0;x'+(s.split` `.map(v=>({i:"++",d:"--",m:"*=2",h:"/=2",P:";alert(x)",e:"//"})[v[0]]).join`;x`))


1

Луа, 207 байт

s=0;n=0;for a in io.read():gmatch'.'do if s==0 then s=1;n=a=='i'and n+1 or a=='d'and n-1 or a=='m'and n*2 or a=='h'and n/2 or n;if a=='P'then print(n)elseif a=="e"then break end elseif a==' 'then s=0 end end

1

Python 3 , 114 110 109 116 байт

Насправді, у Python 2 було б на два байти менше, тому що execце заява і не потрібні дужки ...

  • Збережено 4 зайвих байти завдяки @ElPedro

  • Збережено додатковий байт, скориставшись тим, що findповертає -1 на помилку, яка потім може бути використана як індекс

  • +7 байт, тому що я не помітив правила про нові строки :(

i=0;exec(";".join("i+=1 i-=1 i*=2 i/=2 print(i,end='') exit()".split()["idmhP".find(h[0])]for h in input().split()))

Спробуйте в Інтернеті!

Позначає перший символ кожного введеного слова на фрагмент коду Python. Потім вони об'єднуються та виходять exec.

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


112 Спробуйте в Інтернеті! якщо у вас є команди як пробіл, відокремлений рядком, і розділіть його.
ElPedro

1
110 насправді, як дужки можуть перейти Спробуйте в Інтернеті!
ElPedro

Це не дає правильного результату. Питання говорить, що ви повинні друкувати без роздільників, так що вам потрібно print(i,end=''). Дивіться 4 тестовий випадок.
mbomb007

Я не помітив, я це виправлю. Спасибі !
etene

@etene Прокоментуйте, коли ви виправите це, і я вилучу свій нижчий запис.
mbomb007

1

Ruby + -na, 81 73 65 байт

x=0;$F.map{|w|eval %w{x+=1 x-=1 1/0 $><<x x*=2 x/=2}[w.ord%11%6]}

Спробуйте в Інтернеті!

Досить прямо. Для першої літери кожного слова знайдіть відповідний командний рядок і evalйого. Використовує ціле ділення і exitsкидаючи a ZeroDivisionError.

-5 байт: Використовуйте .ord%11%6замість пошуку рядків. Кредит йде на користувачу202729

-3 байти: .ord розглядає лише перший символ рядка, тому я можу пропустити [0].

-8 байт: Використовуйте -aпрапор для автоматичного розділення вводу, завдяки Кирилу Л.


1
Ви можете зекономити ще більше байтів, додавши -aопцію зробити автосплит для вас, як це
Кирилл Л.

1

Emojicode , 270 байт

🐖🔥🍇🍮c 0🔂j🍡💣🐕🔟 🍇🍊😛j🔤inc🔤🍇🍮c➕c 1🍉🍋😛j🔤dec🔤🍇🍮c➖c 1🍉🍋😛j🔤mult🔤🍇🍮c✖️c 2🍉🍋😛j🔤half🔤🍇🍮c➗c 2🍉🍋😛j🔤Pri🔤🍇👄🔡c 10🍉🍓🍇🍎🍉🍉🍉

Спробуйте в Інтернеті!

🐋🔡🍇
🐖🔥🍇
🍮c 0
🔂j🍡💣🐕🔟 🍇
🍊😛j🔤inc🔤🍇🍮c➕c 1🍉
🍋😛j🔤dec🔤🍇🍮c➖c 1🍉
🍋😛j🔤mult🔤🍇🍮c✖️c 2🍉
🍋😛j🔤half🔤🍇🍮c➗c 2🍉
🍋😛j🔤Pri🔤🍇👄🔡c 10🍉
🍓🍇🍎🍉🍉🍉🍉

🏁🍇
 🔥🔤inc inc inc dec Pri exit🔤
😀🔤🔤
 🔥🔤dec inc mult inc inc Pri🔤
😀🔤🔤
 🔥🔤inc inc inc mult half Pri exit inc🔤
😀🔤🔤
 🔥🔤inc Pri inc Pri inc Pri exit half mult🔤
😀🔤🔤
 🔥🔤Pri exit🔤
😀🔤🔤
 🔥🔤inc half Pri exit🔤
🍉

0

SNOBOL4 (CSNOBOL4) , 165 байт

	P =INPUT ' exit ' 
	x =0
S	P LEN(1) $ L ARB ' ' REM . P	:S($L)F(end)
i	X =X + 1	:(S)
d	X =X - 1	:(S)
P	O =O X		:(S)
m	X =X * 2	:(S)
h	X =X / 2.	:(S)
e	OUTPUT =O
END

Спробуйте в Інтернеті!

Валовий.

	P =INPUT ' exit ' 				;* append ' exit ' to the input to guarantee that the program will stop
	x =0						;* initialize x to 0 else it won't print properly if the program is 'Pri'
S	P LEN(1) $ L ARB ' ' REM . P	:S($L)F(end)	;* set L to the first letter of the word and goto the appropriate label
i	X =X + 1	:(S)
d	X =X - 1	:(S)
P	O =O X		:(S)				;* append X to the output string
m	X =X * 2	:(S)
h	X =X / 2.	:(S)				;* divide by 2. to ensure floating point
e	OUTPUT =O					;* print whatever's in O, which starts off as ''
END

0

C # (.NET Core), 186 байт

class P{static void Main(string[]a){int v=0;foreach(var s in a){var i=s[0];if(i=='i')v++;if(i=='d')v--;if(i=='m')v*=2;if(i=='h')v/=2;if(i=='P')System.Console.Write(v);if(i=='e')break;}}}

Ви можете голитися 26bytes геть це, роблячи кілька простих речей, як декларування iз v, консультаційної таблицю ASCII , так що ви можете використовувати невелику кількість, переставляючи ifс, а потім з допомогою потрійного: class Z{static void Main(string[]a){int v=0,i;foreach(var s in a){i=s[0]%'d';if(i==1)break;if(i>9)System.Console.Write(v);else v=i<1?v-1:i<5?v/2:i<6?v+1:v*2;}}}(PS пояснення того , як він працює і як його використовувати це (наприклад, очікує, що аргументи командного рядка) завжди цінується!)
VisualMelon

(О, це бентежить ... Мені слід користуватися %50замість %'d')
VisualMelon,

0

Perl 5 -a , 61 байт

eval'$,'.qw(++ -- ;exit ;print$,||0 *=2 /=2)[(ord)%11%6]for@F

Спробуйте в Інтернеті!

Вкрав @ user202729 ігровий ord%11%6трюку

Як?

-a            # split the input by whitespace, store in @F
eval          # Execute the string that results from:
'$,'          # $, (the accumulator)
.             # appending:
qw(           # create an array for the following whitespace separated values:
++ --            # operators for inc & dec
;exit            # exit
;print$,||0      # Pri  (||0 ensures that 0 is output if accumulator is null
*=2 /=2)         # mult div
[(ord)%11%6] # @user202729's trick selects one of the preceding operations
for@F        # for every term input

0

Піт, 44 байт

Vmx"idmhPe"hdcwd=Z@[hZtZyZcZ2ZZ)NIqN4pZIqN6B

Тестовий сюїт

пояснення

Vmx"idmhPe"hdcwd=Z@[hZtZyZcZ2ZZ)NIqN4pZIqN6B   ## full program
             cwd                               ## split input on space
Vmx"idmhPe"hd                                  ## iterate through list of numbers corresponding to operators
                =Z@[hZtZyZcZ2ZZ)N              ## assign the variable Z (initialliy Zero) it's new value
                                 IqN4pZ        ## print Z if the current operator is "Pri" (4)
                                       IqN6B   ## break if the current operator is "exit" (5)

0

TI-BASIC, 112 байт

Це використовує деякі припущення, які є AFAIK цілком прийнятними. Номер один - це те, що всі змінні ініціалізуються до нуля перед виконанням; номер два, що вводиться через Ans.

Ans+" E→Str1
While 1
I+4→I
sub(Str1,I-3,1→Str2
A+(Ans="I")-(Ans="D
If inString("MH",Str2
Then
I+1→I
2AAns+A/2(1-Ans
End
If Str2="P
Disp A
If Str2="E
Stop
Ans→A
End

0

Java (OpenJDK 8) , 164 байти

a->{int c=0;for(String g:a.split(" ")){char b=g.charAt(0);if(b==105)c++;if(b==100)c--;if(b==109)c*=2;if(b==104)c/=2;if(b==80)System.out.print(c);if(b==101)return;}}

Спробуйте в Інтернеті!

Вище є моє рішення, яке округляється до цілих чисел, а нижче - моє рішення, яке обробляє десяткові знаки. Неприємний спосіб друку подвоєних символів додає ще 55 бай до рахунку. Я залишив нові рядки, щоб зробити код читабельнішим у другому поданні лише тому, що це по суті те саме рішення з однією додатковою командою та заявою про імпорт.

Java (OpenJDK 8) , 219 байт

a->{
double c=0;
for(String g:a.split(" ")){
char b=g.charAt(0);
if(b==105)c++;
if(b==100)c--;
if(b==109)c*=2;
if(b==104)c/=2;
if(b==80)System.out.print(new DecimalFormat("0.#").format(c));
if(b==101)return;}}

Спробуйте в Інтернеті!


0

C (gcc) , 120 114 111 байт

-6 байт завдяки стельовій кішці.

x,d;f(char*s){for(x=0;s>1;s=index(d^1?s:"",32)+1)d=*s-100,x+=d?d==5:-1,x*=d^9?d^4?1:.5:2,d+20||printf("%d",x);}

Спробуйте в Інтернеті!

124 байти

Версія з плаваючою комою:

d;f(char*s){for(float f=0;s>1;s=strchr(s,32)+1)d=*s-80,f+=d==25,f-=d==20,f*=d^29?d^24?1:.5:2,s=d^21?s:"",d?:printf("%f",f);}

Спробуйте в Інтернеті!

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


0

33 , 62 байти

s'i'{1a}'d'{1m}'m'{2x}'h'{2d}'P'{o}'e'{@}It[mzsjk""ltqztItn1a]

Спробуйте в Інтернеті!

Ця програма бере інструкції, розмежовані новими рядками

Пояснення:

It[mzsjk""ltqztItn1a]
  [mz            n1a] | Forever
It    jk       It     | - Get the first character of the next instruction
            qz        | - Call the function declared previously
     s  ""lt  t       | - Make sure we don't lose track of the variable

Код перед цим сегментом визначає всі функції.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.