El reto
El código más corto por recuento de caracteres para ingresar una representación 2D de una placa y generar 'verdadero' o 'falso' de acuerdo con la entrada .
El tablero está hecho de 4 tipos de fichas:
# - A solid wall
x - The target the laser has to hit
/ or \ - Mirrors pointing to a direction (depends on laser direction)
v, ^, > or < - The laser pointing to a direction (down, up, right and left respectively)
Solo hay un láser y un solo objetivo . Las paredes deben formar un rectángulo sólido de cualquier tamaño, donde el láser y el objetivo se colocan dentro. Las paredes dentro de la 'habitación' son posibles.
El rayo láser dispara y viaja desde su origen a la dirección en la que apunta. Si un rayo láser golpea la pared, se detiene. Si un rayo láser golpea un espejo, rebota 90 grados en la dirección que apunta el espejo. Los espejos tienen dos lados, lo que significa que ambos lados son 'reflectantes' y pueden hacer rebotar un rayo de dos maneras. Si un rayo láser golpea el láser ( ^v><
), se trata como una pared (el rayo láser destruye el proyector y, por lo tanto, nunca golpea el objetivo).
Casos de prueba
Entrada: ########## # / \ # # # # \ X# #> / # ########## Salida: cierto Entrada: ########## # vx # # / # # / # # \ # ########## Salida: falso Entrada: ############## # # # #> # # # # # # # X # # # # ############## Salida: falso Entrada: ########## # / \ / \ / \ # # \\ // \\\ # # // \ / \ / \\ # # \ / \ / \ / x ^ # ########## Salida: cierto
El recuento de código incluye entrada / salida (es decir, programa completo).
fuente
Respuestas:
Perl,
166160 caracteresPerl,
251248246222214208203201193190180176173170166 -> 160 caracteres.Solution tuvo 166 golpes cuando terminó este concurso, pero A. Rex ha encontrado un par de maneras de eliminar 6 personajes más:
La primera línea carga la entrada en
%t
una tabla del tablero donde$t{99*i+j}
se encuentra el carácter en la fila i , columna j . Luego,busca en los elementos
%t
un carácter que coincida con> ^ <
ov
, y simultáneamente establece$d
un valor entre 0 y 3 que indica la dirección inicial del rayo láser.Al comienzo de cada iteración en el bucle principal, actualizamos
$d
si el haz está actualmente en un espejo. XOR'ing by 3 da el comportamiento correcto para un\
espejo y XOR'ing by 1 da el comportamiento correcto para un/
espejo.A continuación, la posición actual
$r
se actualiza según la dirección actual.Asignamos el carácter en la posición actual
$_
para hacer un uso conveniente de los operadores de coincidencia.Continúe si estamos en un espacio en blanco o un personaje espejo. De lo contrario, terminamos
true
si estamos en el destino ($_ =~ /x/
) y de lofalse
contrario.Limitación: puede no funcionar en problemas con más de 99 columnas. Esta limitación podría eliminarse a expensas de 3 caracteres más,
fuente
s!.!$t{$s++}=$&!ge,$s=$r+=99for<>;
, cambie%d=split//,.." to
% d = .. = ~ /./ g, and change
grep {..}% t` agrep..,%t
Perl, 177 Personajes
El primer salto de línea se puede eliminar; Los otros dos son obligatorios.
Explicación:
Si una viga que se mueve hacia la derecha se encuentra con un {espacio vacío, espejo en ángulo hacia arriba, espejo en ángulo hacia abajo} se convierte en una {viga en movimiento hacia la derecha, viga en movimiento hacia arriba, viga en movimiento hacia abajo}. Inicialice
$/
en el camino - afortunadamente "6" no es un carácter de entrada válido.Lea la pizarra en
$_
.$s
es el símbolo de lo que sea que esté sentado el rayo encima. Dado que el emisor láser debe tratarse como una pared, para empezar, configúrelo como una pared.Si el rayo láser apunta hacia cualquier lado, excepto a la derecha, gire su símbolo y luego gire toda la placa en su lugar (también girando los símbolos de los espejos). Es una rotación a la izquierda de 90 grados, lograda efectivamente invirtiendo las filas mientras se transponen filas y columnas, en un poco diabólico
s///e
con efectos secundarios. En el código de golf, el tr está escrito en la formay'''
que me permite omitir una barra diagonal inversa.Termine con el mensaje correcto si golpeamos el objetivo o una pared.
Si hay un espacio vacío frente al láser, avance. Si hay un espejo frente al láser, avance y gire el haz. En cualquier caso, vuelva a colocar el "símbolo guardado" en la ubicación de la viga anterior y coloque lo que acabamos de sobrescribir en el símbolo guardado.
Repita hasta la terminación.
{...;redo}
es dos caracteres menos quefor(;;){...}
y tres menos quewhile(1){...}
.fuente
C89 (209 caracteres)
Explicación
Esta monstruosidad probablemente será difícil de seguir si no comprende C. Solo una advertencia.
Esta pequeña macro verifica si el carácter actual (
*p
) es igual a lo quea
esté en forma de carácter (*#a
). Si son iguales, establezca el vector de movimiento enb
(m=b
), marque este carácter como un muro (*p=1
) y establezca el punto de partida en la ubicación actual (q=p
). Esta macro incluye la parte "más".Declarar algunas variables. *
q
es la ubicación actual de la luz. *G
es el tablero de juego como una matriz 1D. *p
es la ubicación de lectura actual al rellenarG
. *w
es el ancho del tablero.Obvia
main
.m
es una variable que almacena el vector de movimiento. (Es un parámetromain
como una optimización).Recorre todos los personajes, rellenando
G
conp
. SaltarG[0]
como una optimización (no es necesario desperdiciar un personaje escribiendop
nuevamente en la tercera parte de lafor
).Utilice la macro antes mencionada para definir el lazer, si es posible.
-1
y1
corresponden a izquierda y derecha, respectivamente,-w
yw
arriba y abajo.Si el carácter actual es un marcador de fin de línea (ASCII 10), establezca el ancho si aún no se ha establecido. El omitido
G[0]
nos permite escribir enw=p-G
lugar dew=p-G+1
. Además, esto termina la?:
cadena de laM
's.Mueve la luz por el vector de movimiento.
Refleja el vector de movimiento.
Si esto es un muro o
x
, salga con el mensaje apropiado (m=0
termina el ciclo). De lo contrario, no haga nada (noop;m=m
)fuente
g.c:3: declaration expected
:(puts
de la declaración ayudó, pero no fue suficiente para reducirla a 170. Sin embargo, 209 es bastante bueno, así que creo que lo dejaré así. Gracias por su ayuda chicos. Realmente lo aprecio. =] (¡Cualquier cosa para destronar a esas brujas de Perl!)Apuesto a que la gente ha estado esperando este por MUCHO tiempo. (¿Qué quieres decir con que el desafío ha terminado y a nadie le importa más?)
He aquí ... aquí presento una solución en
Befunge-93!
Pesa la friolera de 973 caracteres (o 688 si eres lo suficientemente caritativo como para ignorar los espacios en blanco, que solo se usa para formatear y no hace nada en el código real).
Advertencia : escribí mi propio intérprete Befunge-93 en Perl hace poco tiempo, y desafortunadamente esto es todo lo que realmente he tenido tiempo para probarlo. Tengo una confianza razonable en su corrección en general, pero podría tener una limitación extraña con respecto a EOF: dado que el
<>
operador de Perl devuelve undef al final del archivo, esto se procesa como un 0 en el contexto numérico. Para implementaciones basadas en C donde EOF tiene un valor diferente (digamos -1), este código podría no funcionar.Explicación
Si no está familiarizado con la sintaxis y operación de Befunge, marque aquí .
Befunge es un lenguaje basado en la pila, pero hay comandos que le permiten a uno escribir caracteres en el código Befunge. Aprovecho eso en dos lugares. Primero, copié toda la entrada en la placa Befunge, pero ubiqué un par de líneas debajo del código escrito real. (Por supuesto, esto nunca es realmente visible cuando se ejecuta el código).
El otro lugar está cerca de la esquina superior izquierda:
En este caso, el área que he resaltado arriba es donde guardo un par de coordenadas. La primera columna en la fila central es donde guardo la coordenada x para la "posición del cursor" actual; la segunda columna es donde guardo la coordenada y; las siguientes dos columnas son para almacenar las coordenadas x e y de la fuente del rayo láser cuando se encuentra; y la columna final (con el carácter 'a' en ella) finalmente se sobrescribe para contener la dirección del haz actual, que obviamente cambia a medida que se rastrea la trayectoria del haz.
El programa comienza colocando (0,27) como la posición inicial del cursor. Luego, la entrada se lee un carácter a la vez y se coloca en la posición del cursor; las nuevas líneas simplemente causan que la coordenada y aumente y la coordenada x regrese a 0, al igual que un retorno de carro real. Eventualmente, el intérprete lee undef y ese valor de 0 caracteres se usa para señalar el final de la entrada y pasar a los pasos de iteración del láser. Cuando se lee el carácter láser [<> ^ v], eso también se copia en el repositorio de memoria (sobre el carácter 'a') y sus coordenadas se copian en las columnas a la izquierda.
El resultado final de todo esto es que todo el archivo se copia básicamente en el código Befunge, un poco por debajo del código real atravesado.
Posteriormente, la ubicación del haz se copia nuevamente en las ubicaciones del cursor y se realiza la siguiente iteración:
Si hay suficiente demanda, intentaré señalar exactamente en qué parte del código se logra todo esto.
fuente
F #, 36 líneas, muy legible
Ok, solo para obtener una respuesta:
Muestras:
fuente
Golfscript - 83 caracteres (mashup mío y extraño)
La nueva línea está aquí para envolver
Golfscript - 107 caracteres
La nueva línea solo está ahí para mayor claridad.
Cómo funciona.
La primera línea resuelve la ubicación inicial y la dirección.
La segunda línea da un giro cuando el láser golpea un espejo.
fuente
353 caracteres en Ruby:314277 caracteres ahora!OK, 256 caracteres en Ruby y ahora he terminado. Bonito número redondo para detenerse. :)247 caracteres. No puedo parar223203201 caracteres en RubyCon espacios en blanco:
Ligeramente refactorizado:
fuente
ch
aC
cualquier otra letra de char para guardar 2 caracteres!i++
(en lugar dei+=1
)?Pitón
294277253240232 caracteres incluyendo nuevas líneas:(el primer carácter en las líneas 4 y 5 es una pestaña, no espacios)
Había olvidado que Python incluso tenía puntos y comas opcionales.
Cómo funciona
La idea clave detrás de este código es usar números complejos para representar posiciones y direcciones. Las filas son el eje imaginario, aumentando hacia abajo. Las columnas son el eje real, aumentando a la derecha.
l='>v<^';
Una lista de los símbolos láser. El orden se elige de modo que el índice de un carácter de dirección láser corresponda con una potencia de sqrt (-1)x={'/':'^<v>','\\':'v>^<',' ':l};
Una tabla de transformación que determina cómo cambia la dirección cuando la viga sale de diferentes mosaicos. El mosaico es la clave, y las nuevas direcciones son los valores.b=[1];
Sostiene el tablero. El primer elemento es 1 (se evalúa como verdadero) para que el ciclo while se ejecute al menos una vez.r=p=0
r
es el número de fila actual de la entrada,p
es la posición actual del rayo láser.while b[-1]:
dejar de cargar datos de la placa cuando raw_input devuelve una cadena vacíab+=[raw_input()];r+=1
agregue la siguiente línea de entrada al tablero e incremente el contador de filasfor g in l:
adivina cada dirección láser a su vezc=b[r].find(g)
configure la columna en la ubicación del láser o -1 si no está en la línea (o apunta en una dirección diferente)if-1<c:p=c+1j*r;d=g
Si encontramos un láser, establezca la posiciónp
y dirección actualesd
.d
es uno de los caracteres enl
Después de cargar la placa
b
, la posiciónp
y dirección actualesd
se han establecido en las de la fuente láser.while' '<d:
el espacio tiene un valor ASCII más bajo que cualquiera de los símbolos de dirección, por lo que lo usamos como un indicador de detención.z=l.find(d);
índice de la dirección actual char en lal
cadena.z
se utiliza más adelante para determinar la nueva dirección del haz utilizando lax
tabla y para incrementar la posición.p+=1j**z;
incrementar la posición usando una potencia de i. Por ejemplo,l.find('<')==2
-> i ^ 2 = -1, que se movería a la izquierda una columna.c=b[int(p.imag)][int(p.real)];
lee el personaje en la posición actuald=x.get(c,' '*4)[z]
Busque la nueva dirección de la viga en la tabla de transformación. Si el carácter actual no existe en la tabla, configúrelod
en espacio.print'#'<c
imprima falso si nos detenemos en otra cosa que no sea el objetivo.fuente
p+=1j**z
: Eso es dulce.Este
esfue un puerto directo de la solución de Brian para C # 3, menos las interacciones de la consola. Esta no es una entrada en el desafío, ya que no es un programa completo, me preguntaba cómo algunas de las construcciones de F # que utilizó podrían estar representadas en C #.Editar: después de experimentar un poco, el siguiente código de búsqueda bastante detallado:
ha sido reemplazado por un código LINQ to Objects mucho más compacto:
fuente
F #, 255 caracteres (¡y aún bastante legible!):
Ok, después de una noche de descanso, mejoré mucho esto:
Hablemos de ello línea por línea.
Primero, sorba toda la entrada en una gran matriz unidimensional (las matrices 2D pueden ser malas para el golf de código; solo use una matriz 1D y sume / reste el ancho de una línea al índice para subir / bajar una línea).
Luego calculamos 'w', el ancho de una línea de entrada, y 'c', la posición inicial, indexando en nuestra matriz.
Ahora definamos la función 'siguiente' 'n', que toma una posición actual 'c' y una dirección 'd' que es 0,1,2,3 para arriba, izquierda, derecha, abajo.
El índice-épsilon 'e' y el qué-nueva-dirección-si-golpeamos-una-barra 's' son calculados por una tabla. Por ejemplo, si la dirección actual 'd' es 0 (arriba), entonces el primer elemento de la tabla dice "-w, 2", lo que significa que disminuimos el índice por w, y si tocamos una barra oblicua, la nueva dirección es 2 (Derecha).
Ahora volvemos a la siguiente función 'n' con (1) el siguiente índice ("c + e" - actual más épsilon), y (2) la nueva dirección, que calculamos mirando hacia adelante para ver qué hay en la matriz en esa próxima celda. Si el lookahead char es una barra oblicua, la nueva dirección es 's'. Si se trata de una barra diagonal inversa, la nueva dirección es de 3 s (nuestra elección de codificación 0123 hace que esto funcione). Si es un espacio, seguimos yendo en la misma dirección 'd'. Y si se trata de cualquier otro personaje 'c', entonces el juego termina, imprimiendo 'verdadero' si el carácter era 'x' y falso de lo contrario.
Para comenzar, llamamos a la función recursiva 'n' con la posición inicial 'c' y la dirección de inicio (que realiza la codificación inicial de la dirección en 0123).
Creo que probablemente todavía pueda eliminar algunos caracteres más, pero estoy bastante satisfecho con esto de esta manera (y 255 es un buen número).
fuente
Con un peso de 18203 caracteres, hay una solución de Python que puede:
Todavía necesita ser arreglado un poco y no sé si la física 2D dicta que el rayo no puede cruzarse solo ...
Un script bash para mostrar el informe de errores de color:
Las pruebas unitarias utilizadas en el desarrollo:
fuente
Ruby, 176 caracteres
Utilicé una máquina de estado simple (como la mayoría de los carteles), nada lujoso. Seguí reduciéndolo usando cada truco que se me ocurría. El XOR bit a bit utilizado para cambiar la dirección (almacenado como un entero en la variable
c
) fue una gran mejora con respecto a los condicionales que tenía en versiones anteriores.Sospecho que el código se incrementa
x
yy
podría acortarse. Aquí está la sección del código que hace el incremento:Editar : pude acortar un poco lo anterior:
La dirección actual del láser
c
se almacena de la siguiente manera:El código se basa en este hecho para aumentar
x
yy
en la cantidad correcta (0, 1 o -1). Intenté reorganizar qué números se asignan a cada dirección, buscando un arreglo que me permitiera hacer una manipulación bit a bit para incrementar los valores, porque tengo la sensación de que sería más corto que la versión aritmética.fuente
C # 3.0
259 caracteres
Ligeramente más legible:
El principal desperdicio de caracteres parece estar en encontrar el ancho del mapa y la posición de la fuente láser. ¿Alguna idea de cómo acortar esto?
fuente
while(1)
C + ASCII, 197 caracteres:
Esta solución C asume un conjunto de caracteres ASCII, lo que nos permite utilizar el truco del espejo XOR. También es increíblemente frágil: todas las líneas de entrada deben tener la misma longitud, por ejemplo.
Se rompe por debajo de la marca de 200 caracteres, pero ¡dang, todavía no ha superado esas soluciones Perl!
fuente
Golfscript (83 caracteres)
Hola gnibbler!
fuente
Python - 152
Lee la entrada de un archivo llamado "L"
Para leer de stdin, reemplace la primera línea con esto
Si necesita minúsculas verdadero / falso, cambie la última línea a
fuente
True
atrue
yFalse
afalse
? ;-)D<5
" a "imprimir D <5"? ¿O hay algo que me falta?JavaScript: 265 caracteres
Actualización IV : las probabilidades son que esta será la última ronda de actualizaciones, lograron salvar un par de caracteres más al cambiar a un bucle do-while y reescribir la ecuación de movimiento.
Actualización III : gracias a la sugerencia de Strager con respecto a eliminar Math.abs () y colocar las variables en el espacio de nombre global, que junto con una cierta reorganización de las asignaciones de variables redujo el código a 282 caracteres.
Actualización II : algunas actualizaciones más del código para eliminar el uso de! = -1, así como un mejor uso de variables para operaciones más largas.
Actualización : cuando terminó e hizo algunos cambios al crear una referencia a la función indexOf (¡gracias LiraNuna!) Y eliminar paréntesis que no eran necesarios.
Esta es la primera vez que hago un código de golf, así que no estoy seguro de cuánto mejor podría ser, cualquier comentario es apreciado.
Versión completamente minimizada:
Versión original con comentarios:
Página web para probar con:
fuente
index != -1
conindex > 0
por favor! (Esperemos que nadie ponga el lazer en la esquina superior izquierda para0
que no se devuelva. =]) Puede encadenar lasvar
declaraciones o deshacerse de ellas por completo (colocando las variables en el espacio de nombres global). Creo queMath.abs(m)==1
puede ser reemplazado porm==-1|m==1
. Puedemovement = ...; location += movement
ser optimizado paralocation += movement =
?function(a){return g.indexOf(a)}
se puede reemplazar confunction(a)g.indexOf(a)
versiones recientes de JavaScript.Casa de los espejos
No es una entrada real al desafío, pero escribí un juego basado en este concepto (no hace mucho tiempo).
Está escrito en Scala, de código abierto y disponible aquí :
Hace un poquito más; trata de colores y varios tipos de espejos y dispositivos, pero la versión 0.00001 hizo exactamente lo que este desafío pide. Sin embargo, he perdido esa versión y nunca fue optimizada para el recuento de caracteres de todos modos.
fuente
c (K&R) 339 caracteres necesarios después de más sugerencias de un extraño.
El físico en mí notó que las operaciones de propagación y reflexión son invariantes de inversión de tiempo, por lo que esta versión arroja rayos desde el objetivo y comprueba si llegan al emisor láser.
El resto de la implementación es muy sencillo y se toma más o menos exactamente de mi esfuerzo anterior y avanzado.
Comprimido:
Sin comprimir (ish):
No hay validación de entrada, y una entrada incorrecta puede enviarlo a un bucle infinito. Funciona correctamente con una entrada no mayor de 99 por 99. Requiere un compilador que vinculará la biblioteca estándar sin incluir ninguno de los encabezados. Y creo que ya terminé , extraño me ha superado considerablemente, incluso con su ayuda.
Espero que alguien demuestre una forma más sutil de realizar la tarea. No hay nada de malo en esto, pero no es magia profunda.
fuente
=0
en los globales, ya que se inicializan a 0 de forma predeterminada. Reemplace las constantes de caracteres con su equivalente en decimal. Use en>0
lugar de!=EOF
para verificar contra EOF (y\0
). Probablemente pueda#define
eliminar parte del códigocase
como hice conif
's. No es necesario el extra\n
en elputs
comoputs
debe imprimir una nueva línea de todos modos.for(;;)
es más corto quewhile(1)
. Espero que esto ayude. =]"There is no input validation"
- No debería haber ninguno. Para facilitar a los golfistas, se supone que la entrada siempre está "limpia" a menos que se especifique lo contrario.Ruby - 146 caracteres
fuente
PostScript , 359 bytes
Primer intento, mucho margen de mejora ...
fuente
Haskell,
395391383361339 caracteres (optimizado)Todavía usa una máquina de estado genérica, en lugar de algo inteligente:
Una versión legible:
fuente
Creo en Code Reuse, usaría uno de sus códigos como API :).
32 caracteres \ o / ... wohoooo
fuente
C ++: 388 caracteres
( 318 sin encabezados)
Cómo funciona:
Primero, se leen todas las líneas, luego se encuentra el láser. Lo siguiente evaluará
0
mientras no se haya encontrado ninguna flecha láser todavía, y al mismo tiempo asigne ax
la posición horizontal.Luego miramos en qué dirección encontramos y lo almacenamos
i
. Los valores pares dei
son superior / izquierda ("decreciente") y los valores impares son inferior / derecha ("creciente"). Según esa noción, se establecend
("dirección") yr
("orientación"). Indexamos la matriz de punterosz
con orientación y agregamos la dirección al entero que obtenemos. La dirección cambia solo si golpeamos una barra diagonal, mientras que permanece igual cuando golpeamos una barra diagonal inversa. Por supuesto, cuando golpeamos un espejo, siempre cambiamos de orientación (r = !r
).fuente
Groovy @ 279 personajes
fuente
C#
1020 caracteres.1088 caracteres (entrada agregada desde la consola).925 caracteres (variables refactorizadas).875 caracteres (se eliminó el inicializador de diccionario redundante; se cambió a Binario y operadores)
Hizo un punto para no mirar a nadie más antes de publicar. Estoy seguro de que podría ser LINQ'd un poco. Y todo el método FindLaser en la versión legible me parece muy sospechoso. Pero funciona y es tarde :)
Tenga en cuenta que la clase legible incluye un método adicional que imprime la Arena actual a medida que el láser se mueve.
Versión legible (no es la versión final de golf, pero la misma premisa):
fuente
Perl 219
Mi versión Perl es
392342 caracteres de longitud (que tenía que manejar el caso del haz de golpear el láser):Actualización , gracias Hobbs por recordarme
tr//
, ahora es 250 caracteres:Actualización , eliminación de la
m
enm//
, el cambio de los doswhile
bucles traídas algunos ahorros; ahora solo se requiere un espacio.(
L:it;goto L
tiene la misma longitud quedo{it;redo}
):Me afeité un poco, pero
apenascompite con algunos de estos, aunque tarde.Se ve un poco mejor como:
Bueno ... Sinceramente, esto debería explicarse por sí mismo si comprende que
@b
hay una matriz de matrices de caracteres en cada línea, y puede leer latr
expresión regular simple y las declaraciones.fuente
$_=$s;tr/^v<>/<>^v/
y$_=$s;tr/v^<>/<>^v/
respectivamente. Además, no es necesario elm
enm//
.$_=$s;tr/v^></<>^v/;
if m/.../
que podrían estarif/.../
guardando dos caracteres por pop.y///
lugar detr///
guardar dos caracteres.F # - 454 (o por ahí)
Llegué un poco tarde al juego, pero no puedo resistirme a publicar mi segundo intento.
Actualizar modificada ligeramente. Ahora se detiene correctamente si se golpea el transmisor. Pellizcó la idea de Brian para IndexOfAny (lástima que la línea sea tan detallada). En realidad no he logrado resolver cómo hacer que ReadToEnd regrese de la consola, así que estoy confiando un poco en eso ...
Estoy satisfecho con esta respuesta, como si fuera bastante corta, todavía es bastante legible.
fuente