Code Golf: ¿Cuál es el destino de la nave espacial? [Versión de arte ASCII]

14

Antecedentes

En una galaxia (y posiblemente un universo) muy, muy lejos ... había una nave espacial y un montón de planetas. Un mal funcionamiento a bordo hizo que la nave espacial se quedara sin combustible. ¡Ahora se mueve a una velocidad peligrosamente lenta cerca de un grupo de planetas, del cual debe escapar! ¿Cuál será el destino de la tripulación?

El reto

Usted es el programador principal en el USS StackExchange. Como tal, deseas escribir un simulador que revele si estás o no condenado a estrellarte en un planeta, escaparás del sistema planetario o estarás en órbita para siempre.

La explosión en su nave espacial, sin embargo, significa que había recursos computacionales muy limitados. Su programa debe ser lo más pequeño posible. Además, esto significa que la única forma posible de ingresar simulaciones para ejecutar es a través del arte ASCII.

La simulación

En este cuadrante del multiverso, las leyes de la física se modifican ligeramente para acomodar el arte ASCII. Esto significa que el cosmos se divide en células. El movimiento se describirá en unidades de celdas, y el tiempo estará en unidades de pasos de tiempo.

El barco en sí tiene impulso. Si la nave movió +2 celdas en el eje xy -1 celda en el eje y (abreviado como (2, -1)) en el paso de tiempo anterior, y no hay campo gravitacional, entonces la nave se moverá con el exacto misma velocidad en el siguiente paso de tiempo.

Habrá varios planetas, todos los cuales ejercerán un campo gravitacional en las ocho celdas que lo rodean inmediatamente, lo que afectará la velocidad de la nave y acercará la nave al planeta. Estar justo "al norte" de un planeta dará como resultado un campo que arrastrará la nave una célula hacia el "sur" con una fuerza de (-1,0). Estar justo "al noreste" de un planeta dará como resultado una fuerza que arrastrará la nave una célula hacia el "sur" y una unidad hacia el "oeste" con una fuerza de (-1, -1).

Los campos gravitacionales agregan un vector al impulso de la nave al salir de la celda con la gravedad. Si una nave previamente movió (2, -1) celdas y ahora está en un campo gravitacional de (-1,1), en el siguiente paso de tiempo moverá (1,0) celdas. Si la nave está muy cerca de varios planetas, entonces habrá múltiples vectores para agregar.

Entrada

En STDIN, recibirá una representación de arte ASCII del sistema planetario que mostrará las coordenadas de los planetas y la velocidad actual de su nave. Habrá varios planetas en forma de signos @, mientras que habrá una nave espacial en forma de signo av ^ <>. La elección del símbolo para el barco indica la velocidad actual del barco (antes de que se haya agregado la gravedad). Por ejemplo, a <significa la velocidad de una celda hacia el oeste, mientras que a ^ significa la velocidad de una celda hacia el norte. Todo el espacio vacío consistirá en puntos, que rellenan cada línea para que tenga el mismo ancho. Una línea en blanco representa el final de la entrada. Aquí hay un ejemplo de una entrada:

.................
...@[email protected]..
......@..@..@@...
..@..............
.......@..@......
.................

Salida

La salida será una sola palabra en STDOUT, que indicará si la nave escapará de la gravedad, chocará contra un planeta o girará para siempre.

Escapar de la gravedad se define como la nave que se aleja del mapa. Si el barco se escapa, entonces su programa debe imprimir la palabra "escapar".

El aterrizaje forzoso es cuando una nave pasa directamente sobre un planeta o termina en la misma celda durante un paso de tiempo. Tenga en cuenta que no es suficiente calcular simplemente dónde está el barco cada vez que se realiza un paso. Una nave que se mueve a una velocidad de (5,5) se estrellará contra un planeta ubicado en (1,1) a pesar de que el cálculo directo significará que nunca visitará esa celda. Sin embargo, una nave con una velocidad de (5,6) no chocará contra el planeta. Si su nave espacial aterriza, su programa debe imprimir la palabra "crash".

