前奏语法检查器


10

Prelude是一种深奥的编程语言,对构成有效程序的内容几乎没有限制,但有不同寻常的限制。只要满足以下条件,任何可打印的ASCII文本块(“块”表示可打印的ASCII行用换行符-0x0A分隔)都是有效的:

  • 文本的每个(垂直)列最多包含(和之一)
  • 忽略它们的垂直位置,the (和and )是平衡的,也就是说,每个(和恰好)在其右侧配对,反之亦然。

编写一个程序或函数,给定包含可打印ASCII和换行符的字符串,确定该程序或函数是否构成有效的Prelude程序。您可以通过STDIN(或最接近的替代品),命令行参数或函数参数进行输入。可以使用您选择的任何两个固定的 真假值将结果返回或打印到STDOUT 。

不得假定输入为矩形。

这是代码高尔夫球,因此最短的提交(以字节为单位)获胜。

例子

以下是有效的 Prelude程序(实际上,它们甚至是真正的 Prelude程序):

?1-(v  #1)-             
1   0v ^(#    0)(1+0)#)!
    (#)  ^#1-(0 #       
1(#  1) v #  - 1+)
    vv (##^v^+
? v-(0 # ^   #)
?
  1+              1-!

这是一些输入,所有输入都是无效的

#(#(##)##)##(
)##(##(##)#)#
#(#)
)###
#(##
(##)
(##)
(#)#
(##)
(###
#(#)
(##)
#(#)
###)
#()#
()##
#(#)##
###
###(#)

Prelude的评论是否有可能挡住亲戚?
Alex A.

@Alex否。以上规则实际上是决定程序是否有效的全部方法。
马丁·恩德

太好了,谢谢您的澄清。只是想确定一下。
Alex A.

规则1-“每一列文字最多包含(和)之一”;示例1,第2行:“ 1 0v ^(#0)(1 + 0)#)!” ->我看到3 )和2 (。每行只有1个吗?
伊斯梅尔·米格尔

1
@IsmaelMiguel 通常将“列”理解为是指垂直线(尤其是在网格的情况下)。无论如何,我已经澄清了。
Martin Ender'3

Answers:


3

CJam,57 56字节

qN/z_{_"()"--W<},,\s:Q,{)Q/({_')/,\'(/,-}:T~\sT0e>+z+}/!

太长,可以打很多球。打高尔夫球后要添加的说明。

简要说明

代码中有两项检查:

  • 第一个过滤器检查每列是否最多包含1个括号。过滤器的最终输出是带有超过1个括号的列数。
  • 其次,我们将输入转换为列主格式,然后在每个索引上将其分为两部分。
    • 在这两部分中,(Number of "(" - Number of ")")应该互相称赞。因此,当您将它们加起来时,其结果应为0。任何未通过此属性的部分将使整个输入具有不匹配的括号。
    • 我还必须确保“(”位于“)”的左侧。这意味着Number of "(" - Number of ")"右侧块的值不能为负。

在这里在线尝试


6

Python 2中,128个 119 105字节

def F(p):
 v=n=1
 for r in map(None,*p.split("\n")):A,B=map(r.count,"()");n+=B-A;v*=n<2>A+B
 return n*v>0

您是否知道可以在Python 2中映射无

说明

我们想从转置前奏开始,使列成为行。通常,我们会使用来执行此操作zip,但是由于zip截断到最短的itertools.zip_longest行长并且对于代码高尔夫来说太长了,所以似乎没有捷径可做。

除了映射None

>>> print map(None,*[[1,2,3],[4],[5,6]])
[(1, 4, 5), (2, None, 6), (3, None, None)]

不幸的是(幸运的是,对于所有非高尔夫目的),这仅在Python 2中有效。

至于nv

  • n就像一个堆栈,计数1 - <number of unmatched '(' remaining>。对于(我们看到的每一个,我们减去1,对于我们看到的每一个,我们减去)1。因此,如果n >= 2在任何时候,我们都看到了太多)s,并且该程序无效。如果n没有在1上完成,那么我们至少还有一个无与伦比的(剩余空间。
  • v检查有效性,并从1开始。如果程序曾经是无效的(n >= 2A+B >= 2),则v变为0表示无效。

因此,如果程序有效,那么到最后我们必须有n = 1, v = 1。如果程序无效,那么最后必须有v = 0v = 1, n <= 0。因此有效性可以简洁地表示为n*v>0

(感谢@feersum提供了许多好的建议,这些建议占用了14个字节!)

以前的,更具可读性的提交:

def F(p):
 p=map(None,*p.split("\n"));v=n=0
 for r in p:R=r.count;A=R("(");B=R(")");n+=A-B;v|=A+B>1or n<0
 return n<1>v

这是对map... 的疯狂使用
xnor 2015年

1
119-> 106def F(p): v=n=3 for r in map(None,*p.split("\n")):A,B=map(R.count,"()");n+=A-B;v*=n>2>A+B return n*v==9
feersum 2015年

@feersum谢谢!我一直在尝试将更or改为比较链接,但没有想到更改|=*=。但是,通过使内容更加倒退来
占用

2

J,64个字节

输入是带有尾随换行符的字符串。输出为0或1。

(0=(1<|s)s+[:(|@{:+(0>])s)[:+/\]s=.+/@:)@(1 _1 0{~[:'()'&i.];.2)

用法示例

   ]in=.'#(#)##',LF,'###',LF,'###(#)',LF
#(#)##
###
###(#)

   ((0=(1<|s)s+[:(|@{:+(0>])s)[:+/\]s=.+/@:)@(1 _1 0{~[:'()'&i.];.2)) in
0

方法如下

  • 在换行符处剪切输入并放入矩阵 ];.2
  • 映射(/ )/ anything else进入1/ -1/0 1 _1 0{~[:'()'&i.]
  • 定义s=.+/@:添加到动词的副词将动词数组输出求和
  • 在列中添加值 ]s

    • 检查()每个前缀中的正余额 [:(0>])s)[:+/\]
    • 检查()整个列表中的余额是否相等(即最后一个前缀) |@{:@]
  • 在列中添加abs(values)并检查每个元素的最大值是否为1 (1<|s)s

  • 由于所有先前的检查都在失败时产生正数,因此我们将它们加起来并与0比较以得到输入的有效性 0=]


2

J,56个字节

3 :'*/0<: ::0:(+/\*:b),-.|b=.+/+.^:_1]0|:''()''=/];.2 y'

这是一个匿名函数,接受带尾随换行符的字符串并返回0或1。从右向左读取:

  • ];.2 y与其他J提交中一样,y在所有出现的最后一个字符时都剪切字符串(这就是输入需要末尾换行符的原因),并制作一个矩形矩阵,其行是片段,必要时用空格填充。

  • '()'=/首先与该矩阵中的每个字符进行比较(,然后)返回两个0-1矩阵的列表。

  • +.^:_1]0|:将两个矩阵的列表转换为一个复数矩阵。到目前为止,该程序将(输入中的)每个字符都变为1,将每个字符都变为i,其他所有字符都变为0。

  • b=.+/将该复杂矩阵的行之和分配给b

  • -.|b列出1- | z | 在每ž b。每列最多包含一个括号的条件会转换为所有这些数字1- | z |。非负的

  • +/\*:b是中的数字平方和的和的向量b。如果每一列最多包含一个括号,则其中的数字的平方b均为0、1或-1。该,连接此载体与1-矢量| Z |的。

  • 现在我们要做的就是测试连接向量的项v是否为非负实数,这几乎是*/0<:v,除了如果的某些项v不是实数会导致错误,因此我们将其替换<:<: ::0:在错误情况下仅返回0 。


复杂数字的好主意,但您也需要检查是否0={:+/\*:b因为例如(无效。
randomra 2015年

哦,你是对的,@ randomra,我忘了!
奥马尔2015年

1
0=(-|)v用于检查非负实数的长度要短2个字节。(让我们击败CJam!:P)
Randomra 2015年

1
哦,而inv不是^:_1 保存另一个字节。
randomra 2015年

1
返回56(与平衡检查): 3 :'*/0=({:,]-|)(-.@|,+/\@:*:)+/+.inv]0|:''()''=/];.2 y'
randomra 2015年
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.