前缀表示法到后缀表示法


19

免责声明:不,这不是反向字符串的笑话。

任务

仅支持一种操作:减法(-)。

您还只有两个原子要支持:零(0)和一个(1)。

在这里,前缀符号-AB等效于后缀符号AB-,其中AB是表达式。

您的任务是(递归)将前缀表示形式的表达式转换为后缀表示形式中的等效表达式。

定义

以下语法生成前缀表示形式的表达式:

S > -SS
S > 0
S > 1

以下语法生成后缀表示形式的表达式:

S > SS-
S > 0
S > 1

Prefix notation:  --01-0-01
Parentheses:      -(-01)(-0(-01))
Convert:          (01-)(0(01-)-)-
Postfix notation: 01-001---

规则与自由

  • 您可以将操作和原子重命名为任何字符,只要它是一致的即可。
  • 输入格式必须与输出格式一致(除了输入为前缀表示法而输出为后缀表示法之外)。

测试用例

Input       Output
1           1
0           0
-01         01-
-10         10-
--01-0-01   01-001---

测试用例归功于Dada


1
您能否再添加一些测试用例?
毛茸茸的

@Shaggy您想要什么样的测试用例?
Leaky Nun

@LeakyNun像我在最新版本的答案中所做的那样,将输入和输出作为迭代器可以吗?
L3viathan '17

@ L3viathan我想是这样的
Leaky Nun

Answers:


12

操蛋,32字节

,[[->++++<<+>]>[[-]<<[.[-]<]]>,]

在线尝试!

我将其@用作操作,因为它的代码点(64)很方便。 U使用3 * 85 + 1 = 256 = 0,也可以使用相同的字节数。

说明

磁带用作堆栈。在主循环的每次迭代中,数据指针从堆栈顶部的右边开始两个单元。

,[                Take input and start main loop
  [->++++<<+>]    Push input, and compute 4*input
  >[              If 4*input is nonzero (and thus input is not @):
    [-]<<           Zero out this cell and move to top of stack
    [.[-]<]         Pop from stack and output until \0 is reached
  ]
  >,              Move pointer into the correct position.  If input was @, the earlier > pushed \0 onto the stack.
]

6

视网膜37 30 29字节

M!`-*.
+m`^-(.*)¶(\d.*)
$1$2-

在线尝试!通过意识到术语始终以数字开头节省了7个字节,因此我不必再将匹配限制为最后-一个(以前,它是唯一保证后面跟有两个术语的匹配项)。不将-s放在自己的行上,节省了1个字节。例如,-01变成-0¶1,然后被替换01-。现在,如果我有--010--0¶1¶0后来我想内改变-0¶1,以01-让我可以代替-01-¶0使用01-0-,但实际上它并不无论哪两个-的I删除,所以我删除了一个在该行的开头,如这更容易测试。


我认为是您的事情:)
Leo

@Leo通常不起作用,例如-0-0-00应该变成0000---
尼尔

您说得对,对不起。我有另一个想法,但是有很大的不同,所以我将其发布为新答案
Leo

1
@Leo我现在找到了我的东西……
Neil

1
@Leo我最近的高尔夫球赛被绑!
尼尔

6

Haskell62 59字节

f(x:r)|x>'-'=([x],r)|(a,(b,c))<-f<$>f r=(a++b++"-",c)
fst.f

在线尝试!用法:fst.f $ "--01-0-01"0并且1可以是大于的任意字符-

编辑: -3字节感谢Zgarb!

该函数f以简单的语法递归地解析一个表达式,并以后缀表示法和其余字符串返回该表达式的元组,该语法可以从中构建有效的前缀表达式:

<exp> ::= - <exp> <exp> | 0 | 1

如果a输入字符串的第一个字符大于-,则我们在一个原子表达式上,并返回一个字符串,其中包含charactera和其余的输入字符串。

如果找到-,则需要解析两个表达式。这可以通过(a,x)<-f r获取第一个表达式a,然后x再次解析其余字符串(b,c)<-f x以获取第二个表达式b和最终的其余字符串来实现c(a,(b,c))<-f<$>f r这样做是因为<$>在元组上将函数映射为元组的第二个元素两个,而比元组短三个字节(a,x)<-f r,(b,c)<-f x。在获得两个表达式和其余字符串之后,将这些表达式连接起来,并附加一个“-” :(a++b++"-",c)


1
您可以通过合并f(x:r)|x>'-'=([x],r)|(a,(b,c))<-f<$>f r=(a++b++"-",c)
大小写

