Vérificateur de syntaxe Prelude


10

Prelude est un langage de programmation ésotérique, qui a très peu de restrictions, mais inhabituelles, sur ce qui constitue un programme valide. Tout bloc de texte ASCII imprimable ("bloc" signifiant que les lignes ASCII imprimables sont séparées par des sauts de ligne - 0x0A) est valide à condition que:

  • Chaque colonne (verticale) de texte contient au plus un (et ).
  • En ignorant leur position verticale, les (et )sont équilibrés, c'est-à-dire que chacun (est jumelé avec exactement un )à sa droite, et vice versa.

Écrivez un programme ou une fonction qui, étant donné une chaîne contenant de l'ASCII imprimable et des sauts de ligne, détermine si elle constitue un programme Prelude valide. Vous pouvez saisir des données via STDIN (ou l'alternative la plus proche), l'argument de ligne de commande ou l'argument de fonction. Le résultat peut être retourné ou imprimé à STDOUT, en utilisant deux valeurs fixes de vérité / fausse de votre choix.

Vous ne devez pas supposer que l'entrée est rectangulaire.

Il s'agit du code golf, donc la soumission la plus courte (en octets) l'emporte.

Exemples

Les programmes Prelude suivants sont valides (en fait, ce sont même de vrais programmes Prelude):

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

Et voici un certain nombre d'entrées, qui sont toutes invalides :

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

Prélude a-t-il des commentaires qui pourraient bloquer une parenthèse étroite?
Alex A.

@Alex Non. Les règles ci-dessus sont tout ce qu'il faut pour décider si un programme est valide ou non.
Martin Ender

Cool, merci pour la clarification. Je voulais juste m'en assurer.
Alex A.

Règle 1 - "Chaque colonne de texte contient au plus une de (et)"; Exemple 1, ligne 2: "1 0v ^ (# 0) (1 + 0) #)!" -> Je vois 3 )et 2 (. Cela ne devrait-il pas être seulement 1 par ligne?
Ismael Miguel

1
@IsmaelMiguel "colonne" est généralement compris comme faisant référence aux lignes verticales (en particulier dans le contexte des grilles). Je l'ai quand même clarifié.
Martin Ender

Réponses:


3

CJam, 57 56 octets

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

Trop long, peut être beaucoup joué au golf. Explication à ajouter une fois que je jouerai au golf.

Brève explication

Il y a deux contrôles dans le code:

  • Le premier filtre vérifie que chaque colonne représente au maximum 1 parenthèse. La sortie finale du filtre est le nombre de colonnes avec plus de 1 parenthèses.
  • Ensuite, nous convertissons l'entrée en format majeur de colonne, puis la divisons sur chaque index en deux parties.
    • Dans chacune de ces deux parties, ( Number of "(" - Number of ")") devrait se compléter. Ainsi, lorsque vous les additionnez, cela devrait donner 0. Toute partie qui échoue à cette propriété fait que l'entrée entière a des crochets qui ne correspondent pas.
    • Je dois également m'assurer que "(" se trouve à gauche de ")". Cela signifie que la valeur de Number of "(" - Number of ")"ne peut pas être négative pour le bloc de droite.

Essayez-le en ligne ici


6

Python 2, 128 119 105 octets

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

Saviez-vous que vous pouvez mapper None dans Python 2?

Explication

Nous voulons commencer par transposer le Prélude pour que les colonnes deviennent des lignes. Habituellement, nous le ferions avec zip, mais comme ziptronqué à la longueur de ligne la plus courte et itertools.zip_longestbeaucoup trop long pour le code-golf, il semble qu'il n'y ait pas de moyen court de faire ce que nous voulons ...

Sauf pour la cartographie None:

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

Malheureusement (ou plutôt, heureusement pour toutes les utilisations non liées au golf), cela ne fonctionne qu'en Python 2.

Quant à net v:

  • nagit comme une pile, en comptant 1 - <number of unmatched '(' remaining>. Pour tout ce que (nous voyons, nous soustrayons 1, et pour tout ce que )nous voyons, nous ajoutons 1. Par conséquent, si n >= 2à tout moment, nous avons vu trop de )s et le programme n'est pas valide. Si nne se termine pas sur 1, il nous en reste au moins un inégalé (.
  • vvérifie la validité et commence à 1. Si le programme est jamais invalide ( n >= 2ou A+B >= 2), vdevient alors 0 pour marquer l'invalidité.