La órbita puede ser la más difícil de detectar. La órbita ocurre cada vez que la nave espacial visita la misma celda dos veces y con la misma velocidad. Si el barco orbita, debe imprimir la palabra "órbita".

Aquí está la salida para el ejemplo anterior:

escape

Explicación

Aquí hay un mapa que muestra dónde viajó la nave espacial en cada paso de tiempo en el ejemplo anterior:

   ^
.................
...@[email protected]..
....^.@..@..@@...
..@..<.<<<.<.v...
.......@..@......
.................

Se dirigió hacia el sur, giró hacia el oeste, viajó por un corredor, giró hacia el norte y escapó por poco entre planetas con una alta velocidad, todo debido a la gravedad.


Más casos para examen

...
^@.
...
orbit
...........
.>@.@......
.@......@..
....@......
crash (it crashes into the easternmost planet)
...
.@.
.v.
crash (momentum can't overcome gravity)
........
..@.....
..<.....
...@....
........
orbit (it gets trapped in a gravity well between two planets)

Reglas, Regulaciones y Notas

Este es el código de golf. Se aplican las reglas estándar del código de golf. Sus programas deben estar escritos en ASCII imprimible. No se le permite acceder a ningún tipo de base de datos externa.

Fin de transmisión

PhiNotPi
fuente
Parece que hay un error tipográfico en la línea justo encima de la sección ENTRADA ... ¿Supongo que te refieres a planeta? :-)
Gaffi
En realidad, ese párrafo parcial completo necesitaba ser eliminado, la información se repite en la sección de salida.
PhiNotPi
1
Me gustaría esto mejor con una física ligeramente menos alterada ... este sitio podría tener más problemas que también involucran un poco de aritmética de punto flotante costosa.
dejó de girar en contra del reloj el
1
@leftaroundabout Ese puede ser mi próximo desafío.
PhiNotPi
¿Qué tan cerca de un planeta debe estar para chocar contra él?
Peter Taylor

Respuestas:

6

C # 991 984

struct P{public P(int x,int y){X=x;Y=y;}public int X,Y;}
class O:Exception{}
class C:O{}
List<P>p=new List<P>();
List<string>h=new List<string>();
P r,v,u;
void S(){
var i=0;
for(var l=Console.ReadLine();l!="";l=Console.ReadLine())
{u.X=l.Select((c,j)=>
{if(c=='@')p.Add(new P(j,i));else if(c!='.')
{r=new P(j,i);v=(c=='v'?new P(0,1):c=='<'?new P(-1,0):c=='^'?new P(0,-1):new P(1,0));}
return u;}).Count();i++;}
u.Y=i;
var x=new Action<string>(Console.WriteLine);
try{
while(true){
p.ForEach(q=>{var a=q.X-r.X;var b=q.Y-r.Y;
if(a<2&&a>-2&&b<2&&b>-2){v.X+=a;v.Y+=b;}});
var c=string.Join(".",r.X,r.Y,v.X,v.Y);
if(h.Contains(c))throw new O();
h.Add(c);
var z=new P(r.X,r.Y);var k=new[]{v.X,v.Y};var m=k.Min();var M=k.Max();
for(var j=1;j<=M;j++)
if((j*m)%M==0){
if(p.Contains(new P(z.X+(v.X==M?j:j*m/M),z.Y+(v.Y==M?j:j*m/M))))throw new C();}
r.X+=v.X;r.Y+=v.Y;
if(r.X<0||r.X>=u.X||r.Y<0||r.Y>=u.Y)throw new Exception();}}
catch(C){x("crush");}
catch(O){x("orbit");}
catch{x("escape");}}

La versión no protegida (y ligeramente refactorizada) está disponible en http://pastebin.com/yAKYvwQf

Versión en ejecución: https://compilify.net/1n9 Esto se ha modificado ligeramente para ejecutarse en complify:

  • sin creación implícita de matrices, por ejemplo: new[]{1,2}
  • utiliza en return <string>lugar deConsole.WriteLine , porque así es como funciona compilify.net
Cristian Lupascu
fuente