Tome una cuadrícula bidimensional y dibuje una serie de segmentos de línea en ella para representar espejos. Ahora elija un punto para colocar un láser teórico y un ángulo para definir la dirección a la que apunta. La pregunta es: si sigue la trayectoria del rayo láser durante una distancia específica, ¿en qué punto de coordenadas se encuentra?
Ejemplo:
En esta imagen, L
es la ubicación del láser, t
es Es ángulo (medido desde el eje X positivo), M1
, M2
, y M3
son todos los espejos de segmentos de línea, y E
es el punto en la trayectoria del rayo láser después de D = d1 + d2 + d3 + d4
unidades, a partir de L
.
Gol
Escribir el programa más corto (en bytes) que los resultados E
dados L
, t
, D
, y una lista de espejos.
(Use http://mothereff.in/byte-counter para contar bytes).
Formato de entrada
La entrada vendrá de stdin en el formato:
Lx Ly t D M1x1 M1y1 M1x2 M1y2 M2x1 M2y1 M2x2 M2y2 ...
- Todos los valores serán los puntos que coinciden con la expresión regular flotando:
[-+]?[0-9]*\.?[0-9]+
. - Siempre hay exactamente un espacio entre cada número.
- Requerir cotizaciones alrededor de la entrada está permitido.
t
está en grados, pero no necesariamente en el[0, 360)
rango. (Si lo prefiere, puede usar radianes en su lugar, solo dígalo en su respuesta).D
puede ser negativo, efectivamente girando el láser 180 grados.D
también puede ser 0.- Puede haber arbitrariamente muchos espejos (incluido ninguno).
- El orden de los espejos no debería importar.
- Puede suponer que la entrada vendrá en múltiplos de 4 números. por ejemplo,
Lx Ly t
oLx Ly t D M1x1
no son válidos y no serán probados. Ninguna entrada también es inválida.
El diseño anterior se puede ingresar como:
1 1 430 17 4.8 6.3 6.2 5.3 1.5 4.8 3.5 6 6.3 1.8 7.1 3
(Tenga en cuenta que la imagen se dibujó a mano alzada y estos valores son solo aproximaciones. Los valores de entrada de Martin Büttner
1 1 430 17 4.8 5.3 6.2 4.3 1.5 4.8 3.5 6 6.3 1.8 7.1 3
dará más colisiones aunque no coincidan con el boceto).
Formato de salida
La salida debería ir a stdout en el formato:
Ex Ey
Estos también son flotantes y pueden estar en forma exponencial.
Notas
- Los espejos pueden cruzarse entre sí.
- Ambos lados de los espejos son reflectantes.
- El rayo puede golpear el mismo espejo muchas veces.
- El rayo continúa para siempre.
Casos indefinidos
Puede suponer que los casos donde
- el láser comienza en un segmento de línea espejo
- el rayo láser golpea el punto final de un espejo
- el rayo láser golpea la intersección entre dos espejos
no están definidos y no serán probados. Su programa puede hacer cualquier cosa si esto ocurre, incluso arrojar un error.
Prima
Solo por diversión, otorgaré 200 puntos de recompensa a la presentación más votada que genere una representación gráfica del problema (incluso podría escribir un guión interactivo). No es necesario jugar golf con estos bonos y puede ser indulgente con la forma en que se manejan las entradas y salidas. Son distintos de los envíos de golf reales, pero ambos deben presentarse en la misma respuesta .
Nota: Solo enviar una respuesta extra está bien, simplemente no será la respuesta aceptada. Para ser aceptado, debe seguir exactamente las especificaciones de entrada / salida (por ejemplo, la salida solo involucra Ex Ey
, no imágenes), y ser el más corto.
Respuestas:
Rubí, 327 bytes.
(desplazarse hacia abajo)
Mathematica, respuesta extra
Solo voy por la presentación gráfica en este momento. Podría portar esto a Ruby más tarde y jugarlo si me da la gana.
Puedes llamarlo como
Eso le dará una animación en Mathematica y también exportará un GIF (el que está arriba para esta entrada). He ampliado ligeramente el ejemplo de OP para esto, para que sea un poco más interesante.
Más ejemplos
Un tubo con paredes ligeramente divergentes pero un extremo cerrado:
Un triángulo equilátero y una dirección inicial que es casi paralela a uno de los lados.
Uno mas:
Ruby, respuesta de golf
Esto es básicamente una traducción directa de la solución de Mathematica a Ruby, además de jugar al golf y asegurarse de que cumpla con los criterios de E / S.
fuente
Python 3 (
421C 390C, 366C)Usar
builtin.complex
como vector 2d. Asi quePara vencer a la solución 368C Ruby, he encontrado un método bastante compacto para calcular la reflexión puntual a lo largo de un espejo. Y también usó un poco de álgebra compleja para reducir más personajes. Estos se pueden encontrar fácilmente en el código sin golf.
Aquí está la versión de golf.
Sin golf
Bonificación: HTML, Coffeescript, Ajuste y cálculo en tiempo real
Es decir, arrastra cualquier punto final (o lazer, mirros), luego se procesa la pista. También admite dos tipos de entrada, la descrita en la pregunta y la utilizada por @ Martin Büttner.
La escala también se ajusta automáticamente.
Por ahora no tiene animación. Tal vez lo mejoraré más tarde. Sin embargo, al arrastrar los puntos blancos puede ver otro tipo de animación. Pruébelo en línea aquí mismo, ¡es divertido!
Todo el proyecto se puede encontrar aquí
Actualizar
Aquí presento un caso interesante:
Y el resultado es:
fuente
HTML JavaScript,
10,543,947889Solucioné un error y me aseguré de que el resultado cumpla con la especificación de la pregunta. La página web a continuación tiene la versión de golf y también la versión de bonificación gráfica. También arreglé un error señalado por @Ray que salvó 58 caracteres. (Gracias Ray.) También puedes ejecutar el código de golf en una consola JavaScript. (Ahora estoy usando un láser verde de 2 mW).
Código de golf
Entrada
Salida
Puedes probarlo aquí: http://goo.gl/wKgIKD
Explicación
El código en la página web está comentado. Básicamente calculo la intersección del láser con cada espejo suponiendo que el láser y los espejos son infinitamente largos. Luego verifico si la intersección está dentro de la longitud finita del espejo y el láser. Luego tomo la intersección más cercana, muevo el láser a ese punto y continúo hasta que el láser pierde todos los espejos.
Proyecto muy divertido. Gracias por hacer esta pregunta!
Código legible
fuente
0 0 0.4 100 1 1 1 -1 1 -1 -1 -1 -1 -1 -1 1 -1 1 1 1
.Python - 765
Buen reto Esta es mi solución que obtiene entradas de stdin y salidas a stdout. Usando el ejemplo de @Martin Büttner:
Aquí está el código de golf:
Y aquí está el código no golfista con una figura extra
fuente
sys.argv
no es stdin.Matlab (388)
Trama
Conceptos
Puntos de reflexión
Para calcular los puntos de reflexión, básicamente tenemos que interesect dos líneas rectas. Uno con el punto p0 y el vector v, el otro entre los dos puntos p1, p2. Entonces la ecuación a resolver es (s, t son parámetros): p0 + t v = s p1 + (1-s) * p2.
El parámetro s es entonces una coordenada barcéntrica del espejo, por lo que si 0
Reflejo
La duplicación de v es bastante simple. Supongamos que || v || = || n || = 1 donde n es el vector normal del espejo actual. Luego puede usar la fórmula v: = v-2 ** n donde <,> es el producto escalar.
Validez del paso
Al calcular el espejo 'válido' más cercano, debemos considerar algunos criterios que lo hacen válido. Primero, el punto de intercepción del espejo debe estar entre los dos puntos finales, por lo que debe ser 0
Programa
Ligeramente golfizado (388)
fuente