> <> Fuera del agua

20

El querido pez que nada a través del código de > <> (un lenguaje de programación esotérico) ha sido sacado de su entorno natural. Este cambio lo ha vuelto incapaz de moverse de la forma en que solía hacerlo: lo que solía ser un movimiento toroidal se ha restringido a un simple movimiento de izquierda a derecha. Pero los programas> <> todavía se escriben como si el pez fuera capaz de moverse a través de ellos. Es su tarea, querido programador, escribir un programa para linealizar un programa> <>. Y hazlo en el menor número de bytes posible; Los peces no tienen recuerdos muy grandes.

Movimiento en> <>

En> <>, el movimiento es toroidal y un carácter a la vez. Esto significa que el pez (el puntero) puede "envolverse" desde el final de una línea hasta el principio. En> <>, el pez también es capaz de moverse de arriba hacia abajo, de abajo hacia arriba y de derecha a izquierda, en contraste con la forma en que se mueven la mayoría de los punteros. Entonces este patrón de movimiento sería válido:

>>>^  >>>v
   >>>^  v

y terminaría en un bucle infinito (volviendo a la línea superior una vez que pasa infinitamente por la inferior).

El pez se mueve en una cuadrícula de longitud igual al máximo (longitud de la fila) y la altura igual al número de filas.

¿Cómo sabes de qué manera se mueve el pez? Estos comandos cambian el vector de dirección del movimiento (por ejemplo, (-1,0)significa de derecha a izquierda):

Command | Direction Change
---------------------------
   >    | (1,0) (default)
   <    | (-1,0)
   ^    | (0,1)
   v    | (0,-1)
   /    | (x,y) -> (y,x)
   \    | (x,y) -> (-y,-x)
   |    | (x,y) -> (-x,y)
   _    | (x,y) -> (x,-y)
   #    | (x,y) -> (-x,-y)
   ;    | (0,0)

Como se señaló, el pez comienza a moverse de izquierda a derecha, es decir, con el vector de dirección (1,0). El pez comienza a analizar los comandos comenzando con el primer comando que ve y cambia su dirección si un comando coincide con uno de los cambiadores de dirección mencionados anteriormente.

El pez deja de moverse cuando ve a ;y finaliza el programa.

Entrada

La entrada será un programa válido (por ejemplo, no de bucle infinito) dado a través de STDIN. También puede leer un archivo si lo desea. Las líneas de cada programa no serán necesariamente de la misma longitud.

La entrada se da como una cadena, con nuevas líneas que separan cada línea en el programa.

Los programas no se repetirán, lo que también significa que siempre terminarán con a ;.

Salida

La salida será el programa linealizado. Es decir, debe devolver todos los caracteres (incluidos los cambiadores de dirección) que el pez vería si ejecutara el programa "normalmente". Estos son todos los personajes en su camino hacia el ;.

Si la entrada tiene líneas de longitud desigual y el pez termina moviéndose a lo largo de una línea más corta que la longitud de la línea más larga, debe tratar eso como si el pez se moviera sobre un espacio (ver casos de prueba).

Aquellos familiarizados con> <> sabrán que los cambiadores de dirección no son la única forma de hacer movimiento en él, sino que, por simplicidad, tratan la entrada como si fueran la única forma de afectar el movimiento.

Reglas

  1. Se aplican lagunas estándar
  2. Puede escribir un programa completo o una función
  3. La entrada se proporciona a través de STDIN o un archivo como una cadena que contiene las líneas del programa separadas por líneas nuevas ( \n)
    • Puede tomar la entrada de manera diferente, dentro de lo razonable (no dude en preguntarme si tiene un tipo específico de entrada en mente). No puede rellenar la entrada con espacios para que las longitudes de línea coincidan.
    • Consulte esta meta publicación con respecto a la entrada flexible. Tal como están las publicaciones, el consenso general debe ser lo más flexible posible dentro de lo razonable.
  4. La salida es una sola cadena a través de STDOUT o devuelta por la función (dependiendo de lo que elija hacer, consulte la Regla 2)

Casos de prueba

v     >v
>abcv//;
gfed<^ih

v>abcv<defghi^//>v;



