Analizzare una sintassi bidimensionale


25

sfondo

Alice e Bob stanno creando un linguaggio golfistico per vincere ogni singola sfida PPCG. Alice vuole creare un linguaggio bidimensionale, come> <>, ma Bob preferisce una sintassi con prefisso come in J. Come compromesso, decidono di creare un linguaggio con prefisso bidimensionale. Il parser è un dolore da scrivere e hanno bisogno del tuo aiuto!

Specifica di sintassi

Nel linguaggio di Alice e Bob, ci sono variabili , che sono rappresentate da lettere ASCII minuscole a-z, e funzioni , che sono rappresentate da lettere ASCII maiuscole A-Z. Una funzione può essere invocata con uno o due argomenti. Un programma è una griglia rettangolare di lettere a-zA-Ze spazi e l'angolo in alto a sinistra non deve contenere uno spazio. Questo è un esempio di un programma valido:

F Gy
H   
R x 

Quando il programma viene analizzato, viene trasformato in un'espressione di un linguaggio in stile C (C, Java, Python ...) contenente variabili a lettera singola e chiamate di funzione nel formato <func>(<arg>)o <func>(<arg1>,<arg2>). Ad esempio, il programma sopra riportato risulta in questa espressione:

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

I dettagli del processo di analisi sono i seguenti:

  • Gli spazi sono solo riempitivi, quindi non vengono analizzati.
  • Ogni variabile a-zviene sempre analizzata come se stessa.
  • Ogni funzione A-Zviene analizzata come una chiamata di funzione. I suoi argomenti sono le espressioni più vicine al di sotto di essa e alla sua destra nella griglia, in questo ordine. Se solo uno di questi è presente, viene fornito come unico argomento. Si può presumere che tutte le funzioni abbiano almeno un argomento nella griglia.

Nell'esempio sopra, le variabili xe yvengono analizzate come se stesse. La funzione Rnon ha nulla al di sotto e xalla sua destra, quindi viene analizzata come invocazione con un argomento R(x). Allo stesso modo, Hviene analizzato come H(R(x)), poiché ha al di Rsotto di esso. La funzione Gha xsotto di essa e yalla sua destra, quindi è analizzata come G(x,y), e allo stesso modo per F. L'espressione analizzata nell'angolo in alto a sinistra è il risultato del processo di analisi.

Ingresso e uscita

Il tuo input è una matrice rettangolare di caratteri non vuota. Sarà sempre un programma valido nel linguaggio di Alice e Bob, ma può contenere espressioni non utilizzate nell'output. L'output deve essere l'espressione analizzata risultante dal processo precedente.

Regole e punteggio

È possibile scrivere un programma completo di una funzione. Vince il conteggio di byte più basso e non sono consentite scappatoie standard.

Casi test

Questi sono indicati nel formato grid <newline> expression, con trattini ---tra i casi. Il formato SE lascia alcune righe vuote, ma dovrebbero essere riempite di spazi.

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)))

Un output come (A (B (D x)) (C (D x)))sarebbe adatto o il formato è fisso?
coredump,

1
@coredump In questa sfida, il formato di output è rigoroso; Alice e Bob vogliono essere in grado di usare direttamente l'espressione analizzata.
Zgarb,

Dov'è la parte "infix" della lingua? Vedo solo il prefisso.
Paŭlo Ebermann,

6
Puoi per favore creare effettivamente una lingua con questa sintassi? :)
Martin Ender il

4
Sfida di follow-up: scrivi un meta-golfista per questa sintassi (dato un albero delle espressioni, trova la griglia più piccola corrispondente ad essa). Per ulteriori difficoltà, distinguere tra funzioni commutative e non commutative.
Martin Ender,

Risposte:


8

CJam, 67 62 60 58 57 54 byte

Grazie a Dennis per aver salvato 4 byte.

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

Questo definisce un blocco denominato (funzione) Je lo lascia nello stack. La stessa funzione prevede una serie di stringhe nello stack, che rappresenta la griglia di input e lascia la stringa desiderata al suo posto.

Provalo qui.

Ho intenzione di affrontare questo da quando è stato pubblicato, ma a quanto pare avevo bisogno di una taglia e una soluzione Pyth eccessivamente lunga per motivarmi sufficientemente.

Spiegazione

La soluzione è ovviamente ricorsiva e costruisce gradualmente la stringa.

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

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()

(I quattro spazi sono in realtà schede)

Accetta un elenco di caratteri 2D come primo argomento di r.


5

Pyth, 97 byte

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

Mio dio che ci è voluto molto tempo per realizzarlo (circa 5/6 ore?). Pyth non è stato progettato per questo ...

Provalo qui .

Tentativo di spiegazione nonché equivalente di 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)

Dove le funzioni Pprinte assignrestituiscono ciò che viene dato.


Molta concisione. Eeeek !!!
Addison Crump,

5

Haskell, 124 122 120 119 byte

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)

Esempio di utilizzo: (#id) ["RT Hq ","I xR k"]-> "R(I(x),T(H(R(k),q)))".

Come funziona: oltre alla griglia di input r, la funzione #assume un'altra funzione gcome argomento che viene applicato rogni volta che il carattere in alto a sinistra è uno spazio. Se invece è un carattere minuscolo, restituiscilo. Altrimenti deve essere un carattere maiuscolo e #viene chiamato ricorsivamente, una volta con tailper andare giù e una volta con map tailper andare a destra. !unisce i risultati delle chiamate ricorsive con un ,, se necessario. Tutto inizia con la griglia di input e la funzione di identità.


0

Python 3, 187 byte

Sono ancora alla ricerca di modi per giocare a golf, ma sono contento di essere riuscito a trasformarlo in un solo giocatore.

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()
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.