拼写单词算术


25

我们都已经看到过这些在线“算术”,如下所示:

Think of a number, divide by 2, multiply by 0, add 8.

而且,通过魔术,每个人最终都得到8!


语言

让我们定义一种使用上面文本的语法的编程语言,称为“ WordMath”。WordMath脚本遵循以下模板:

Think of a number, <commandlist>.

这基本上意味着:将一个数字(作为来自STDIN的输入)作为初始累加器,对其执行所有命令,然后输出结果。

这些命令由定界符,(逗号+空格)分隔。有效的命令是(注意,它#代表一个非负整数:)

  • add #/ subtract #-添加/减去累加器的值。
  • divide by #/ multiply by #- floordiv /乘累加器由给定的值。
  • subtract from #-与相似subtract,但acc = # - acc代替acc = acc - #
  • repeat-再次执行最后一个命令。这不能是第一个命令,但是您必须支持多个连续的重复。

挑战

你的任务是创建一个程序或功能,这需要一个有效WordMath脚本作为输入和 transpiles它变成一个有效的完整程序-相同的语言代码是英寸

例如,如果我的代码在Python 2中并且脚本是:

Think of a number, subtract from 10, add 10, multiply by 2.

输出的程序可以是:

a = input()
a = 10 - a
a += 10
a *= 2
print(a)

或者:

print(((10-input())+10)*2)

只要它是一个完整的程序,即可从输入STDIN或打印到STDOUT或该语言最接近的等价物。


规则

  • 您的原始程序可能会假设输入始终是有效的WordMath脚本。
  • 编译的程序不必处理数学错误,例如被0除。
  • 编译的程序可能会假设输入表示您语言的标准整数范围内的有效带符号整数。
  • 这是,因此最短的解决方案(以字节为单位)获胜。
  • 仅原始程序的字节数很重要-输出的代码可以任意长!

示例脚本

范例1:

Think of a number. 

接受输入,不执行任何操作,将其显示:WordMath的cat程序。

范例2:

Think of a number, divide by 5, subtract from 9.

请记住,“ divide”是楼层划分,因此对于此程序6 -> 8,和29 -> 4

范例3:

Think of a number, add 5, add 10, multiply by 2, subtract 15, repeat, divide by 2.

扩展的猫程序!

范例4:

Think of a number, subtract 1, repeat, repeat.

取一个数字并减去3。


我们必须支持连续重复吗?
darrylyeo's

1
当这是语言的默认类型时/如果它不支持整数,我们可以使用浮点数吗?
Rainer P.

@RainerP。仅当该语言不支持整数/整数除法时
FlipTack

1
的预期结果是-5/3什么?我们是0朝着负无穷还是朝着负无穷大?
马丁·恩德

1
@MartinEnder我想说它是向下取整,因为它是底数除法,但是如果您的语言将整数除法实现为0也可以。
FlipTack

Answers:


6

05AB1E59 56 54 52字节

„, ¡¦vyDþs.AJá'bK"dmas""/*+-"‡„-f„s-.:«D'rQi®}©}J'rK

在线尝试!

之后,我的大脑像地狱一样痛...它在05AB1E代码中的输出如下:

  • Think of a Number 由于隐式输入而被删除。
  • Subtract From #羽到#s-(交换ab并执行操作)。
  • Subtract #转换为#-
  • Add #转换为#+
  • Multiply by #转换为#*
  • Divide by #转换为#/
  • Repeat 抓取最后存储在寄存器中的所有内容并将其连接起来。

解释:

„, ¡                                                 # Split on ', '.
    ¦                                                # Remove the 'Think of a number'.
     vy                                        }     # Loop through chunks.
       Dþs                                           # Dupe, push only digits, swap.
          .AJá                                       # Acronymify without digits.
              'bK                                    # Remove the `b`.
                 "dmas""/*+-"‡                       # Replace letters with OPs.
                              „-f„s-.:               # Replace '-f' with 's-'.
                                      «              # Concat # with OP.
                                       D'rQ          # Dupe, push 1 if OP='r'.
                                           i®}       # If 'r', push last #OP.
                                              ©      # Store current OP.
                                                J'rK # Join, remove remaining r's.

例:

输入:

Think of a number, divide by 2, multiply by 10, add 8, subtract 6, subtract from 9, repeat, repeat, subtract 41.

输出:

2/10*8+6-9s-9s-9s-41-

尝试输入10的解决方案:

在线尝试!

在Google上查看:

这是指向Google中键入的相同方程式的链接。


13

C预处理器,362字节

我几乎在C预处理器中就完成了这项工作,但是重复命令实在太难实现了。因此,我改为使用预处理器将输入转换为数组,然后由其他一些代码解释。