Par conséquent, si le programme est valide, à la fin, nous devons l'avoir n = 1, v = 1. Si le programme n'est pas valide, à la fin, nous devons soit avoir v = 0, soit v = 1, n <= 0. Par conséquent, la validité peut être exprimée succinctement par n*v>0.

(Merci à @feersum pour une multitude de bonnes suggestions qui ont pris 14 octets!)

Soumission précédente, plus lisible:

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

C'est une utilisation insensée de 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 Merci! J'avais essayé de changer le orchaînage en comparaison, mais je n'ai pas pensé à changer |=en *=. A pris un autre octet cependant, en rendant les choses encore plus en arrière :)
Sp3000

2

J, 64 octets

L'entrée est une chaîne avec une nouvelle ligne de fin. La sortie est 0 ou 1.

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

Exemple d'utilisation

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

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

La méthode est la suivante

  • couper l'entrée à la nouvelle ligne et la mettre dans une matrice ];.2
  • carte (/ )/ anything elsedans 1/ -1/0 1 _1 0{~[:'()'&i.]
  • définir un s=.+/@:adverbe qui ajouté à un verbe résume la sortie du tableau de verbes
  • ajouter des valeurs dans les colonnes ]s

    • vérifier le ()solde positif dans chaque préfixe [:(0>])s)[:+/\]
    • vérifier un ()équilibre égal dans toute la liste (c'est-à-dire dans le dernier préfixe) |@{:@]
  • ajouter des abs (valeurs) dans les colonnes et vérifier chaque élément pour une valeur maximale de 1 (1<|s)s

  • comme toutes les vérifications précédentes ont donné un résultat positif à l'échec, nous les additionnons et les comparons à 0 pour obtenir la validité de l'entrée 0=]


2

J, 56 octets

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

Il s'agit d'une fonction anonyme acceptant une chaîne avec un retour à la ligne de fin et retournant 0 ou 1. Lecture de droite à gauche:

  • ];.2 y, comme dans l'autre soumission J, coupe la chaîne yà toutes les occurrences de son dernier caractère (c'est pourquoi l'entrée a besoin d'un retour à la ligne) et crée une matrice rectangulaire dont les lignes sont les morceaux, complétée par des espaces si nécessaire.

  • '()'=/compare d'abord chaque caractère de cette matrice avec (puis en )renvoyant une liste de deux matrices 0-1.

  • +.^:_1]0|:transforme cette liste de deux matrices en une seule matrice de nombres complexes. Jusqu'à présent, le programme transforme chaque (entrée en 1, chaque )en i et chaque autre caractère en 0.

  • b=.+/affecte la somme des lignes de cette matrice complexe à b.

  • -.|bfait une liste de 1- | z | pour chaque z b. La condition que chaque colonne contienne au plus une seule parenthèse se traduit par tous ces nombres 1- | z | étant non négatif.

  • +/\*:best le vecteur des sommes cumulées des carrés des nombres en b. Si chaque colonne contient au plus une parenthèse, les carrés des nombres bsont tous 0, 1 ou -1. Le ,concatène ce vecteur avec le vecteur de 1- | z |.

  • maintenant tout ce que nous devons faire est de tester que les entrées de notre vecteur concaténé vsont des nombres réels non négatifs, c'est presque */0<:v, sauf que cela provoque une erreur si certaines entrées de vne sont pas réelles, donc nous remplaçons <:par <: ::0:qui retourne simplement 0 en cas d'erreur .


Excellentes idées avec les nombres complexes mais vous devez également vérifier si, 0={:+/\*:bpar exemple, (n'est pas valide.
randomra

Oh, tu as raison, @randomra, j'ai oublié!
Omar

1
0=(-|)vest de 2 octets plus court pour vérifier les réels non négatifs. (Battons CJam!: P)
randomra

1
Oh, et invau lieu d' ^:_1 enregistrer un autre octet.
randomra

1
Retour à 56 (avec vérification de l' équilibre): 3 :'*/0=({:,]-|)(-.@|,+/\@:*:)+/+.inv]0|:''()''=/];.2 y'.
randomra
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.