@Zgarb谢谢!出于某种原因,我仅f(x:r)|x<'0',(a,(b,c))<-f<$>f r=(a++b++"-",c)|1<3=([x],r)在寻找兼有两种情况的版本时才考虑,该版本更长。
Laikoni '17

5

Haskell,54个字节

v f""=""
v f(a:s)=last(v.v:[id|a>'-'])((a:).f)s
h=v h

该函数v接受一个字符串和一个函数,重新排列初始子表达式,然后将函数应用于字符串的其余部分,直到所有内容都重新排列为止。调用堆栈和函数参数一起跟踪正在解析的表达式。该函数h回答了挑战,并且只是v作为一个虚拟的第一个参数而被调用。


1
哇!(1)只有53,您不需要计算最后的换行符。(2)v f l=l如果将第二行移至第一行,则可以缩短为第一行。
与Orjan约翰森

1
我认为您不需要解析多个完整的表达式,因此可以使用匿名函数节省一个字节v id
与Orjan约翰森

1
实际上,第一行永远不会在有效输入上被调用,因此您可以删除它。
与Orjan约翰森

1
拆分为后卫似乎可以将last技巧克服一个字节。
与Orjan约翰森

4

Perl 5、57字节

sub f{"@_"=~s/x((?0)|.)((?0)|.)/my$n=$2;f($1).f($n).x/re}

我将其x用作运算符,而不是-(请参见下面的TryItOnline链接)。

在线尝试!

说明:
/x((?0)|.)((?0)|.)/递归匹配一个完整的表达式:x在开始(?0)时是a ,然后是一个表达式(这是一个递归调用)或一个atom(.),然后是另一个expression-or-atom。
然后,我需要保存第二个expression / atom(my$n=$2;),因为否则递归调用将覆盖它。
然后在第一个表达式(f($1))上递归调用该函数,然后在第二个表达式上递归调用f($n),并将x追加到末尾(.x)。


4

Python 3,117 112 105 100 98 76 62 61 59字节

def p(s):x=next(s);yield from[x]*(x>"-")or[*p(s),*p(s),"-"]

变更日志:

  • 尽可能删除了换行符(-5个字节)
  • lambda而不是完整功能(-7个字节,感谢@Dada)
  • 其他(-5个字节,感谢@Leaky Nun)
  • 撤消狂热的高尔夫运动(-2个字节,感谢@Leaky Nun)
  • 而是在全局列表上工作(-22字节)
  • 实际上,让我们改为使用迭代器(-14字节)
  • 更改!=>(-1字节,从@ovs的建议复制)
  • 懒惰的评估技巧(-2个字节,感谢@ovs)

像这样使用它:

>>> list(p(iter("--01-0-01")))
['0', '1', '-', '0', '0', '1', '-', '-', '-']


2
lambda x:p(x)[0]可能会取代您的f功能。
达达

1
方法,你不需要else
Leaky Nun

1
是否有d="-"真正节省字节?
Leaky Nun

1
def p(s):x=next(s);yield from[x]*(x>"-")or[*p(s),*p(s),"-"]59字节
ovs,

3

Pyth,20个字节

L+&-hbTsyM.-Btbytbhb

这创建了一个功能 y将字符串作为参数的函数。

在线尝试:演示测试套件

说明:

该函数y将解析第一个前缀表达式并将其转换为后缀表达式。因此,如果像y"10"这样调用它,它将仅返回1

L+&-hbTsyM.-Btbytbhb
L                      define a function y(b), that returns:
   -hbT                   remove the chars "10" from the first char b
                          (T=10, and - will convert a number to a string)
  &                       if this gives the empty string (a falsy value)
 +                hb         then append b[0] to it and return it
                             (so this will parse a digit 0 or 1 from the string)
  &                       otherwise (the first char is a -)
               ytb           parse the first prefix expression from b[1:]
                             (recursive call)
          .-Btb              remove this parsed expression bifurcated from b[1:]
                             this gives a tuple [b[1:], b[1:] without first expr]
        yM                   parse and convert an expression from each one
       s                     join the results
 +                hb         and append the b[0] (the minus) to it and return

2

视网膜34 31 29字节


;
-;
¶
+`¶(.+);(.+)
$1$2-
;

在线尝试!

;用于表示节点,这些节点最初由单个数字组成,然后增长到已经解析的任何内容。-被换成新换行符,这样.+我们就可以抓住一切不可解析的东西-


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.