main(){int c[]={
#define Think 
#define of
#define a
#define number 0
#define add 1,
#define subtract 2,
#define from 0,3,
#define multiply 4,
#define divide 5,
#define by
#define repeat 6, 0
#include "input.wm"
,'$'};int _,l,v;scanf("%d", &_);for(int i=1;c[i]-'$';++i){c[i]!=6?l=c[i],v=c[++i]:++i;l==1?_+=v:l==2?_-=v:l==3?_=v-_:l==4?_*=v:_/=v;}printf("%d",_);}

输入必须在“ input.wm”中提供,或仅转储到源代码的那一行中。我将其字节数包括在我的计数中,因为我认为它有点hacky,并且与挑战规则略有出入,因此非常合适。

无论如何,一旦将WordMath源代码转储到input.wm中,编译器就可以找到它,则应该能够按原样进行编译,并发出警告以生成可执行WordMath源代码所说明内容的可执行文件。


2
注意:不幸的是,当您以重复结束时,这对于某些编译器将失败。这是因为他们在0后面扔了一个空格,然后看到了一个杂散期,不知道该怎么做。
LambdaBeta

聪明,我印象深刻。
cat

7

视网膜,170字节

因为谁不想看到这个?

我想到了看到Retina解决方案有多棒,于是决定快速创建它。只花了一个小时。通常,字节数假定为ISO 8859-1编码。

S`, 
\.

T.*
.*¶$$*
\;+`(.*)¶rep.*(¶?)
$1¶$1$2
\d+
$*
.*f.* (1*)
1¶x¶$¶$1¶+`x1¶
m.* 
1¶
di.* (1*)
^¶$1 ¶^(1+) (\1)+1*$¶x$$#+¶1+ 1*¶x0¶x\d+¶$$*
s.* (1*)
^$1¶
a.* 
^¶
\z
¶1

在线尝试

输出具有结尾的换行符,在测试结果程序时不应复制该换行符。该程序不支持负片,因为Retina的标准整数范围(一元)不支持。

说明:

S`,                 # Split input on ", " putting each command on its own line
\.                  # Remove the period

T.*                 # Think of a number -> .*\n$* (replaces input with unary)
.*¶$$*
\;+`(.*)¶rep.*(¶?)  # Loop, replacing "repeat" with the line before it
$1¶$1$2
\d+                 # Replace all numbers with their unary representation
$*
.*f.* (1*)          # Replace "subtract from " with a subtract from program
1¶x¶$¶$1¶+`x1¶
m.*                 # Replace "multiply by " with a multiply program
1¶
di.* (1*)           # Replace "divide by " by my integer division program
^¶$1 ¶^(1+) (\1)+1*$¶x$$#+¶1+ 1*¶x0¶x\d+¶$$*
s.* (1*)            # Replace "subtract " with a subtraction program
^$1¶
a.*                 # Replace "add " with an addition program
^¶
\z                  # At the end, add a stage to change unary into decimal
¶1

数学程序:

加:

将数字加到开头。加5:

^
1111

减去:

从一开始就删除一些。减去5:

^11111

减去:

将输入1s 替换为xs。放在固定编号旁边。反复删除x1。减去10:

