Le premier langage de programmation auquel j'ai été exposé était Sinclair BASIC . Comme de nombreux dialectes BASIC, il nécessite que toutes les lignes de code source soient numérotées .
En conséquence, l'utilisation de la GO TO
commande était idiomatique et saute l'exécution au numéro de ligne donné (pas d'étiquettes).
Il existe également une GO SUB
commande associée qui peut être utilisée comme un appel de fonction rudimentaire. Encore une fois, l'exécution passe au numéro de ligne donné, mais lorsqu'une RETURN
commande est atteinte, l'exécution revient à l'instruction suivante après le GO SUB
.
De même, la RUN
commande redémarrera l'exécution du programme sur la ligne donnée.
Quiconque a passé du temps dans un interprète BASIC numéroté en ligne aura appris à utiliser un schéma de numérotation avec des lacunes. C'est pour qu'il soit plus facile d'insérer de nouvelles lignes de code. Cependant, même dans ce cas, vous pouvez toujours avoir besoin d'insérer de nouvelles lignes entre des lignes numérotées consécutivement.
Étant donné une liste BASIC numérotée en ligne en entrée, sortez le même programme mais renuméroté de sorte que les numéros de ligne commencent à 10 et incrémentent par étapes de 10. La liste d'entrée peut avoir GO TO
ou des GO SUB
commandes, de sorte que les numéros associés à ceux-ci doivent également être ajustés.
GO TO
et lesGO SUB
commandes sont sur leurs propres lignes ou à la fin desIF
THEN
lignes. Son sûr^(\d+) .*GO (TO|SUB) (\d+)$
est suffisant pour correspondre à de telles lignes. Ces commandes entre guillemets doivent être ignorées.RUN
les commandes seront toujours sur leurs propres lignes. Dans ce cas, un numéro de ligne est facultatif. S'il est manquant, alors l'interpréteur démarre simplement en haut du programme.Si une commande
GO TO
,GO SUB
ou faitRUN
référence à une ligne inexistante, elle passera à la place à la ligne définie suivante. Votre entrée doit y faire face et s'assurer que ces références de ligne sont fixes afin qu'elles pointent vers la ligne correcte. Le comportement peut être indéfini si un numéro de ligne après la fin du programme est indiqué dans l'une de ces commandes.Les numéros de ligne seront toujours des entiers positifs de 1 à 9999 (selon le manuel). Cela signifie que les programmes d'entrée n'auront jamais plus de 999 lignes.
Les lignes d'entrée seront toujours numérotées dans l'ordre croissant numérique.
Aux fins de ce défi, les listes d'entrées ne contiendront que de l'ASCII imprimable. Vous n'avez pas à vous soucier du jeu de caractères ZX. Cela dit, si votre entrée est effectivement écrit dans ZX BASIC ou approprié z80 montage / code machine (et il y a des émulateurs sur là - bas ), vous pouvez choisir pour votre entrée à coder dans le caractère ZX jeu à la place.
Vous ne pouvez utiliser aucune bibliothèque ou utilitaire de renumérotation spécialement conçu à cet effet.
Exemple d'entrée:
1 REM "A rearranged guessing game"
2 INPUT A: CLS
3 INPUT "Guess the number ", B
10 IF A=B THEN PRINT "Correct": STOP
100 IF A<B THEN GO SUB 125
120 IF A>B THEN GO SUB 122
121 GO TO 3
125 PRINT "Try again"
126 RETURN
127 REM "An example of GO TO 7 and GO SUB 13 in quotes"
Exemple de sortie:
10 REM "A rearranged guessing game"
20 INPUT A: CLS
30 INPUT "Guess the number ", B
40 IF A=B THEN PRINT "Correct": STOP
50 IF A<B THEN GO SUB 80
60 IF A>B THEN GO SUB 80
70 GO TO 30
80 PRINT "Try again"
90 RETURN
100 REM "An example of GO TO 7 and GO SUB 13 in quotes"
Je voulais créer un lien vers un manuel ZX BASIC. Le meilleur que j'ai pu trouver semble être http://www.worldofspectrum.org/ZXBasicManual/index.html mais cela semble être un lien mort. La machine de renvoi a cependant une copie .
GOTO 100 + A*10
, et l' annexe C du ZX Spectrum Manual répertorieGO TO
comme acceptant une expression numérique (pas de restriction aux constantes). Voici une discussion sur les mérites de calculGOTO
sur ZX80 et ZX81. BTW, je ne sais pas pourquoi l'espace a été ajouté dans la version Spectrum.Réponses:
JavaScript (ES6) 177
Modifier Ajout de l'analyse (coûteuse) du prochain numéro de ligne valide
TESTER
la source
Perl 6,
147145144 144142 octetsCela peut probablement être joué un peu plus.
Étendu
la source
.min
. utiliser à la{min %line-map.keys».Num.grep:*>=$1
placeVisual Basic pour Applications, 288 octets
Je n'ai pas pu résister à donner une solution dans un dialecte BASIC. Fonctionne probablement avec Visual Basic 6 / .NET ou d'autres variantes modernes avec des modifications mineures.
J'ai utilisé beaucoup de variables à une lettre pour plus de concision. De plus, j'ai supprimé tous les espaces blancs inutiles (VBE les étend automatiquement lors de l'importation). Le nombre d'octets est pour le fichier .BAS final, avec CHR (10) comme nouvelle ligne.
Le sous-programme, qui peut être invoqué depuis la fenêtre immédiate de VBE, ouvre un programme Sinclair BASIC (le premier paramètre est le chemin vers un fichier ASCII - avec CHR (10) en tant que nouvelle ligne - contenant le programme), renuméroter les lignes et écrire les résultats dans une variable Variant (deuxième paramètre).
L'idée est d'itérer sur tous les numéros de ligne source possibles, dans l'ordre croissant, et pour chacun, de remplacer à la fois tous les numéros de ligne correspondants ainsi que
GO TO
,GO SUB
etRUN
les références avec le prochain numéro de ligne cible disponible. En utilisant cette approche, nous n'avons besoin d'aucune sorte de table de traduction. Le numéro de ligne cible est incrémenté chaque fois qu'une correspondance dans le numéro de ligne source est trouvée, de sorte que les références de ligne "incorrectes" sont ajustées automatiquement au numéro valide suivant. Les caractères de nouvelle ligne sont utilisés comme marqueurs de début et de fin de ligne, et un CHR (0) - jamais utilisé dans le programme car il n'est pas imprimable - est utilisé comme marqueur temporaire, pour éviter de renuméroter plusieurs fois la même ligne.Quelques remarques:
Par souci de concision, nous utilisons la plus petite chaîne possible pour une correspondance avec les instructions sautantes. En utilisant la fin de ligne sur nos chaînes de recherche, nous ne courons pas le risque d'inclure des occurrences citées ou des fonctions utilisateur (qui utilisent toujours des parenthèses dans Sinclair).
GO TO
nécessite une chaîne plus grande en raison de laFOR ... TO
construction (par exemple, comparer50 FOR X=AGO TO 100
et50 GO TO 100
)Le code ne prend pas en charge les instructions du formulaire
GO TO200
(sans espace), bien que le manuel ZX implique qu'il s'agit d'un code valide sur plusieurs exemples (cela coûterait une douzaine d'octets de plus pour le traiter).Le code ajoute une nouvelle ligne au début et une autre à la fin du programme. Je pourrais nettoyer cela à la fin (une douzaine d'octets de plus) mais je suppose que le ZX ignorerait probablement les lignes vides.
Ci-dessous, une version plus lisible:
la source
Pip
-rn
, 63 octetsEssayez-le en ligne!
Explication
Installer
L'
-r
indicateur lit tout stdin et le stocke sous forme de liste de lignes dans la variable localeg
. La variable globalet
est préinitialisée à 10 et la variable globales
est préinitialisée à" "
.Met la liste des lignes
g
dans la variable globaley
, afin qu'elle soit disponible dans la fonction que nous sommes sur le point de définir.Fonction de traduction des numéros de ligne
Nous construisons une fonction qui mappe à partir de n'importe quel numéro de ligne dans le schéma de numérotation d'origine (y compris un numéro inexistant) vers le numéro de ligne correspondant dans le nouveau schéma de numérotation.
Supposons que nous ayons ces lignes:
Nous voulons mapper 1 à 10, 2-4 à 20 et 5-9 à 30. Si nous avons une liste des numéros de ligne d'origine (
[1; 4; 9]
), nous pouvons utiliser une opération de filtrage pour savoir combien de ces nombres sont moins que le numéro de ligne que nous essayons de convertir. Multipliez ce résultat par 10 et ajoutez 10, et nous avons la réponse souhaitée.Par exemple, lors de la conversion de 9, il y a deux numéros de ligne (1 et 4) inférieurs à 9. 2 * 10 + 10 donne 30. Lors de la conversion de 3, il y a un numéro de ligne (1) inférieur à 3. 1 * 10 + 10 donne 20.
Voici le code (légèrement modifié pour être plus facile à lire):
Le premier remplacement:
GO TO
,GO SUB
etRUN
Le reste du programme est une expression unique qui prend
g
et fait quelques remplacements de regex (qui vectorisent, s'appliquent à chaque ligneg
).Voici le premier remplacement:
L'expression régulière correspond à l'un des
RUN
,GO SUB
etGO TO
, suivi d'un nombre, suivi de la fin de la ligne. Cela garantit qu'il ne correspond pas à l'intérieur des chaînes, ni àRUN
un numéro de ligne.L'ordre des groupes de capture est important. Le premier groupe saisit la commande ( l' un des
RUN
,GO SUB
ouGO TO
). Le deuxième groupe, s'il est utilisé, capture soitSUB
ouTO
. Nous n'avons pas besoin de capturer cette partie, mais un groupe non capturant nécessiterait des octets supplémentaires. Ensuite, le troisième groupe capture le numéro de ligne.Nous utilisons une fonction de rappel pour le remplacement. Avec des fonctions de rappel dans Pip, l'intégralité du match est le premier argument
a
, et les groupes de capture dans l' ordre sont les arguments suivantsb
,c
,d
ete
. Nous avons donc la commande dans le premier groupe, qui entreb
, et le numéro de ligne dans le troisième groupe, qui entred
. Le seul changement que nous devons faire est de passer le numéro de ligne grâce à notre fonction de conversion, qui est appelé style Lisp:(nd)
. Ensuite, nous concaténons cela avecb
un espace et le renvoyons.Deuxième remplacement: numéros de ligne
Il ne reste plus qu'à convertir les numéros de ligne au début des lignes.
L'expression régulière correspond à une série de chiffres au début d'une ligne. Encore une fois, nous utilisons une fonction de rappel; cette fois, la fonction de conversion
n
elle-même est suffisante, car la correspondance entière (premier argumenta
) est le nombre que nous voulons convertir.Comme il s'agit de la dernière expression du programme, Pip imprime automatiquement le résultat. Le
-n
drapeau sépare la liste des résultats par des sauts de ligne.la source