2 차원 구문 분석


25

배경

앨리스와 밥은 모든 PPCG 도전에서 승리하기 위해 골프 언어를 만들고 있습니다. Alice는> <>와 같은 2 차원 언어를 만들고 싶어하지만 Bob은 J와 같은 접두사 접두사 구문을 선호합니다. 파서는 작성하는 데 어려움이 있으며 도움이 필요합니다!

구문 사양

Alice와 Bob의 언어에는 소문자 ASCII 문자로 표시되는 변수a-z 와 대문자 ASCII 문자로 표시되는 함수 가 있습니다 A-Z. 하나 또는 두 개의 인수로 함수를 호출 할 수 있습니다. 프로그램은 문자의 사각형 격자이다 a-zA-Z공백, 그리고 왼쪽 상단 코너에 공백을 포함 할 수 없습니다. 다음은 유효한 프로그램의 예입니다.

F Gy
H   
R x 

프로그램이 구문 분석 할 때, 형식의 단일 문자 변수와 함수 호출을 포함하는 C 스타일 언어 (C, 자바, 파이썬 ...)의 표현으로 변환 것 <func>(<arg>)<func>(<arg1>,<arg2>). 예를 들어, 위의 프로그램은 다음과 같은 식으로 나타납니다.

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

구문 분석 프로세스의 세부 사항은 다음과 같습니다.

  • 공백은 필러이므로 구문 분석되지 않습니다.
  • 모든 변수 a-z는 항상 그 자체로 구문 분석됩니다.
  • 모든 함수 A-Z는 함수 호출로 구문 분석됩니다. 이 인수는 아래에 있고 그리드에서 오른쪽에 가장 가까운 식입니다. 이들 중 하나만있는 경우 유일한 인수로 제공됩니다. 모든 함수에 격자에 하나 이상의 인수가 있다고 가정 할 수 있습니다.

위의 예에서 변수 x와 변수 y는 그 자체로 구문 분석됩니다. 이 함수 R는 그 아래와 x오른쪽에 아무것도 없으므로 1 인수 호출로 구문 분석됩니다 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 December

1
@coredump이 과제에서 출력 형식은 엄격합니다. Alice와 Bob은 구문 분석 된 표현식을 직접 사용할 수 있기를 원합니다.
Zgarb

언어의 "접두사"는 어디에 있습니까? 접두사 만 보입니다.
Paŭlo Ebermann

6
이 구문으로 언어를 실제로 만들 수 있습니까? :)
Martin Ender

4
후속 과제 :이 구문에 대한 메타 골퍼를 작성하십시오 (표현식 트리에서 해당하는 가장 작은 격자를 찾으십시오). 추가적인 어려움을 위해, 정류 함수와 비 정류 함수를 구별하십시오.
Martin Ender

답변:


8

CJam, 67 62 60 58 57 54 바이트

4 바이트를 절약 해 준 Dennis에게 감사합니다.

{: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

파이썬 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()

(사실은 실제로 탭입니다)

r의 첫 번째 인수로 2d 문자 목록을 사용합니다.


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는 실제로 이것을 위해 설계되지 않았습니다 ...

여기에서 시도 하십시오 .

파이썬과 동등한 설명뿐만 아니라 설명하려고 시도하십시오.

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그들이 제공하는지 돌아갑니다.


많은 결정. 그런 와우.
애디슨 크럼

5

하스켈 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함수 #는 왼쪽 상단 문자가 공백 gr때마다 적용되는 인수로 다른 함수 를 사용합니다 . 대신 소문자 인 경우 반환하십시오. 그렇지 않으면 대문자 여야하며 #한 번은 tail아래로, 한 번은 map tail오른쪽으로 돌아가는 것으로 재귀 적으로 호출 됩니다. 필요한 경우 !재귀 호출의 결과를와 결합합니다 ,. 모든 것은 입력 그리드와 아이덴티티 기능으로 시작합니다.


0

파이썬 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()
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.