1
x
$
1111111111
+`x1

乘以:

1它们替换为一定数量。乘以3:

1
111

被除以:

这将我的Retina程序用于整数分区。除以2:

^                   # Place the fixed divisor before the dividend
11 
^(.+) (\1)+.*$      # Match the divisor, followed by each occurrence in the dividend.
x$#+                # Replace with the number of matches. Trailing ones are dropped
.+ .*               # If there are still two numbers, the result is zero
x0
x\d+                # Replace result (marked with an 'x') with unary
$*

恐怕我看不到它如何工作。无论我为减法命令尝试什么输入,结果都将损坏(输出中是否缺少换行符?)。我也看不到它如何处理负输入或负中间结果。
马丁·恩德

@MartinEnder如果您解释了为什么此简化程序在输出中给出两个,则我可以修复减法。retina.tryitonline.net/#code=JArCtjE&input=dGVzdAo
mbomb007

因为$在字符串的末尾或结尾的换行符之前匹配。你需要\z,如果你只想要前者。
Martin Ender

4

GNU awk,139个字节

BEGIN{RS="[,.]";c="{}{";ORS=";"}
/ad/{c="+="$2}
/c/{c="-="$2}
/om/{c="="$3"-$0"}
/l/{c="*="$3}
/v/{c="=int($0/"$3")"}
!NF{c="}1"}
$0="$0"c

调用:

$> awk `awk -f wordmath <<< "Think of a number, add 1, repeat, repeat."` <<< 0
$> 3

测试用例:

$> awk -f wordmath <<< "Think of a number."  
$> $0{}{;$0}1;

$> awk -f wordmath <<< "Think of a number, divide by 5, subtract from 9."
$> $0{}{;$0=int($0/5);$0=9-$0;$0}1;

$> awk -f wordmath <<< "Think of a number, add 5, add 10, multiply by 2, subtract 15, repeat, divide by 2."
$> $0{}{;$0+=5;$0+=10;$0*=2;$0-=15;$0-=15;$0=int($0/2);$0}1;

4

Haskell,232 231字节

当然,函数式程序员更喜欢返回一个函数而不是代表一个程序的字符串,但是这里我们开始:

t l="main=getLine>>=print."++""%words l++"(0+).read"
x%((o:_):f:n:r)|o=='m'=h"*"n r|o=='d'=h"`div`"n r|f=="from"=h"(-)"n r
x%(s:n:r)|s=="add"=h"+"n r|s!!0=='s'=h s(' ':n)r
x%(_:r)=x%r++x
_%_=""
h s n r|x<-'(':s++init n++")."=x%r++x

备注:我们总是从加零开始,否则琐碎的WordMath程序的转译将不会提供足够的信息来推断使用的类型readsubtract from n可以实现为(n-),但是我使用它((-)n)来保持一致。在subtract nsubtract从输入中复制的情况下,我不必编写它,但是我需要补偿最后丢失的空间。repeat用作默认操作;再加上空的初始上一个操作,可以轻松忽略前四个单词。

用法示例:

*Main> t "Think of a number. "
"main=getLine>>=print.(0+).read" 

其他示例给出以下结果:

"main=getLine>>=print.((-)9).(`div`5).(0+).read"
"main=getLine>>=print.(`div`2).(subtract 15).(subtract 15).(*2).(+10).(+5).(0+).read"  
"main=getLine>>=print.(subtract 1).(subtract 1).(subtract 1).(0+).read"

只是好奇,您将如何生成要返回而不是字符串的函数?
Cyoce

在函数式编程语言中,创建和组成函数并不比创建和附加字符串困难。h可能看起来像,h s n r|x<-s.read.init$n=x%r.x并使用第一个参数调用类似的函数h(+)n r(并且需要在某个flip地方获得正确的运算符顺序),基本情况是_%_=id。主要功能可以避免所有重复步骤t l=id%words l。-由于使用currying,它可能会被视为口译员,并且该想法可能会导致更轻松和/或更短的解决方案。
Christian Sievers,2016年

4

Python 2中,263个 258 260 221字节

这可能仍会短得多。

def r(s,o="",p=""):c=s.pop(0);c=[c,p]['re'in c];n=c.split()[-1];o=[[o+[['+-'['s'in c],'//']['v'in c],'*']['m'in c]+n,n+'-'+o]['f'in c],'input()']['T'in c];return s and r(s,"(%s)"%o,c)or o
lambda s:"print "+r(s.split(','))

在线尝试

我使用//而不是/,因为最后一条指令.的末尾会有一个,使任何数字成为浮点数。因此,为了保持除法一致,我使用整数除法。

测试用例输出:

print input()
print 9.-((input())//5)
print ((((((input())+5)+10)+10)-15)-15)//2.
print (((input())-1)-1)-1

如果将ifs的较大部分更改为o以下内容(我认为应该可以使用)o=[[o+[['+-'['s'in c],'//']['v'in c],'*']['m'in c]+n,n+'-'+o]['f'in c],'input()']['T'in c]
:,

@Kade是的,它仍然清晰可见。不能那样
mbomb007 '16

@Cyoce不,调用lambda的行为可能会比节省的更多。每个调用必须节省4或5个字节才能还清。
mbomb007 '16

4

Befunge,342305字节

>~$1 +:89+`#v_801p
  v_^#`+85~$<
1+>~:5+88+/3-!#v_$
v`"/":~p8p10+1<>>:"/"`!|
 "+"\5+8p4+:1+^:p11:g10<  >:"+"\2+8p:"*"\3+8p:
_$7%:01g\!#v_\2-7g\:1+:01v^p8+1\"5":p8\"5":g10
#8\"\"$#:0#<^v<p8p8\<g80p<>\#+$#12#p
-/+* >:#,_@  #^p8g10<
".@"<^"&"
10<v0<\g8-\g11:<:p1>#1+g11:p10+g
-:^>1g\-8p1-::#^_$8g^  >$$01g11g

在线尝试!

输出量

它生成的代码以&(输入值)命令开头,以.(输出值)和@(退出)命令结尾。在这两者之间,我们有各种形式的计算<number><operation>,其中运算可以是+(加),-(减),/(除),*(乘)和\-(减)。

数目本身是有点复杂,因为Befunge仅支持在0到9的范围内数字文本,所以手动计算比需要更大的东西来。由于我们已经在逐个字符地读取数字,因此我们只需在读取每个数字时就建立一个数字,例如123变为155+*2+55+*3+,即(((1 * 10) + 2) * 10) + 3

例子

Input:  Think of a number.
Output: &.@

Input:  Think of a number, divide by 5, subtract from 9.
Output: &5/9\-.@

