Prelude Syntax-Checker


10

Preludio è un linguaggio di programmazione esoterico, che ha pochissime, ma inusuali, restrizioni su ciò che costituisce un programma valido. Qualsiasi blocco di testo ASCII stampabile ("blocco" significa che le linee di ASCII stampabile sono separate da nuove righe - 0x0A) è valida a condizione che:

  • Ogni colonna (verticale) di testo contiene al massimo uno di (e ).
  • Ignorando la loro posizione verticale, i (e )sono bilanciati, cioè ognuno (è accoppiato esattamente con uno )alla sua destra e viceversa.

Scrivi un programma o una funzione che, data una stringa contenente ASCII stampabile e newline, determina se costituisce un programma Prelude valido. È possibile accettare input tramite STDIN (o alternativa più vicina), argomento della riga di comando o argomento della funzione. Il risultato può essere restituito o stampato su STDOUT, utilizzando due valori di verità / falsa fissi di propria scelta.

È necessario non assume che l'ingresso è rettangolare.

Questo è il golf del codice, quindi vince l'invio più breve (in byte).

Esempi

I seguenti sono programmi Prelude validi (in realtà, sono anche veri programmi Prelude):

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

E qui ci sono una serie di input, tutti non validi :

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

Prelude ha commenti che potrebbero bloccare una parentesi chiusa?
Alex A.

@Alex No. Le regole di cui sopra sono davvero tutto ciò che è necessario per decidere se un programma è valido o meno.
Martin Ender,

Bene, grazie per il chiarimento. Volevo solo essere sicuro.
Alex A.

Regola 1 - "Ogni colonna di testo contiene al massimo una di (e)"; Esempio 1, riga 2: "1 0v ^ (# 0) (1 + 0) #)!" -> Vedo 3 )e 2 (. Non dovrebbe essere solo 1 per riga?
Ismael Miguel,

1
La "colonna" di @IsmaelMiguel è generalmente intesa come riferimento a linee verticali (specialmente nel contesto delle griglie). L'ho chiarito comunque, comunque.
Martin Ender,

Risposte:


3

CJam, 57 56 byte

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

Troppo a lungo, può essere giocato molto a golf. Spiegazione da aggiungere dopo averlo provato.

Breve spiegazione

Esistono due controlli nel codice:

  • Il primo filtro controlla che ogni colonna sia al massimo 1 parentesi. L'output finale del filtro è il numero di colonne con più di 1 parentesi.
  • Secondo, convertiamo l'input nel formato principale della colonna e poi lo dividiamo su ciascun indice in due parti.
    • In ciascuna di queste due parti, ( Number of "(" - Number of ")") dovrebbe complimentarsi a vicenda. Quindi, quando li sommi, dovrebbe risultare a 0. Qualsiasi parte che fallisce questa proprietà fa sì che l'intero input abbia parentesi non corrispondenti.
    • Devo anche assicurarmi che "(" sia alla sinistra di ")". Ciò significa che il valore di Number of "(" - Number of ")"non può essere negativo per il blocco laterale destro.

Provalo online qui


6

Python 2, 128 119 105 byte

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

Sapevi che puoi mappare None in Python 2?

Spiegazione

Vogliamo iniziare trasponendo il Preludio in modo che le colonne diventino righe. Di solito lo faremmo con zip, ma poiché si zipriduce alla lunghezza della riga più corta ed itertools.zip_longestè troppo lungo per il code-golf, sembra che non ci sia modo di fare ciò che vogliamo ...

Tranne per la mappatura None:

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

Sfortunatamente (o meglio, fortunatamente per tutti gli scopi diversi dal golf), questo funziona solo in Python 2.

Per quanto riguarda ne v:

  • nsi comporta come una pila, contando 1 - <number of unmatched '(' remaining>. Per ogni (cosa che vediamo sottraggiamo 1, e per ogni )cosa che vediamo aggiungiamo 1. Quindi, n >= 2in qualsiasi momento, abbiamo visto troppi messaggi )e il programma non è valido. Se nnon finisce su 1, allora abbiamo almeno un (rimanente ineguagliato .
  • vverifica la validità e inizia da 1. Se il programma non è mai valido ( n >= 2o A+B >= 2), vdiventa 0 per contrassegnare la validità.

Quindi se il programma è valido, allora alla fine dobbiamo avere n = 1, v = 1. Se il programma non è valido, alla fine dobbiamo avere v = 0o v = 1, n <= 0. Pertanto la validità può essere sinteticamente espressa come n*v>0.

(Grazie a @feersum per una moltitudine di buoni suggerimenti che sono decollati 14 byte!)

Presentazione precedente, più leggibile:

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

Questo è un uso folle di map...
xnor

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

@feersum Grazie! Avevo cercato di cambiare la orin confronto concatenamento, ma non pensavo di cambiare |=in *=. Decollò un altro byte, rendendo le cose ancora più arretrate :)
Sp3000