v     >v
>abcv//;
gfed<^

v>abcv<defg  ^//>v;


abcdef;

abcdef;


abcd|;

abcd|dcba;


abcd#;

abcd#dcba;


abcd\;
    _

abcd\_\dcba;


^;
>abcde/
 ^jihg<

^ >abcde/ <ghij^a;


;

;
col
fuente
2
¿Podemos tomar la entrada como una matriz de cadenas?
Lucas
2
¿Podemos suponer que el primer carácter (el superior izquierdo) no será un punto y coma?
Kritixi Lithos
1
@KritixiLithos buena pregunta, voy a decir que no puedes asumir eso. Agregaré un caso de prueba.
cole
1
@Luke puede tomar la entrada como una matriz de cadenas si es muy difícil o imposible operar en el formato de entrada (cadena con líneas separadas por nuevas líneas). Ver la Regla añadido ahora 3.
cole
3
Voto obligatorio por razones absurdas
Patrick Roberts

Respuestas:

13

Röda , 405 393 392 391 371 366 361 236 234 232 230 223 200 bytes

F f{L=f()|[#_]|sort|tail
c=""x=0
y=0
X=1
Y=0{l=f[y]l.=[" "]*(L-#l)c=l[x]a=X
[c]
C=indexOf(c,`><v^/\|_#`)X=[1,-1,0,0,-Y,Y,-X,X,-X,X][C]Y=[0,0,1,-1,-a,a,Y,-Y,-Y,Y][C]x+=X
x=x%L
y+=Y
y=y%#f}until[c=";"]}

Pruébalo en línea!

¡Verifique las salidas!

Explicación (obsoleta)

F f{                          /* Declares a function F with parameter f */
                              /* Takes a 2D array of single-char Strings as f */
L =                           /* L contains the value of the length of the longest line*/
    f()                       /* Push the contents each element of f to the stream; this pushes each line*/
        | [#_]                /* Pull a line and push its length to the stream*/
               |sort|tail     /* Sort it and get the last value (the largest one) */
c=""                          /* c contains the value of the current char that is being processed */
x=0; y=0                      /* x and y contain the position of the fish */
X=1; Y=0                      /* X and Y contain the direction of the fish */
{ ... }while [c != ";"]       /* While c is not `;` do: */
l=f[y]                        /*  l is the line (row) the fish is at */
c=" " if [x >= #l]            /*  If x is more than or equal to the line's length, set c to a space (so that we don't need to pad spaces to the array at the beginning)*/
else c = l[x]                 /*  Else set c to the character a position x of l*/
[c]                           /*  Push c to the output stream; ie prints c without a trailing newline*/
a = X                         /*  a preserves the value of X before analysing c */
C = indexOf(c,`><v^/\|_#`)    /*  Simple enough */
X=[1,-1,0,0,-Y,Y,-X,X,-X,X][C]/*  Map each value of C to their respective X-direction in the array */
                              /*  If c cannot be found in `><v^/\|_#` then it will be given the value of -1, or in other words, the -1th element of an array its last element */
Y=[0,0,1,-1,-a,a,Y,-Y,-Y,Y][C]/*  Do the same thing for Y */
x += X                        /*  Change the x-pos by the X-direction */
x = x%L                       /*  Wrap around the right edge */
y += Y                        /*  Do the same for y */
y=y%#f                        /*  But wrap around the bottom instead */
x+=L if[x<0]                  /*  Wrap around the left */
y+=#f if[y<0]                 /*  Wrap around the top */
}

Ediciones

  • ¡10 bytes guardados gracias a @fergusq al usar en %lugar de verificar si x o y está por encima de los límites, lo que allanó el camino para 2 más!
  • Usado en `\`lugar de"\\"
  • Se trasladó c=""a la segunda línea y luego eliminó la nueva línea que le sigue
  • Se movió la conversión de las líneas a una matriz de un solo carácter en los bucles en lugar de al principio (inspirado en la respuesta de Python)
  • Usé la sintaxis de whilellaves de (gracias a @fergusq por detectar eso)
  • Se movió a=Xfuera de las declaraciones if
  • Gracias a @fergusq por encontrar una forma más corta de encontrar la longitud de la línea más larga
  • Se utilizó la sintaxis de matriz en lugar de sentencias if (como la respuesta de Python) para guardar toneladas de bytes
  • Se eliminó el código que rellenaba espacios, en su lugar, los espacios se agregan a medida que> <> se mueve
  • Se corrigió un error, gracias y jugué un personaje gracias a @fergusq
  • Se eliminó el código al +1final indexOfy reestructurado para guardar 2 bytes
  • Ahorré 2 bytes moviendo cosas (gracias a @fergusq nuevamente)
  • Se guardó 1 byte gracias a @fergusq al usar un método diferente de espacios de relleno
  • Se guardó 1 byte usando en until[c=";"]lugar dewhile[c!=";"]
  • Gracias a una pista de @fergusq, eliminé el bucle que rellena los espacios y lo reemplacé por l.=[" "]*L
  • Se guardaron más de 20 bytes al eliminar las declaraciones if al final que envuelven el programa alrededor de los bordes izquierdo y superior
Kritixi Lithos
fuente
Creo que puede guardar unos pocos bytes utilizando en x=((x+X)%#l)lugar de x+=X. Lamentablemente, (-1)%#ltodavía regresa -1.
fergusq
@fergusq Golfed su sugerencia :)
Kritixi Lithos
Se puede utilizar con ydemasiado: y=y%#f.
fergusq
@fergusq Estaba a punto de agregar eso :)
Kritixi Lithos
Pensé más en esto, aquí hay otros dos consejos de golf: usar en keylugar de cmpy usar en {...}while[...]lugar de while[...]do ... done.
fergusq
10

Python 2, 262 243 237 235 234 233 231 221 219 218 217 bytes

Toma entrada como ['<line_1>', '<line_2>', ...]

i=input()
q=max(map(len,i))
i=[k+' '*q for k in i]
x=y=k=0
j=1
o=''
while';'not in o:r=[1,-1,-j,-k,0,0];o+=i[y][x];l='><#\\v^/|_'.find(o[-1]);a=(r+[k,-j,j])[l];k=([k,-k,k,j]+r)[~l];j=a;x=(x+j)%q;y=(y-k)%len(i)
print o

Pruébalo en línea!

-19 bytes gracias a @math_junkie
-6 bytes gracias a @ThisGuy
-2 bytes extrayendo max(map(L,i))a una variable (porque teóricamente se usa dos veces).
-1 byte al reducir la cantidad de veces que i[y][x]aparece.
-1 byte usando '\x00'para no tener que hacer la [1:]parte de o[1:]la salida
-2 bytes usando en \0lugar de \x00
-10 bytes gracias a @KritixiLithos por darme cuenta de que puedo rellenar todo lo que quiero en el lado derecho porque
error adicional será ignorado (sin cambio de byte) porque la variable extraída estaba fuera del bucle
-2 bytes porque ahora solo uso len2 veces, así que la reasignación toma 2 bytes adicionales
-2 byte usando en while';'not in olugar dewhile o[-1]!=';'y usando en o=''lugar de o='\0'. Esto no solo ahorra 2 bytes, sino que también elimina el byte nulo inicial que técnicamente no era realmente válido.

Explicación

i = input()                       # Takes input as an array of strings
q = max(map(len,i))               # Finds the width of the longest line
i = [k + ' ' * q for k in i]      # Makes sure everything is at least that width
x = y = k = 0                     # Set the point to (0, 0). Set the vertical motion to 0
j = 1                             # Set the horizontal motion to 1
o = '\0'                          # Initialize the output to a null byte (this is output as nothing, so it doesn't actually affect output)
while o[-1] != ';':               # While the last character in the output is not ';' (this is why the output needs to be initialized with something, otherwise o[-1] gives an index error)
    r = [1,-1,-j,-k,0,0]          # Some of the vertical and horizontal coordinates correspond in opposite order
    o += i[y][x]                  # Add the current character to the output
    l = '><#\\v^/|_'.find(o[-1])  # Find the index of the current character here (or -1 if it's just a regular character)
    a = (r + [k, -j, j])[l]       # The fancy array contains the horizontal movement for each control character
    k = ([k, -k, k, j] + r)[~l]   # The fancy array contains the vertical movement for each control character. Using ~l to get the right index, because r has the values backwards
    j = a                         # a was a placeholder because otherwise k would not be correct
    x = (x + j) % q               # Adjust the pointer position
    y = (y - k) % len(i)          # Adjust the pointer position
print o                           # Print the output after the loop is finished
Hiperneutrino
fuente
Puede jugar golf trydesde la finddevolución -1si no se encuentra: TIO
adicto a las matemáticas
@math_junkie Oh, bien, gracias!
HyperNeutrino
Puede asignar lena una variable, por ejemplo, Lpara guardar 3 bytes y otros 4 cambiando la asignación multilínea a 01 línea x=y=k=0.
caird coinheringaahing
@ThisGuy Gracias!
HyperNeutrino
2
@Cole En mi golf sugerido, agregué j y k al final de cada matriz. Esto es para mantener la dirección
drogadicto de matemáticas
5

Rubí, 274 200 187 183

Afeitó unos pocos caracteres más al soltar la matriz de impulso, d .

Estoy muy orgulloso de este. ¡Esto fue divertido! Toma una serie de cadenas y devuelve la cadena adecuada.

->a{o,x,y='',-1,0
b,m=1,0
(o+=n=a[y=(y+m)%a.size][x=(x+b)%(a.map &:size).max]||' '
b,m=([1]+[0,-1,0]*2+[1,-m]+[-b,m,b]*2+[-m,-b,-m,b,m])[2*('><^v/\\|_#'.index(n)||9),2])until o[?;]
o}

Comentó a continuación.

->a{
    o,x,y='',-1,0  # o is the output string, x and y are the positions in the array
    b,m=1,0          # b and m are the direction of momentum
    until o[?;] # until o contains a semicolon
        w=(a.map &:size).max # w is the max width of the arrays
        h=a.size    # h is the height of arrays
        x=x+b % w   # increment cursor position
        y=y+m % h
        o+=n=a[y][x]||' ' # add the new char (or " ") to o
        ix=2*('><^v/\\|_#'.index(n)||9) # find the index new char in the string
        b,m=([1]+[0,-1,0]*2+[1,-m]+[-b,m,b]*2+[-m,-b,-m,b,m])[ix,2] # set momentum to its new value
    end
    o # return output string
}
No es que Charles
fuente
1

PHP 7, 291260 bytes

for($m=max(array_map(strlen,$z=explode("
",$argv[1]))),$y=0,$r=count($z)-$v=1;';'!=$c;[$v,$w]=[[$v,1,-1,0,0,-$w,$w,-$v,$v,-$v][$o=strpos(' ><^v/\|_#',$c)],[$w,0,0,-1,1,-$v,$v,$w,-$w,-$w][$o]],$x+=$m+$v,$x%=$m,$y=0<=($y+=$w)?$r<$y?:$y:$r)echo$c=$z[$y][$x]??' ';
chocochaos
fuente
Cuento 291 bytes / caracteres.
HyperNeutrino
Tienes razón, no puedo contar aparentemente = P
chocochaos
Ja, no te preocupes, yo también hice eso.
HyperNeutrino
Encontré algunas cosas al golf, reduciéndolo en un 25% a 218 bytes. No probado, pero definitivamente vale la pena echarle un vistazo .
Titus
2
una falla en uno de mis juegos de golf y seis bytes más de golf: lista de golf actualizada .
Titus
1

JavaScript, 242 236 235 231 220 bytes

a=>{n=a.length;m=x=y=p=0;a.map(g=>m=(w=g.length)<m?m:w);q=1,o="";while((t=a[y][x]||" ")!=";")o+=t,h=q,q=[q,1,0,p,-q][(s=">v\\| <^/_#".indexOf(t)+1)%5]*(r=s>5?-1:1),p=[p,0,1,h,p][s%5]*r,x=(x+q+m)%m,y=(y+p+n)%n;return o+t}

Pruébalo en línea!

fəˈnɛtɪk
fuente
puede guardar 13 caracteres si toma la cadena como una matriz. Las especificaciones fueron cambiadas.
No es que Charles