La entrada constará de los siguientes caracteres:
^
: Sube unov
: Baja uno▲
ok
: sube dos▼
oj
: baja dos
Por ejemplo, la siguiente entrada:
^^▲^v▼▲^^v
produciría el siguiente resultado:
^
^ ^ v
▲ v ▲
^ ▼
^
Secuencias de escape que mueven el cursor como \e[B
no están permitidas. Debe producir la salida utilizando espacios y líneas nuevas.
Aquí hay algunos casos de prueba más.
▲v^v^v^v^v^v^v^v▲
▲
▲ ^ ^ ^ ^ ^ ^ ^
v v v v v v v v
^^^^^^^▲▲▲▼▼▼vvvvvv
▲
▲ ▼
▲ ▼
^ ▼
^ v
^ v
^ v
^ v
^ v
^ v
v^^vv^^vvv^v^v^^^vvvv^^v^^vv
^ ^ ^
^ v ^ v ^ v ^
v v v ^ ^ ^ v ^ ^ v
v v v v ^ v v
v
j
bajar dos veces yk
subir dos veces también.Respuestas:
Pyth, 27 bytes
Pruébelo en línea: Demostración o conjunto de pruebas
Yo uso
k
y enj
lugar de▲
y▼
. Hay muchas líneas vacías iniciales y finales. Tienes que buscar un poco para encontrar la imagen. Aquí hay una versión de 34 bytes , que elimina todas las líneas vacías iniciales y finales.Pruébelo en línea: Demostración o conjunto de pruebas
Explicación:
fuente
Ilegible ,
219921452134210420872084 bytesSoporta tanto
k
/j
como▲
/▼
sintaxis.En una buena tradición ilegible, aquí está el programa formateado en fuente proporcional, para ofuscar la distinción entre apóstrofes y comillas dobles:
Este fue un desafío increíble. ¡Gracias por tu publicación!
Explicación
Para tener una idea de lo que ilegible puede y no puede hacer, imagine Brainfuck con una cinta infinita en ambas direcciones, pero en lugar de un puntero de memoria moviendo una celda a la vez, puede acceder a cualquier celda de memoria desreferenciando un puntero. Esto resulta bastante útil en esta solución, aunque otras operaciones aritméticas, incluido el módulo, deben realizarse a mano.
Aquí está el programa como pseudocódigo con comentarios del director:
Esto en cuanto a la lógica del programa. Ahora tenemos que traducir esto a ilegible y usar algunos trucos de golf más interesantes.
Las variables siempre se desreferencian numéricamente en No legible (por ejemplo, se
a = 1
convierte en algo parecido*(1) = 1
). Algunos literales numéricos son más largos que otros; el más corto es 1, seguido de 2, etc. Para mostrar cuánto más largos son los números negativos, aquí están los números de -1 a 7:Claramente, queremos asignar la variable # 1 a la que ocurre con mayor frecuencia en el código. En el primer ciclo while, esto es definitivamente
mod5
, que aparece 10 veces. Pero no necesitamosmod5
más después del primer ciclo while, por lo que podemos reasignar la misma ubicación de memoria a otras variables que usaremos más adelante. Estos sonptr2
yptr3
. Ahora se hace referencia a la variable 21 veces en total. (Si está tratando de contar el número de ocurrencias usted mismo, recuerde contar algo comoa++
dos veces, una para obtener el valor y otra para establecerlo).Solo hay otra variable que podemos reutilizar; después de calcular los valores del módulo,
ch
ya no es necesario.up
ydn
aparece el mismo número de veces, así que cualquiera está bien. Fusionémonosch
conup
.Esto deja un total de 8 variables únicas. Podríamos asignar las variables 0 a 7 y luego iniciar el bloque de memoria (que contiene los caracteres y los números de línea) en 8. ¡Pero! Como 7 tiene la misma longitud en el código que −1, también podríamos usar las variables −1 a 6 e iniciar el bloque de memoria en 7. ¡De esta manera, cada referencia a la posición de inicio del bloque de memoria es ligeramente más corta en el código! Esto nos deja con las siguientes tareas:
Ahora esto explica la inicialización en la parte superior: es 5 porque es 7 (el comienzo del bloque de memoria) menos 2 (el incremento obligatorio en la primera condición while). Lo mismo ocurre con las otras dos ocurrencias de 5 en el último bucle.
Tenga en cuenta que, dado que 0 y 4 tienen la misma longitud en el código,
ptr
yminLine
podrían asignarse de cualquier manera. ... ¿O podrían?¿Qué pasa con el misterioso 2 en el penúltimo bucle while? ¿No debería ser este un 6? Solo queremos disminuir los números en el bloque de datos, ¿verdad? Una vez que llegamos a 6, estamos fuera del bloque de datos y debemos detenernos. ¡Sería una vulnerabilidad de seguridad de error de error de desbordamiento de búfer!
Bueno, piensa en lo que pasa si no nos detenemos. Decrementamos las variables 6 y 4. La variable 6 es
mod4
. Eso solo se usa en el primer ciclo while y ya no es necesario aquí, por lo que no se hace daño. ¿Qué pasa con la variable 4? ¿Qué crees que debería serptr
o debería ser la variable 4minLine
? Así es, ¡minLine
ya no se usa en este momento! Por lo tanto, la variable # 4 esminLine
y podemos disminuirla de manera segura y no hacer daño.ACTUALIZACIÓN 1! Golfed desde 2199 a 2145 bytes por darse cuenta de que
dn
puede también fusionarse conmod5
, a pesar de quemod5
todavía se utiliza en el cálculo del valor dedn
! La nueva asignación de variables es ahora:ACTUALIZACIÓN 2! Golfó de 2145 a 2134 bytes al darse cuenta de que, dado
mod5
que ahora está en la misma variable quedn
, que se cuenta a 0 en un ciclo while,mod5
ya no necesita inicializarse explícitamente a 0.ACTUALIZACIÓN 3! Golfó de 2134 a 2104 bytes al darse cuenta de dos cosas. Primero, aunque la idea del "módulo negativo" valió la pena
mod5
, el mismo razonamiento no se aplicamod4
porque nunca probamos,mod4+2
etc. Por lo tanto, cambiarmod4 ? mod4+1 : -3
amod4 ? mod4-1 : 3
nos lleva a 2110 bytes. En segundo lugar, dadomod4
que siempre es 0 o 2, podemos inicializarmod4
a 2 en lugar de 0 e invertir los dos ternarios (enmod4 ? 3 : 1
lugar demod4 ? 1 : 3
).ACTUALIZACIÓN 4! Jugó desde 2104 hasta 2087 bytes al darse cuenta de que el ciclo while que calcula los valores del módulo siempre se ejecuta al menos una vez, y en tal caso, Ilegible le permite reutilizar el valor de la última declaración en otra expresión. Por lo tanto, en lugar de
while --ch: [...]; up = (mod5 ? mod5+1 ? [...]
ahora tenemosup = ((while --ch: [...]) ? mod5+1 ? [...]
(y dentro de ese ciclo while, calculamosmod4
primero, así que esamod5
es la última declaración).ACTUALIZACIÓN 5! Golfé de 2087 a 2084 bytes al darme cuenta de que en lugar de escribir las constantes
32
y10
(espacio y nueva línea), puedo almacenar el número 10 en la variable (ahora no utilizada) # 2 (llamémoslaten
). En lugar deptr3 = 5
escribirten = (ptr3 = 5) + 5
, luego se32
vuelveten+22
y seprint 10
vuelveprint ten
.fuente
CJam, 37 bytes
Esto imprime líneas vacías antes y después de la salida deseada, que ha sido permitida por el OP .
Pruébelo en línea en el intérprete de CJam .
Cómo funciona
fuente
Pitón 2, 102
Imprime línea por línea.
Recorre los caracteres en la entrada y rastrea la altura actual. La altura se actualiza por uno de los
+2, +1, -1, -2
calculados por'kv_^j'.find(c)-2
. Probablemente hay una cadena mod que es más cortaCuando la altura actual es igual al número de línea (que puede ser negativo), agregamos el carácter actual a la línea y, de lo contrario, agregamos un espacio. Luego, imprimimos la línea. En realidad, es más corto comenzar la altura en el número de línea actual y restar los cambios de altura, agregando el carácter cuando llega el valor
0
.Los números de línea abarcan un rango lo suficientemente grande como para que una secuencia de dos arriba o dos abajo permanezca dentro de él. En realidad, hay una buena cantidad de exceso. Si tuviéramos un límite superior en la longitud de entrada, sería más corto escribir, digamos
j=999
.Sorprendentemente,
i and' 'or c
fue más corto de lo habitual[' ',c][i==0]
. Tenga en cuenta quei
puede ser negativo, lo que elimina algunos trucos habituales.fuente
MATLAB, 116
Es un comienzo. El
j
yk
hacer que sea un dolor en el cuello ya que no puedo encontrar una manera de mapear matemáticamente desde yj^vk
hacia[-2 -1 1 2]
MATLAB sin reconocer el Unicode (aparentemente, tanto arriba como abajo tienen un valor de 26 en MATLAB. ¡Vaya!), Hay muchos bytes desperdiciados haciendo el mapeo.Al inspirarse en la solución @xnors, el código se puede reducir en otros 14 caracteres mapeando el carácter de control dentro del bucle for.
También se desperdician muchos bytes tratando de explicar si la cadena de entrada envía el patrón nuevamente debajo del índice en el que comenzó (tal vez si hubiera un límite en la longitud de la cadena podría simplificar ese bit).
Y en su forma legible:
fuente
b=[-2 -1 1 2](a==[106 107 94 118])
? Funciona en octava. ¡O inclusob=[-2 -1 1 2](a-94==[12 13 0 24])
si quieres afeitarte un byte más!==
paradas deja de funcionar, y también en MATLAB no se puede poner un()
después de un[]
.+=
, fwiw.)JavaScript (ES6), 140
Pruebe a ejecutar el fragmento a continuación en un navegador compatible con EcmaScript 6 (probado en Firefox).
fuente
GS2, 34 bytes
Este calcula correctamente los límites de salida para que no se produzca un exceso de espacio en blanco. Aquí está mi solución en hexadecimal
Una pequeña explicación está en orden. En la pila tenemos la entrada del usuario como una matriz de códigos ASCII. El programa comienza en una cadena literal debido a
05
. Aquí vamos.GS2, 24 bytes
También tengo una solución de 24 bytes que no tiene mucho cuidado al calcular el tamaño de salida, y termina con espacios en blanco adicionales. Sin embargo, prefiero el que tiene el espacio en blanco al mínimo.
fuente
Crayón , 13 bytes (no competidor)
Pruébalo en línea!Utiliza las flechas reales porque por qué no.
No compite porque Crayon es mucho más nuevo que este desafío.
Cómo funciona
Crayon es un lenguaje basado en pila diseñado para ser asesino en los desafíos de arte ASCII. Se basa en la base de un "lienzo" de salida bidimensional y un "crayón", un cursor que recorre este lienzo. Todo lo que se envía a la salida se dibuja en el lienzo en la posición del crayón y en la dirección en la que se encuentra el crayón. Por defecto, el crayón apunta al Este (a la derecha).
fuente
pb - 136 bytes
Usos
k
y enj
lugar de▲
y▼
.Un par de notas:
Escape sequences that move the cursor such as \e[B are not allowed. You must produce the output using spaces and newlines.
¡Sigo esta regla! pb utiliza el concepto de "pincel" para generar caracteres. El pincel se mueve alrededor del "lienzo" y puede imprimir un personaje inmediatamente debajo de él. Sin embargo, la implementación real imprime el personaje usando espacios y líneas nuevas.You are allowed trailing spaces and/or empty lines
. Esto es por un par de razones:n
comienza enY=3n+1
. El-1
es porque está bajando3n
deY=-1
, y a partir deY=2n-1
falla por una entrada de todosk
.¡Puedes ver este programa en acción en YouTube! Esta versión está ligeramente modificada ya que solo se reduce a
n-1
. Funciona para esta entrada, pero fallará para otros. Sin embargo, captura mucho mejor.Con comentarios:
fuente
Ceilán, 447 bytes
O con saltos de línea para "legibilidad":
import ceylon.language{o=null,v=variable,s=shared}s void y(){v L c;v L f;v L l;v Integer i=0;class L(v L?p,v L?n){s v String t="";s L u=>p else(f=p=L(o,this));s L d=>n else(l=n=L(this,o));s void a(Character c)=>t=t+" ".repeat(i-t.size)+c.string;}f=l=c=L(o,o);for(x in process.readLine()else""){switch(x)case('^'){c=c.u;}case('v'){c=c.d;}case('▲'|'k'){c=c.u.u;}case('▼'|'j'){c=c.d.d;}else{}c.a(x);i++;}print(f.t);while(f!=l){f=f.d;print(f.t);}}
Esto funciona tanto con la entrada ▲ / ▼ como con la entrada j / k (si tuviéramos que admitir solo uno de ellos, el programa sería 8 bytes más corto). La última línea de salida está vacía cuando la posición de inicio estaba en ella (es decir, la primera entrada fue una
▲
o^
y nunca volvimos a estar debajo de eso más tarde). La entrada que no sea uno de los caracteres especificados simplemente se imprimirá tal cual, sin cambiar la línea:→
Aquí hay una versión formateada (753 bytes):
Este es un programa "orientado a objetos" casi directo ... la clase (local)
L
(buffer de línea) almacena una línea de texto (int
), así como punteros (anulables) al siguiente (n
) y al anterior (p
) línea. Los atributos (no anulables)u
(para arriba) yd
(para abajo) inicializan aquellos si es necesario (con un puntero inverso a sí mismo), y en este caso también hacen un seguimiento de la primera y última línea en general (en elf
yl
variables ).El
a
método (append) agrega un carácter a esta línea, incluidos algunos espacios eventualmente necesarios.c
Es la línea actual. Analizamos la cadena de entrada (usandoreadLine
como la entrada debe estar en una línea) usando una instrucción switch que actualiza la línea actual y luego llama al método append.Después de realizar el análisis, iteramos sobre las líneas desde la primera hasta la última, imprimiendo cada una de ellas. (Esto destruye el
f
puntero, si fuera necesario después, deberíamos haber usado una variable separada para esto).Algunos trucos usados para jugar al golf:
Algunas cosas que en otros idiomas serían palabras clave en realidad son solo identificadores en el
ceylon.language
paquete, y se pueden renombrar con un alias de importación. Usamos esto para las anotacionesshared
(usado 5 ×) yvariable
(usado 6 ×), así como para el objetonull
(usado 4 ×):(Trivia: The Formatter en el IDE de Ceilán formatea algunas anotaciones de lenguaje incorporadas, entre ellas
variable
yshared
, al colocarlas en la misma línea que la declaración anotada, contrasta con las anotaciones personalizadas, que se colocan en una línea separada encima de la declaración. Esto hace que la versión formateada del programa de golf sea ilegible, por lo tanto, cambié las alias-importaciones para esta versión).this
,void
,case
,else
Son palabras clave reales y no se puede renombrar esta manera, yInteger
,String
yCharacter
aparece sólo una vez cada uno, por lo que no hay nada que ganar mediante la importación.Originalmente también tenía una clase ScreenBuffer separada (que hacía un seguimiento de la lista vinculada de buffers de línea, el índice actual, etc.), pero como solo había un objeto, se optimizó.
Esa clase Screenbuffer también tenía
up
ydown
métodos, que fueron llamados desde el analizador (y lo hicieroncurrentLine = currentLine.up
respectivamentecurrentLine = currentLine.down
). Demostró que hacer esto directamente en el interruptor del analizador es más corto. También permitió escribircurrentLine = currentLine.up.up
(que luego se convirtióc = c.u.u
) en lugar decurrentLine = currentLine.up;currentLine = currentLine.up
.Originalmente pasamos el índice actual como argumento al método append (e incluso al analizador desde el bucle); tener una variable en la función que contiene es más corto.
Originalmente, mi método printAll usaba el puntero actual y lo movía primero hacia arriba hasta que la línea actual estaba vacía, y luego hacia abajo mientras imprimía cada línea. Esto se rompió al usar ▲ y ▼ para saltar sobre las líneas, por lo que tuvimos que agregar explícitamente algo en esas líneas saltadas. Hacer un seguimiento de la primera / última línea resultó más fácil (aunque hizo necesario usar dos declaraciones de impresión, porque no hay un ciclo do-while en Ceilán).
Originalmente tenía algo como esto:
process.readLine
devuelvenull
si no hay una línea que pueda leerse (porque la entrada se ha cerrado), y el compilador de Ceilán me exige que verifique eso antes de accederinput
. Como en este caso no quiero hacer nada, puedo usar elelse
operador que devuelve su primer argumento si no es nulo, y de lo contrario su segundo argumento, guardando la variable y la instrucción if. (Esto también nos permitiría codificar una entrada por defecto para la prueba:for (x in process.readLine() else "^^▲^v▼▲^^v") {
)fuente
JavaScript (ES6), 228 bytes
Bueno, aquí hay una solución recursiva (bastante larga) que pasa todos los casos de prueba dados. Fue un lindo desafío. Esto usa
k
yj
en lugar de▼
y▲
.Fragmento de prueba
Aunque el envío en sí solo puede manejar
k,j
, el siguiente fragmento puede manejar ambosk,j
y▼,▲
.fuente