2

J, 64 byte

L'input è una stringa con una nuova riga finale. L'output è 0 o 1.

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

Esempio di utilizzo

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

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

Il metodo è il seguente

  • tagliare l'input a newline e metterlo in una matrice ];.2
  • mappa (/ )/ anything elsein 1/ -1/0 1 _1 0{~[:'()'&i.]
  • definire un s=.+/@:avverbio che ha aggiunto a un verbo somma l'output dell'array di verbi
  • aggiungi valori in colonne ]s

    • controllare il ()saldo positivo in ogni prefisso [:(0>])s)[:+/\]
    • controlla l' ()equilibrio uguale in tutta la lista (cioè nell'ultimo prefisso) |@{:@]
  • aggiungi abs (valori) nelle colonne e controlla ogni elemento per un valore massimo di 1 (1<|s)s

  • poiché tutti i controlli precedenti hanno dato esito positivo in caso di fallimento, li sommiamo e confrontiamo con 0 per ottenere la validità dell'input 0=]


2

J, 56 byte

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

Questa è una funzione anonima che accetta una stringa con una nuova riga finale e restituisce 0 o 1. Lettura da destra a sinistra:

  • ];.2 y, come nell'altra presentazione J, taglia la stringa yin tutte le occorrenze del suo ultimo carattere (motivo per cui l'input ha bisogno di una nuova riga finale) e crea una matrice rettangolare le cui file sono i pezzi, riempite con spazi se necessario.

  • '()'=/confronta ogni carattere in quella matrice prima con (e poi con la )restituzione di un elenco di due matrici 0-1.

  • +.^:_1]0|:trasforma quell'elenco di due matrici in un'unica matrice di numeri complessi. Finora il programma trasforma ogni (input in un 1, ogni )in i e ogni altro carattere in 0.

  • b=.+/assegna la somma delle righe di quella matrice complessa a b.

  • -.|bcrea un elenco di 1- | z | per ogni z in b. La condizione che ogni colonna contenga al massimo una singola parentesi si traduce in tutti questi numeri 1- | z | essere non negativo.

  • +/\*:bè il vettore delle somme correnti dei quadrati dei numeri in b. Se ogni colonna contiene al massimo una parentesi, i quadrati dei numeri bsono tutti 0, 1 o -1. I ,concatena questo vettore con il vettore di 1- | z | 's.

  • ora tutto ciò che dobbiamo fare è verificare che le voci del nostro vettore concatenato vsiano numeri reali non negativi, questo è quasi */0<:v, tranne quello che provoca un errore se alcune voci di vnon sono reali, quindi sostituiamo <:con il <: ::0:quale restituisce solo 0 in caso di errore .


Grandi idee con i numeri complessi, ma devi anche verificare se, 0={:+/\*:bad esempio, (non è valido.
randomra,

Oh, hai ragione, @randomra, ho dimenticato!
Omar,

1
0=(-|)vè più breve di 2 byte per il controllo dei reali non negativi. (Battiamo CJam!: P)
randomra il

1
Oh, e invinvece di ^:_1 salvare un altro byte.
randomra,

1
Torna a 56 (con il controllo dell'equilibrio): 3 :'*/0=({:,]-|)(-.@|,+/\@:*:)+/+.inv]0|:''()''=/];.2 y'.
randomra,
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.