Input:  Think of a number, add 5, add 10, multiply by 2, subtract 15, repeat, divide by 2.
Output: &5+155+*0++2*155+*5+-155+*5+-2/.@

Input:  Think of a number, subtract 1, repeat, repeat.
Output: &1-1-1-.@

说明

Befunge无法像这样操作字符串,因此大多数解析是通过对字符计数来进行的。我们首先跳过前18个字符,这使我们跳过了数字短语思考(加上逗号或句点)。然后,如果下一个字符是某种形式的换行符或EOF,我们将直接进入输出例程,否则我们将继续寻找命令列表。

要解析命令,我们只需对字符进行计数,直到到达数字或分隔符为止。如果是分隔符,则必须是重复命令,我们将其作为特殊情况处理。如果是数字,我们将其添加到输出缓冲区中,然后继续寻找更多数字。每次输出一个数字时,我们都以前缀55+*(将到目前为止的总数乘以10)并以前缀+给(将其加到总数中)。数字完成后,我们添加命令字符。

至于命令的确定方式,我们将字符数增加到以7为模的第一位数。加法为4(包括后面的空格),为2,除以 3,乘以 5 ,并将其 0 减去。由于需要\-命令组合,因此需要一些额外的处理,但是其他命令仅使用其值在表中查找适当的命令字符。

对每个命令重复此过程,将输出建立到第8行的预构建字符串中。每次添加其他命令时,我们还向字符串添加一个结束引号以确保其始终正确终止。然后,当我们最终到达输入的末尾时,我们只需“执行”此字符串以将其压入堆栈,然后按照标准输出序列将其全部写入即可。


3

JavaScript(ES6),163字节

w=>w.split`, `.map(l=>(o={a:'+',s:'-',m:'*',d:'/'}[a=l[0]])?p=(x=l.split` `.pop(),l[9]=='f'?x+`-n`:`n`+o+x+`|0`):a<'r'?'n=+prompt()':p).join`
n=`+`
console.log(n)`

试试吧:

f=w=>w.split`, `.map(l=>(o={a:'+',s:'-',m:'*',d:'/'}[a=l[0]])?p=(x=l.split` `.pop(),l[9]=='f'?x+`-n`:`n`+o+x+`|0`):a<'r'?'n=+prompt()':p).join`
n=`+`
console.log(n)`

const program = f('Think of a number, add 5, add 10, multiply by 2, subtract 15, repeat, divide by 2.')
document.write('<pre>' + program + '</pre>' )

eval(program)

/*
Outputs:

n=+prompt()
n=n+5|0
n=n+10|0
n=n*2|0
n=n-15|0
n=n-15|0
n=n/2.|0
console.log(n)
*/


3

Vim的208 171 168字节

添加了根据@ Flp.Tkc连续执行多次重复的功能,但是获得了足够的字节数,因此我仍然可以减少字节数。

