El primer lenguaje de programación al que estuve expuesto fue Sinclair BASIC . Al igual que muchos dialectos BÁSICOS, requiere que todas las líneas del código fuente estén numeradas .
Como resultado, el uso del GO TO
comando era idiomático y salta la ejecución al número de línea dado (sin etiquetas).
También hay un GO SUB
comando relacionado que se puede usar como una llamada de función rudimentaria. Nuevamente, la ejecución salta al número de línea dado, pero cuando RETURN
se alcanza un comando, la ejecución vuelve a la siguiente instrucción después de GO SUB
.
Del mismo modo, el RUN
comando reiniciará la ejecución del programa en la línea dada.
Cualquiera que haya pasado algún tiempo en un intérprete BASIC numerado por línea habrá aprendido a usar un esquema de numeración con huecos. Esto es para que sea más fácil insertar nuevas líneas de código. Sin embargo, aun así, es posible que necesite insertar nuevas líneas entre líneas numeradas consecutivamente.
Dada una lista BASIC numerada con línea como entrada, genera el mismo programa pero renumerado de tal manera que los números de línea comienzan en 10 y se incrementan en pasos de 10. La lista de entrada puede tener GO TO
o GO SUB
comandos, por lo que los números asociados con estos también deben ajustarse.
GO TO
y losGO SUB
comandos están en sus propias líneas o al final de lasIF
THEN
líneas. Es seguro decir que^(\d+) .*GO (TO|SUB) (\d+)$
es suficiente para que coincida con tales líneas. Estos comandos entre comillas deben ignorarse.RUN
los comandos siempre estarán en sus propias líneas. En este caso, un número de línea es opcional. Si falta, el intérprete simplemente comienza en la parte superior del programa.Si a
GO TO
,GO SUB
oRUN
referencias de comandos de una línea inexistente, entonces en vez saltará a la siguiente línea definida. Su entrada debe ocuparse de esto y asegurarse de que cualquier referencia de línea sea fija para que apunte a la línea correcta. El comportamiento puede ser indefinido si se proporciona un número de línea después del final del programa en uno de estos comandos.Los números de línea siempre serán enteros positivos del 1 al 9999 (según el manual). Esto significa que los programas de entrada nunca tendrán más de 999 líneas.
Las líneas de entrada siempre se numerarán en orden numérico ascendente.
Para los propósitos de este desafío, los listados de entrada solo contendrán ASCII imprimible. No necesita preocuparse por el juego de caracteres ZX. Una vez dicho esto, si su entrada es en realidad escrito en ZX BASIC o apropiarse z80 montaje / código de máquina (y hay emuladores fuera allí ), entonces usted puede elegir que su entrada a codificar en el conjunto de caracteres ZX en su lugar.
No puede utilizar ninguna biblioteca de renumeración o utilidades específicamente diseñadas para este propósito.
Entrada de ejemplo:
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"
Salida de ejemplo:
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"
Quería vincularme a un manual ZX BASIC. Lo mejor que pude encontrar parece ser http://www.worldofspectrum.org/ZXBasicManual/index.html, pero este parece ser un enlace inactivo. Sin embargo, la máquina wayback tiene una copia .
GOTO 100 + A*10
, y el Apéndice C del ZX Spectrum Manual enumeraGO TO
como aceptar una expresión numérica (sin restricción de constantes). Aquí hay una discusión sobre los méritos de computarGOTO
en ZX80 y ZX81. Por cierto, no tengo idea de por qué se agregó el espacio en la versión Spectrum.Respuestas:
JavaScript (ES6) 177
Editar Se agregó el escaneo (costoso) para el siguiente número de línea válido
PRUEBA
fuente
Perl 6,
147145144142 bytesEsto probablemente se pueda jugar un poco más.
Expandido
fuente
.min
. utilizar{min %line-map.keys».Num.grep:*>=$1
en su lugarVisual Basic para aplicaciones, 288 bytes
No pude resistir dar una solución en un dialecto BÁSICO. Probablemente funciona con Visual Basic 6 / .NET u otras variantes modernas con cambios menores.
Usé muchas variables de una letra para concisión. Además, eliminé todos los espacios en blanco innecesarios (VBE los expande automáticamente en la importación). El recuento de bytes es para el archivo final .BAS, con CHR (10) como nueva línea.
La subrutina, que se puede invocar desde la ventana inmediata de VBE, abre un programa Sinclair BASIC (el primer parámetro es la ruta a un archivo ASCII, con CHR (10) como nueva línea, que contiene el programa), renumera las líneas y escribe los resultados en una variable Variant (segundo parámetro).
La idea es iterar en todos los números de línea de origen posibles, orden ascendente y, para cada uno, reemplazar de una vez todos los números de línea coincidentes, así como
GO TO
,GO SUB
yRUN
referencias con el siguiente número de línea de destino disponibles. Con este enfoque, no necesitamos ningún tipo de tabla de traducción. El número de línea objetivo se incrementa cada vez que se encuentra una coincidencia en el número de línea de origen, por lo que las referencias de línea "incorrectas" se ajustan automáticamente al siguiente número válido. Los caracteres de nueva línea se utilizan como marcadores de inicio y final de línea, y un CHR (0), nunca utilizado en el programa porque no es imprimible, se utiliza como marcador temporal, para evitar volver a numerar la misma línea varias veces.Algunas observaciones:
Para ser concisos, usamos la cadena más pequeña posible para un partido con las declaraciones de salto. Al usar el final de línea en nuestras cadenas de búsqueda, no corremos el riesgo de incluir ocurrencias citadas o funciones de usuario (que siempre usan paréntesis en Sinclair).
GO TO
requiere una cadena más grande debido a laFOR ... TO
construcción (por ejemplo, comparar50 FOR X=AGO TO 100
y50 GO TO 100
)El código no admite declaraciones en el formulario
GO TO200
(sin espacios en blanco), aunque el manual de ZX implica que es un código válido en varios ejemplos (costaría una docena más de bytes tratarlo).El código agrega una nueva línea al principio y otra al final del programa. Podría limpiar esto al final (una docena más de bytes) pero creo que ZX probablemente ignoraría las líneas en blanco.
A continuación, una versión más legible:
fuente
Pip
-rn
, 63 bytesPruébalo en línea!
Explicación
Preparar
El
-r
indicador lee todo el stdin y lo almacena como una lista de líneas en la variable localg
. La variable globalt
está preinicializada a 10, y la variable globals
está preinicializada a" "
.Marca la lista de líneas
g
en la variable globaly
, para que esté disponible dentro de la función que estamos a punto de definir.Función de traducción del número de línea
Construimos una función que se asigna desde cualquier número de línea en el esquema de numeración original (incluido uno inexistente) al número de línea correspondiente en el nuevo esquema de numeración.
Supongamos que tenemos estas líneas:
Queremos asignar 1 a 10, 2-4 a 20 y 5-9 a 30. Si tenemos una lista de los números de línea originales (
[1; 4; 9]
), podemos usar una operación de filtro para averiguar cuántos de estos números son menos que el número de línea que estamos tratando de convertir. Multiplique ese resultado por 10 y agregue 10, y tenemos la respuesta deseada.Por ejemplo, al convertir 9, hay dos números de línea (1 y 4) menores que 9. 2 * 10 + 10 da 30. Al convertir 3, hay un número de línea (1) menor que 3. 1 * 10 + 10 da 20.
Aquí está el código (ligeramente modificado para que sea más fácil de leer):
En primer lugar la sustitución:
GO TO
,GO SUB
yRUN
El resto del programa es una sola expresión que toma
g
y realiza un par de reemplazos de expresiones regulares (que vectorizan, aplicando a cada líneag
).Aquí está el primer reemplazo:
La expresión regular coincide con cualquiera de
RUN
,GO SUB
yGO TO
, seguido de un número, seguido del final de la línea. Esto asegura que no coincida con las cadenas internas, ni conRUN
un número de línea.El orden de los grupos de captura es importante. El primer grupo captura el comando (una de
RUN
,GO SUB
oGO TO
). El segundo grupo, si se usa, captura cualquieraSUB
oTO
. No necesitamos capturar esta parte, pero un grupo sin captura requeriría bytes adicionales. Luego, el tercer grupo captura el número de línea.Utilizamos una función de devolución de llamada para el reemplazo. Con las funciones de devolución de llamada en la pipa, el encuentro es el primer argumento
a
, y los grupos de captura en el orden son los argumentos posterioresb
,c
,d
, ye
. Entonces tenemos el comando en el primer grupo, que entrab
, y el número de línea en el tercer grupo, que entrad
. El único cambio que tenemos que hacer es pasar el número de línea a través de nuestra función de conversión, que se llama Lisp de estilo:(nd)
. Luego concatenamos eso junto conb
un espacio y lo devolvemos.Segundo reemplazo: números de línea
Todo lo que queda por convertir son los números de línea al comienzo de las líneas.
La expresión regular coincide con una serie de dígitos al comienzo de una línea. Nuevamente usamos una función de devolución de llamada; esta vez, la función de conversión en
n
sí misma es suficiente, ya que toda la coincidencia (primer argumentoa
) es el número que queremos convertir.Como esta es la última expresión del programa, Pip imprime automáticamente el resultado. La
-n
bandera separa la lista de resultados con nuevas líneas.fuente