解析二维语法


25

背景

爱丽丝(Alice)和鲍勃(Bob)正在创造一种高尔夫语言,以赢得每一个PPCG挑战。爱丽丝想制作一种二维语言(如> <>),但鲍勃(Bob)更喜欢像J中那样的前缀-前缀语法。作为一种折衷,他们决定创建一种二维前缀-前缀语言。解析器很难编写,他们需要您的帮助!

语法规范

在Alice和Bob的语言中,有变量(由小写ASCII字母表示a-z)和函数(由大写ASCII字母表示)A-Z。可以使用一个或两个参数来调用一个函数。一个方案是字母矩形网格a-zA-Z和空间,以及左上角不能包含空格。这是一个有效程序的示例:

F Gy
H   
R x 

解析程序后,它将转换为C风格语言(C,Java,Python ...)的表达式,其中包含单字母变量和函数调用,格式为<func>(<arg>)<func>(<arg1>,<arg2>)。例如,上面的程序产生以下表达式:

F(H(R(x)),G(x,y))

解析过程的详细信息如下:

  • 这些空格只是填充符,因此不会被解析。
  • 每个变量a-z始终被解析为自身。
  • 每个函数都A-Z被解析为一个函数调用。它的参数是它下面和右边在网格中最接近的表达式(按此顺序)。如果仅存在其中之一,则将其作为唯一参数。您可以假设所有函数在网格中至少有一个参数。

在上面的示例中,变量xy被解析为自身。该函数在其R下方和x右侧没有任何内容,因此将其解析为单参数调用R(x)。同样,由于位于下方,因此H被解析为。该功能具有以下,并在其右侧,所以它解析为,和类似的。左上角解析的表达式是解析过程的结果。H(R(x))RGxyG(x,y)F

输入输出

您的输入是一个非空的矩形字符数组。它始终是Alice和Bob语言的有效程序,但是它可能包含未在输出中使用的表达式。您的输出应为上述过程产生的解析表达式。

规则和计分

您可以编写功能的完整程序。最低字节数获胜,并且不允许出现标准漏洞。

测试用例

这些以格式提供grid <newline> expression,大小写---之间带有连字符。SE格式将某些行留空,但应使用空格填充。

x
x
---
x y
z  
x
---
Fx
F(x)
---
Fx
y 
F(y,x)
---
ABu
A(B(u))
---
G
H
k
G(H(k))
---
ABCA
x xs
 DFk
A(x,B(D(F(k)),C(x,A(s))))
---
A  B  

C  D x
A(C(D(x)),B(D(x)))
---
RT Hq 
I xR k
R(I(x),T(H(R(k),q)))
---
A A  A a 
 S A  b  
B  C   Dx
d X  u f 
A(B(d,C(D(f,x))),A(X(u),A(u,a)))

这样的输出(A (B (D x)) (C (D x)))是否合适或格式是否固定?
coredump

1
@coredump在这个挑战中,输出格式很严格;爱丽丝和鲍勃希望能够直接使用已解析的表达式。
Zgarb 2015年

语言的“中缀”部分在哪里?我只看到前缀。
圣保罗Ebermann

6
您可以实际使用这种语法创建一种语言吗?:)
Martin Ender

4
后续挑战:为此语法编写一个meta-golfer(考虑到表达式树,找到与之对应的最小网格)。对于额外的困难,请区分可交换函数和非可交换函数。
马丁·恩德

Answers:


8

CJam,67 62 60 58 57 54字节

感谢Dennis节省了4个字节。