:map s :s;\v
c4wcw="s, s\w* \w+ (\d+); *-1+\1);g
s, ([adms]).{-}(\d+); \1\2);g
qws(\S+), r\w+;\1 \1
@wq@ws.*;\=tr(submatch(0),'adms','+/*-')
qq])T=i(@qq@qx$xA

在线试用

无法打印的字符:

:map s :s;\v
c4wcw^V^R=^V^R"^[s, s\w* \w+ (\d+); *-1+\1);g
s, ([adms]).{-}(\d+); \1\2);g
qws(\S+), r\w+;\1 \1
@wq@ws.*;\=tr(submatch(0),'adms','+/*-')
qq])T=i(^[@qq@qx$xA
^V^[^[

测试用例输出:

  1. cw^R=^R" ^[ 在线试用
  2. cw^R=((^R" /5) *-1+9) ^[ 在线试用
  3. cw^R=((((((^R" +5) +10) *2) -15) -15) /2) ^[ 在线试用

这似乎不适用于多个连续重复。
FlipTack

@ Flp.Tkc已修复,谢谢!我之前没有注意到。
nmjcman101 '16

2

lex,246个字节

%{
#define P printf
#define O P("n%s%d;",c,v);
int v;char*c;
%}
%%
T {P("%%%%\n.* {int n=atoi(yytext);");}
ad {c="+=";}
fr {c="=-n+";}
s {c="-=";}
v {c="/=";}
l {c="*=";}
re {O}
[0-9]+ {v=atoi(yytext);O}
\. P("printf(\"%%d\",n);}\n%%%%");
. ;
%%

lex的目标是C,因此C编译器需要将其编译为可执行文件。词法分析器库(ll)也需要链接。这可能会增加字节惩罚性,但是我不确定是否有多少字节。

该程序将输出一个lex程序(按规范),该程序可评估转译的词法表达式。%{和之间的代码%}仅用于“编译器”:

#define P printf              /* for brevity */
#define O P("n%s%d;",c,v)     /* expression builder, calls P = printf */
int v;char*c;                 /* v=most recent integer read */
                              /* c=the expression infix */

在两%%行之间是正则表达式/操作部分。第一个要匹配的规则是T(“ Think ...”),它会构建前同步码(lex程序必须至少开始包含规则部分,并且yytext最后是匹配的文本,因此该规则实质上是用用户的输入来植入累加器)。

程序丢弃所有输入除外被匹配,并且其他规则(adfr,最多re)与作为最小的匹配尽可能是唯一的处理wordmath表达条款。在大多数情况下,它将设置c为表达式中缀,将其连接起来,n并在O被调用时读取最后一个整数(例如,读取“ add 9”会将中缀设置为+=,将v设置为9,将对的调用O输出n+=9;) 。(有趣的旁白是“从8中减去”会造成双方sfr规则得到匹配,但由于O只在号码被呼叫,适当的规则n=-n+8;是获取输出的唯一表达)。的re“重复”规则只是调用O再次,它输出最后一个创建的表达式(并且由于后续的匹配将yytext变得很混乱,因此支持“重复”是[0-9]+规则中要求整数转换的原因)。最后,一个句点导致程序预告片输出,该预告片仅输出累加器并以%%表示输出lex程序结尾的对关闭。

注意: 主编译器程序或输出程序都不会终止。输入管道将起作用,或提供EOF(ctrl-D)。如果在第一个输入之后需要终止,则可以添加exit()。

要构建/运行:

Build the main program:
% lex -o wordmath.yy.c wordmath.l
% cc -o wordmath wordmath.yy.c -ll

Execute to create a specific transpiled program:
% echo "This is a number, add 8, subtract 5, repeat." | ./wordmath > program.l

Build the transpiled program:
% lex -o program.yy.c program.l
% cc -o program program.yy.c -ll

Execute the transpiled program (with input 3, called via a pipe or inline):
% echo 3 | ./program
1
% ./program
3
1
^D
%

测试1:

%%
.* {int n=atoi(yytext);printf("%d",n);}
%%

测试2:

%%
.* {int n=atoi(yytext);n/=5;n=-n+9;printf("%d",n);}
%%

测试3:

%%
.* {int n=atoi(yytext);n+=5;n+=10;n*=2;n-=15;n-=15;n/=2;printf("%d",n);}
%%

测试4:

%%
.* {int n=atoi(yytext);n-=1;n-=1;n-=1;printf("%d",n);}
%%

2

Pyth,69 67字节

J\QVtcQ\,Iq@N1\r=NZ)=Jjd+@"+-/*"x"asdm"@N1.>,J-ecN)\.qh@cN)1\f=ZN)J

接受a "quoted string"并打印结果的程序。

测试套件

怎么运行的

Pyth具有前缀运算符,因此使用进行基本的算术运算(operator)(operand1)(operand2),而预初始化的变量Q给出输入。因此,通过从字符串开始'Q',在每个阶段,在运算符之前添加,然后根据需要在操作数之前或之后,构造一个已编译的WordMath程序。

J\QJ已编译的程序字符串设置为字符串'Q'

tcQ\, 在逗号上分割输入,并丢弃第一个元素(即' Think of a number'

V 为此N

  • Iq@N1\r 如果at的字符N[1]'r'(重复):
    • =NZ设置NZ(的先前值N,在for循环的末尾设置)
  • x"asdm"@N1 找到N[1]in 的索引"asdm"(加,减,除,乘)
  • @"+-/*" 索引到中"+-/*",给出所需的运算符
  • ,J-eCN)\.产生两个元素的列表[J, -eCN)\.],其中第二个元素是N空格分隔符的最后一个元素,其中包含'.'删除字符(操作数)
  • qh@cN)1\f 如果N在空格上拆分的第二个元素的第一个字符是'f'(减去):
    • .> 交换两元素列表中的元素
  • + 将运算符和两元素列表合并为一个列表
  • =JjdJ为在空格上连接的那个
  • =ZN 设置ZN

J 打印 J


很好的回答者。。。启发我尝试使用05AB1E,这比预期的要令人胆怯。
魔术八达通n

2

,58字节

太糟糕了,我还没有实现那个反向减法运算符。

{p:a:sNa?ap['Y("-y+  y- y// y+ y* "^sa@?Y`\d`)|'qa@y]}Mq^k

该程序从stdin提取WordMath脚本,并将Pip代码输出到stdout。类似地,输出的代码从stdin中获取一个数字,并将结果输出到stdout。在线尝试!

战略

对于这样的输入:

Think of a number, multiply by 3, add 1.

我们想要这样的输出:

YqYy*3Yy+1

其工作原理如下:

Yq    Yank a line of stdin into y
Yy*3  Compute y*3 and yank result into y
Yy+1  Compute y+1 and yank result into y
      Last expression is autoprinted

脱节+说明

{
 p : a : sNa ? a p
 [
  'Y
  ("-y+  y- y// y+ y* "^s a@?Y`\d`) | 'q
  a@y
 ]
} M q^k

该程序的基本结构是{...}Mq^k,它qk(逗号空间)上分割(一行stdin),并M为每个元素分配一个函数。

在函数内部,我们从处理repeat案例开始。Pip中最短的测试似乎是sNa(命令中是否有空格)。如果是这样,我们要使用a; 如果不是,请使用p,它存储上一个命令。将该值分配回a以及p((下一次)。

对于返回值,我们使用列表,这很好,因为列表的默认输出格式是将所有内容连接在一起。结果总是以Y。接下来,我们需要一个查询表进行操作。

观察到add (4),subtract (9),divide by (10),multiply by (12)和subtract from (14)的长度都是不同的。进一步观察,当使用mod 7时它们仍然是不同的。因此,我们可以使用它们索引到一个包含七个元素的列表(包含五个代码段和两个占位符),以将每个WordMath命令映射到适当的Pip代码(设计为数字可以简单地连接到末尾):

  • 0: ()-y+subtract from
  • 1:占位符
  • 2: ()y-subtract
  • 3: ()y//divide by
  • 4: ()y+add
  • 5: ()y*multiply by
  • 6:占位符

对于索引,我们使用regex来获取命令中第一个数字的索引:a@?`\d`。我们还将正则表达式插入其中,y以备将来使用。查找表被拆分该串产生"-y+ y- y// y+ y* "s(空格)。

我们仍然必须处理第一个条目,它应该转换为代码Yq。由于Think of a number不包含任何数字,因此@?运算符返回nil。使用nil作为查找表的索引也会返回nil。Nil是虚假的,因此在这种情况下,我们需要做的就是添加|'q使用q而不是操作。

返回列表的最后一个元素是数字本身。我们通过以下方式获得此信息a@y(在我们之前提取的digit regex命令中找到所有匹配项)。这将返回一个数字列表,但同样,这不是问题,因为所有列表在输出时都将串联在一起。对于第一个条目,不a@y匹配任何数字并给出空列表,该列表不会在输出中添加任何内容。

例如

带输入

Think of a number, subtract from 20, add 2, repeat.

地图表达式给出了列表

[["Y";"q";[]]; ["Y";"-y+";[2;0]]; ["Y";"y+";[2]]; ["Y";"y+";[2]]]

串联后输出

YqY-y+20Yy+2Yy+2

2

Python 2中154个 153 146字节

固定,甚至在过程中节省了几个字节。^ __ ^

for c in input()[9:-1].split(","):s=c.rfind(" ");p=o=s and"x="+"-x+ input() x- x// x+ x*".split()[s%7]+c[s:]*(c[0]<"a")or p;print o
print"print x"

在线尝试!

基于与我的点子答案相同的策略。特定于Python的功能:

  • Think of 和结束.符在分割(input()[9:-1])之前已从字符串中删除。这个时期太麻烦了,无法在主循环中处理。删除前九个字符有不同的原因(请参阅下文)。
  • 我们不是通过正则表达式搜索数字来获得每个命令的长度(在Python中因为昂贵,因为import re),而是rfind(" ")用来查找命令中的最后一个空格。我们也可以使用它来检查repeat情况。
  • Python没有Pip的循环索引,因此我们必须显式采用索引mod 7。另一方面,这意味着我们可以删除查找表中的最后一个哑数值,因为索引mod 7永远不会为6。
  • 第一次执行的“命令”为a number,其中空格的索引为1。该索引可以方便地填充查找表中的另一个孔。在主循环中处理输入级的另一个问题是+c[s:],这将导致x=input() number。为了解决该问题,我们将字符串乘以c[0]<"a"1对所有常规命令以:,其中所有命令c以空格开头,但0以initial 开头a number

1

WinDbg,449388字节

as, }@$t1
as. }0;?@$t0
asThink n10;ed8<<22;r$t0=dwo(8<<22);r$t1=0;.do{
aSa " "
asQ .printf";r$t1=1;.do{r$t1=@$t1-1;r$t0=@$t0
as/c add Q +"
aSby " "
as/c divide Q /"
asfrom 0;r$t0=-@$t0+
as/c multiply Q *"
aSnumber " "
aSof " "
asrepeat +1
as/c subtract Q -"
.for(r$t9=1;by(@$t0);r$t0=@$t0+1){j44!=by(@$t0) .printf"%c",by(@$t0);.if116!=by(@$t0-1){.printf" , "}};.printf"\b ."

通过定义重复代码的别名来生成-61字节

LambdaBeta使用的启发#define。这种方法会稍微修改WordMath语法(,并且.必须像其他单词一样用空格分隔,并且,不遵循repeat),并创建别名,使修改后的WordMath语法是有效的WinDbg代码。最后一行通过将输入转换为修改后的语法来执行问题并进行翻译。

通过在存储器地址处设置字符串并将伪寄存器$t0设置为该地址来进行输入。注意:这将覆盖intat 0x2000000,因此,如果您在此处开始字符串,它将被部分覆盖。$t0也将被覆盖。

因为它创建别名,所以取决于此代码是在设置字符串之前还是之后运行的,因此输出代码将有所不同(是否为别名)。不幸的是,我没有找到一种方法来在没有用空格分隔的情况下使别名正确扩展(这意味着WordMath脚本不能不先转换就直接执行)。

怎么运行的:

* $t1 is used for repeating and $t0 is used to read the input and hold the accumulator
* Alias , to }@$t1 -- closing do-while loop and allowing repeat
as , }@$t1

* Alias . to }0;?@$t0 -- close do-while loop and evaluate $t0 (accumulator)
as . }0;?@$t0

* Alias Think to (note this is one line)
as Think n10;               * Set base 10
         ed 8<<22;          * Read ints to address 0x2000000. Enter nothing to exit input mode
         r$t0 = dwo(8<<22); * Set $t0 = first int
         r$t1=0;.do{        * Open do-while

* Alias a to nothing
aS a " "

* Alias add to (note one line):
as add ;                       * Close previous statement
       r$t1=1;.do{r$t1=@$t1-1; * Open do-while (once) loop
       r$t0=@$t0+              * Add number to $t0

* Alias by to nothing
aS by " "

* Alias divide to (note one line):
as divide ;                       * Close previous statement
          r$t1=1;.do{r$t1=@$t1-1; * Open do-while (once) loop
          r$t0=@$t0/              * Divide next number from $t0

* Alias from to (note one line):
as from 0;         * Preceding subtract statement subtracts 0
       r$t0=-@$t0+ * Subtract $t0 from next number

* Alias multiply to (note one line):
as multiply ;                       * Close previous statement
            r$t1=1;.do{r$t1=@$t1-1; * Open do-while (once) loop
            r$t0=@$t0*              * Multiply next number with $t0

* Alias number to nothing
aS number " "

* Alias of to nothing
aS of " "

* Alias repeat to +1 making do-while (once) loops into do-while (once)+1
as repeat +1

* Alias subtract to (note one line):
as subtract ;                       * Close previous statement
            r$t1=1;.do{r$t1=@$t1-1; * Open do-while (once) loop
            r$t0=@$t0-              * Subtract next number from $t0


.for (r$t9=1; by(@$t0); r$t0=@$t0+1) * Enumerate the string
{
    j 44!=by(@$t0)                   * If not comma
        .printf "%c",by(@$t0);       * Print the char
    * implicit else
        .if 116!=by(@$t0-1)          * Else if the previous char is not t
        {
          .printf " , "              * Print the comma with spaces around it
        }
};
.printf "\b ."                       * Replacing ending "." with " ."

输出示例,在运行此代码一次之前输入字符串(结果程序类似于WordMath):

0:000> r$t0=8<<22
0:000> eza8<<22"Think of a number, add 5, add 10, multiply by 2, subtract 15, repeat, divide by 2."
0:000> as, }@$t1
0:000> as. }0;?@$t0
0:000> asThink n10;ed8<<22;r$t0=dwo(8<<22);r$t1=0;.do{
0:000> aSa " "
0:000> asadd ;r$t1=1;.do{r$t1=@$t1-1;r$t0=@$t0+
0:000> aSby " "
0:000> asdivide ;r$t1=1;.do{r$t1=@$t1-1;r$t0=@$t0/
0:000> asfrom 0;r$t0=-@$t0+
0:000> asmultiply ;r$t1=1;.do{r$t1=@$t1-1;r$t0=@$t0*
0:000> aSnumber " "
0:000> aSof " "
0:000> asrepeat +1
0:000> assubtract ;r$t1=1;.do{r$t1=@$t1-1;r$t0=@$t0-
0:000> .for(r$t9=1;by(@$t0);r$t0=@$t0+1){j44!=by(@$t0) .printf"%c",by(@$t0);.if116!=by(@$t0-1){.printf" , "}};.printf"\b ."
Think of a number ,  add 5 ,  add 10 ,  multiply by 2 ,  subtract 15 ,  repeat divide by 2 }0;?@$t0

0:000> Think of a number ,  add 5 ,  add 10 ,  multiply by 2 ,  subtract 15 ,  repeat divide by 2 }0;?@$t0
base is 10
02000000 6e696854 18
18
02000004 666f206b 

Evaluate expression: 18 = 00000012

示例输出,在此代码运行一次之后输入字符串(输入字符串时别名会扩展,因此生成的程序不太漂亮):

0:000> r$t0=8<<22
0:000> eza8<<22"Think of a number, add 5, add 10, multiply by 2, subtract 15, repeat, divide by 2."
0:000> as, }@$t1
0:000> as. }0;?@$t0
0:000> asThink n10;ed8<<22;r$t0=dwo(8<<22);r$t1=0;.do{
0:000> aSa " "
0:000> asadd ;r$t1=1;.do{r$t1=@$t1-1;r$t0=@$t0+
0:000> aSby " "
0:000> asdivide ;r$t1=1;.do{r$t1=@$t1-1;r$t0=@$t0/
0:000> asfrom 0;r$t0=-@$t0+
0:000> asmultiply ;r$t1=1;.do{r$t1=@$t1-1;r$t0=@$t0*
0:000> aSnumber " "
0:000> aSof " "
0:000> asrepeat +1
0:000> assubtract ;r$t1=1;.do{r$t1=@$t1-1;r$t0=@$t0-
0:000> .for(r$t9=1;by(@$t0);r$t0=@$t0+1){j44!=by(@$t0) .printf"%c",by(@$t0);.if116!=by(@$t0-1){.printf" , "}};.printf"\b ."
n10;ed8<<22;r$t0=dwo(8<<22);r$t1=0;.do{     number ,  ;r$t1=1;.do{r$t1=@$t1-1;r$t0=@$t0+ 5 ,  ;r$t1=1;.do{r$t1=@$t1-1;r$t0=@$t0+ 10 ,  ;r$t1=1;.do{r$t1=@$t1-1;r$t0=@$t0*   2 ,  ;r$t1=1;.do{r$t1=@$t1-1;r$t0=@$t0- 15 ,  repeat ;r$t1=1;.do{r$t1=@$t1-1;r$t0=@$t0/   2 }0;?@$t0

0:000> n10;ed8<<22;r$t0=dwo(8<<22);r$t1=0;.do{     number ,  ;r$t1=1;.do{r$t1=@$t1-1;r$t0=@$t0+ 5 ,  ;r$t1=1;.do{r$t1=@$t1-1;r$t0=@$t0+ 10 ,  ;r$t1=1;.do{r$t1=@$t1-1;r$t0=@$t0*   2 ,  ;r$t1=1;.do{r$t1=@$t1-1;r$t0=@$t0- 15 ,  repeat ;r$t1=1;.do{r$t1=@$t1-1;r$t0=@$t0/   2 }0;?@$t0
base is 10
02000000 3b30316e 26
26
02000004 3c386465 

Evaluate expression: 26 = 0000001a

仅使用稍微修改的WordMath语法,即可获得更多示例输出:

0:000> Think of a number , add 1 , repeat repeat repeat divide by 3 .
base is 10
02000000 0000001a 3
3
02000004 3c386465 

Evaluate expression: 2 = 00000002


0:000> Think of a number , divide by 5 , subtract from 9 .
base is 10
02000000 00000003 29
29
02000004 3c386465 

Evaluate expression: 4 = 00000004

0

Scala,338个字节

在ideone上尝试一下

s=>{val n=(_:String)filter(_.isDigit)toInt;(Seq("").tail/:s.split(",").tail)((a,&)=> &match{case&if&contains "v"=>a:+"x/="+n(&)
case&if&contains "d"=>a:+"x+="+n(&)
case&if&contains "y"=>a:+"x*="+n(&)
case&if&contains "f"=>a:+"x="+n(&)+"-x"
case&if&contains "s"=>a:+"x-="+n(&)
case p=>a:+a.last})mkString("var x=readInt;",";",";print(x)")}

说明:

// define a function with a parameter s
s => {
    // define a function with a String parameter to extract a number from a string
    val n =
        // filter out the chars that arent't digits
        (_: String) filter (_.isDigit)
        // and parse the number
        toInt;
    // take the tail of a list with an empty string,
    // which is the empty list of type Seq[String].
    // This is the start value for the fold...
    (Seq("").tail /:
        // ... of the tail of the sentence splitted at commas
        s.split(",").tail
    ) (
        // This is the function for the fold.
        // a is the accumulator (the list), and the current element is called &
        (a, &) => & match {
            // if & contains a "v", append "x/=" + n(&) to a.
            case & if & contains "v" => a :+ "x/=" + n(&)
            // the other cases are similar
            case & if & contains "d" => a :+ "x+=" + n(&)
            case & if & contains "y" => a :+ "x*=" + n(&)
            case & if & contains "f" => a :+ "x=" + n(&) + "-x"
            case & if & contains "s" => a :+ "x-=" + n(&)
            // for the repeat, apppend the last value of a to a
            case p                   => a :+ a.last
        }
     )
     // make a string out of the parts by joining them with semicolons,
     // prepending "var x=readInt;" and appending ";print(x)"
     mkString("var x=readInt;", ";", ";print(x)")
}
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.