简单的高尔夫口译员


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
我可以列出一个字符串列表吗?我可以使用其他大写字母吗?
user202729 '18

添加出口案例?出口应该的问题
l4m2

1
@Kaldo:您可以使用换行符进行分隔
Muhammad Salman

3
嗯,我不会将这种语言称为“高尔夫语言”。
圣保罗Ebermann

1
这是死鱼,带有两倍和一半而不是方形和更长的命令名称
Jo King

Answers:


8

重击,61字节

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

在线尝试!

将程序转换为直流程序,然后将其评估为直流代码。这将输入用换行符分隔。请注意,dc基于堆栈,并且使用反向抛光符号。

输入首先通过管道传输到sed

1i0 在输入的第一行,插入(添加)0,这将是累加器

s/.//2g 删除每行中除第一个字符外的所有内容

y"idmhe"+-*/q"分别音译idmhe+-*/q+-* /是算术命令,q退出程序

/+\|-/在包含+或-的每一行上,i1插入1

/*\|\//在包含*或/的每一行中,i2插入2

/P/在包含P的每一行上,cdn将其更改为dn,等效于重复并在dc中输出而不包含换行符

现在,将其评估为dc表达式。


2
我想,sed在打高尔夫球时,期望语法变得比以前认为的更加陌生是不合理的。
Mateen Ulhaq

6

果冻,21字节

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

在线尝试!


请注意,第一个字符(idmhPe)模11 的ASCII值是唯一的模6。


使用模16

果冻,21字节

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

在线尝试!

ḤH‘’IȮ在这种情况下,将使用用于索引的字符串。在‘’上边界不再。


用11个字节表示6个字节的字符串是...太可惜了。但是... “”需要2个字节,¤需要1个字节,数据本身需要6个字节,还剩下2个字节可以做某事。目前,它是j,但ịØJ还是ṃØJ差很多,并且不工作(因为Unicode)的。
user202729 '18

jli的字符串概念(“字符串是带有特殊标志以影响打印的整数列表”)很棒。
user202729 '18

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

红色,121字节

func[s][v: 0 parse s[any[["i"(v: v + 1)|"d"(v: v - 1)|"m"(v: v * 2)|"h"(v: v / 2.0)|"P"(prin v)|"e"(exit)]thru" "| end]]]

在线尝试!

可读性:

f: func [s] [
    v: 0
    parse s [
        any [
            [ "i" (v: v + 1)
            | "d" (v: v - 1)
            | "m" (v: v * 2)
            | "h" (v: v / 2.0)
            | "P" (prin v)
            | "e" (exit)]
            thru [" " | end]
        ]
    ]
] 

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 '18

您可以替换v=(v+1,v-1,v*2,v/2.)v+=(1,-1,v,-v/2.)它应该工作,没有测试但
罗德

@Rod-对此进行了思考,但无法解决该问题half。很简单!谢谢。
ElPedro '18

2

Python 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谢谢,但是我找到了一个更好的方法。
mbomb007 '18

我认为这是有效的:82个字节
Lynn

@Lynn太好了!我想不出一种捷径来缩短print语句!
mbomb007 '18

2

JavaScript(ES6),83 79字节

@ l4m2节省了4个字节

用输出或空字符串迭代替换指令。

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 '18

@ l4m2这w<{}是纯粹的邪恶:p
Arnauld

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

2

木炭37 35字节

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

在线尝试!链接是详细版本的代码。受@RickHitchcock的答案启发。说明:

≔⁰η

清除变量。

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

x如果有输入,则在处截断输入,然后循环并打开输入(其余)的每个字符。

n≦⊕η

nÑ crements变量。

d≦⊖η

d d增加变量。

m≦⊗η

m m将变量乘以2(即双精度)。

h≦⊘η

h ħ阿尔维斯变量。

rIη

rp r int将变量强制转换为字符串。


1
@RickHitchcock抱歉,测试不够彻底。我找到了解决方法,但花了我一个字节。
尼尔,

2

JavaScript(ES6),77 75字节

(借用(偷走)@Arnauld的技巧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:dec
  • m:多
  • h:一半
  • P:Pri
  • x:退出

利用undefined既不大于也不小于的事实'x',导致递归在字符串的结尾遇到'x'in 出口时停止


1
跟进您删除的评论(我当然无法再回复)之后,我忘了粘贴到已更正代码的链接(d'oh!),但是我发现了一种新方法,该方法比我原来的尝试还要短2个字节。
尼尔,



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

Lua,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是一条语句,不需要括号...

  • 多亏@ElPedro,节省了4个额外的字节

  • 利用find错误时返回-1 的事实节省了一个额外的字节,然后可以将其用作索引

  • +7个字节,因为我没有注意到no-newlines规则:(

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 '18 -4-27

1
实际上可以将110放在括号中尝试在线!
ElPedro '18

这不会给出正确的输出。问题是您必须在打印时不要使用分隔符,因此需要print(i,end='')。参见第4个测试用例。
mbomb007 '18

我没有注意到,我会修复它。谢谢 !
etene

@etene在您修复它后发表评论,我将删除我的下注。
mbomb007 '18

1

Ruby + -na81 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抛出ZeroDivisionError

-5个字节:使用.ord%11%6而不是字符串查找。幸得user202729

-3个字节:.ord仅考虑字符串的第一个字符,因此我可以跳过一个[0]

-8个字节:-a感谢Kirill L,使用标志自动拆分输入


1
您可以通过添加节省更多的字节-a选项完成自动分割为你,就像这样
基里尔L.

1

表情符号,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 iv咨询的ASCII表,所以你可以用小的数字,重新安排if:s,然后用三元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 -a 5,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

Pyth,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;}}

在线尝试!

上面是四舍五入为整数的解决方案,但下面是我处理小数的解决方案。Java打印的令人讨厌的方式是将分数再增加55个再见。我留下了新行,以使代码在第二次提交中更具可读性,这仅是因为它本质上是相同的解决方案,只是带有一个额外的命令和一个import语句。

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字节,感谢ceilingcat。

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

该段之前的代码定义了所有功能。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.