{:Gsc_32&{"()"[GGz2{1m<_{S#}#>W<\}*z]{},{J}%',**+}|}:J

这定义了一个命名块(函数)J并将其保留在堆栈上。该函数本身期望堆栈上的字符串数组代表输入网格,而将所需的字符串保留下来。

在这里测试。

自发布以来,我一直想解决这个问题,但显然我需要赏金和过长的Pyth解决方案来充分激发自己的积极性。

说明

解决方案当然是递归的,并逐步构建字符串。

{
  :G       e#  Store the current grid in G.
  sc       e#  Convert the grid to a string, flattening it, then to a character, which
           e#  discards everything but the first character. This is a golfed 0=0=.
           e#  This character will either be an upper-case letter (function) or a lower-
           e#  case letter (variable).
  _32&     e#  Make a copy of the character and take bitwise AND with 32. This gives a
           e#  NULL character for functions and a space for variables.
  {        e#  If the result is falsy... (i.e. NULL, i.e. we have a function)
    "()"   e#   Push parentheses for later use.
    [      e#   Remember the current stack depth.
    GGz    e#   Push an array which contains the grid and its transpose.
    2{     e#   Run this block twice... (it will be applied once to each grid)
      1m<  e#    Rotate the rows. This has two effects: a) It removes the first row
           e#    from the front such that we can go looking for the next non-space
           e#    character down the first column from the start. b) It places a row
           e#    at the end which we know doesn't start with a space, which acts as
           e#    a guard in case there are no further letters below the current one.
      _    e#    Duplicate this grid.
      {    e#    Find the first index where this block yields something truthy...
        S# e#     Find the index of the first space in the current row. If the row
           e#     starts with a space, this is 0, i.e. falsy and the search continues.
           e#     If there is a space in any later position, that will be positive and
           e#     truthy, so this index gets returned. If there is no space at all,
           e#     the result is -1 which is also truthy and ends the search.
      }#        
      >    e#     Discard all lines up to (but not including) the found index.
      W<   e#     Discard the guard row at the end.
      \    e#     Swap the grids so that the next pass processes the other grid.
    }*       
    z      e#    Transpose the second grid back to its original orientation.
    ]      e#    Wrap both processed grids in an array.
    {},    e#    Remove a grid if it's empty.
    {J}/   e#    For each remaining grid, call J recursively.
    ',*    e#    Join the grids with commas if there are still two of them.
    *      e#    Wrap this string in the parentheses below on the stack.
    +      e#    Prepend the function name.
  }|
}:J

5

Python 2中,227个 223 192 182 179 177字节

def r(i,y=0,x=0):
 c=i[y][x];z=[]
 for t in"pq":
    p=q=0
    try:
     while" "==i[y+p][x+q]or 1>p+q:exec t+"+=1"
     z+=[r(i,y+p,x+q)]
    except:1
 return c+"(%s)"%",".join(z)*c.isupper()

(这四个空格实际上是选项卡)

将2d字符列表作为r的第一个参数。


5

Pyth,97个字节

D:TkdI}p@@QTkGR)=Z0p\(V2JK0W|q\ @@Q=b+TJ=H+kK!+JK=J+NJ=K+!NK)I!|gblQgHl@Q0p*Z\,:bH+=Z1d))p\);:000

我的神花了很长时间(大约5/6小时?)。Pyth确实不是为此设计的...

在这里尝试。

尝试解释以及python等效

Q = literal_eval(input())

def at_slice(T,k,d):
  if Pprint(Q[T][k]) in "abcdefghijklmnopqrstuvwxyz": return 
  Z = 0
  Pprint("(")
  for N in range(2):
    J=K=0
    while " "==Q[assign('b',T+J)][assign('H',k+K)] or not J+K:
      J+=N
      K+=not N
    if not (b>=len(Q) or H>=len(Q[0])):
      Pprint(Z*",")
      at_slice(b,H,assign('Z',1)+d)
   Pprint(")")
at_slice(0,0,0)

函数的位置Pprintassign返回给定的函数。


简明扼要。哇
Addison Crump

5

Haskell中,124个 122 120 119字节

r@((c:_):_)#g|c>'_'=[c]|c<'!'=g%r|1<2=c:'(':(tail%r)!(map tail%r)++")"
_#_=""
g%r=g r#g
a!b=a++[','|a>"",b>""]++b
(#id)

用法示例:(#id) ["RT Hq ","I xR k"]-> "R(I(x),T(H(R(k),q)))"

工作原理:除了输入网格外r,该函数#还使用另一个函数g作为自变量,r只要左上角的字符为空格,该函数就会应用于该参数。如果是小写字符,则将其返回。否则,它必须是大写字符,并#递归调用,一次tail下降一次,一次一次map tail向右一次。如果需要!,将递归调用的结果与结合起来,。全部从输入网格和身份功能开始。


0

Python 3,187个字节

仍在寻找打高尔夫球的方法,但我很高兴能将其变成单线。

lambda g,r=0,c=0:g[r][c]+'(%s)'%','.join([p(g,R,c)for R in range(r+1,len(g))if c<len(g[R])and' '!=g[R][c]][:1]+[p(g,r,C)for C in range(c+1,len(g[r]))if' '!=g[r][C]][:1])*g[r][c].isupper()
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.