Código Golf: Qual é o destino da nave espacial? [Versão artística ASCII]

14

fundo

Em uma galáxia (e possivelmente um universo) muito, muito longe ... havia uma nave espacial e um monte de planetas. Um mau funcionamento a bordo fez a nave ficar sem combustível. Agora está se movendo a uma velocidade perigosamente lenta perto de um aglomerado de planetas, do qual deve escapar! Qual será o destino da tripulação?

O desafio

Você é o programador líder no USS StackExchange. Como tal, você deseja escrever um simulador que revele se você está ou não condenado a aterrissar em um planeta, escapará do sistema planetário ou ficará em órbita para sempre.

A explosão da sua nave espacial, no entanto, significa que havia recursos computacionais muito limitados. Seu programa deve ser o menor possível. Além disso, isso significa que a única maneira possível de inserir simulações para executar é através da arte ASCII.

A Simulação

Nesse quadrante do multiverso, as leis da física são ligeiramente alteradas para acomodar a arte ASCII. Isso significa que o cosmos é dividido em células. O movimento será descrito em unidades de células e o tempo será em unidades de tempo.

O navio em si tem impulso. Se a nave moveu +2 células no eixo xe -1 célula no eixo y (abreviado como (2, -1)) no passo anterior, e não há campo gravitacional, a nave se moverá com a precisão exata mesma velocidade no próximo passo.

Haverá vários planetas, todos exercendo um campo gravitacional nas oito células imediatamente ao seu redor, o que afetará a velocidade da nave e puxará a nave para mais perto do planeta. Ser apenas "norte" de um planeta resultará em um campo puxando a nave uma célula para o "sul" com uma força de (-1,0). Ser apenas "nordeste" de um planeta resultará em uma força puxando a nave uma célula para o "sul" e uma unidade para o "oeste" com uma força de (-1, -1).

Os campos gravitacionais adicionam um vetor ao momento da nave, pois esta deixa a célula com a gravidade. Se uma nave apenas moveu anteriormente (2, -1) células e agora está em um campo gravitacional de (-1,1), então, na próxima etapa, ela moverá (1,0) células. Se a nave estiver próxima de vários planetas, haverá vários vetores a serem adicionados.

Entrada

Em STDIN, você receberá uma representação artística do sistema planetário ASCII que mostrará as coordenadas dos planetas e a velocidade atual da sua nave. Haverá vários planetas na forma de sinais @, enquanto haverá uma nave espacial na forma de sinal av ^ <>. A escolha do símbolo para o navio indica a velocidade atual do navio (antes da adição da gravidade). Por exemplo, a <significa a velocidade de uma célula para o oeste, enquanto a ^ significa a velocidade de uma célula para o norte. Todo o espaço vazio consistirá em pontos, que preencherão cada linha com a mesma largura. Uma linha em branco representa o fim da entrada. Aqui está um exemplo de uma entrada:

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

Resultado

A saída será uma única palavra em STDOUT, que dirá se a nave escapará da gravidade, colidirá com um planeta ou orbitará para sempre.

Escapar da gravidade é definido como o navio saindo do mapa. Se o navio escapar, seu programa deverá imprimir a palavra "escape".

O pouso forçado é quando uma nave passa diretamente sobre um planeta ou acaba na mesma célula durante um intervalo de tempo. Observe que não basta calcular simplesmente onde o navio está a cada passo do tempo. Uma nave que se move a uma velocidade de (5,5) colidirá com um planeta localizado em (1,1), embora um cálculo direto signifique que ela nunca visitará essa célula. Porém, uma nave com velocidade de (5,6) não colidirá com terra no planeta. Se a falha de sua nave espacial cair, seu programa deverá imprimir a palavra "falha".

A órbita pode ser a mais difícil de detectar. A órbita ocorre sempre que a nave espacial visita a mesma célula duas vezes e com a mesma velocidade. Se o navio orbitar, imprima a palavra "órbita".

Aqui está a saída para o exemplo acima:

escape

Explicação

Aqui está um mapa mostrando para onde a nave espacial viajou em cada etapa do tempo no exemplo acima:

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

Foi para o sul, virou para o oeste, viajou por um corredor, virou para o norte e escapou por pouco para planetas em alta velocidade, tudo devido à gravidade.


Mais casos para exame

...
^@.
...
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)

Regras, regulamentos e notas

Isso é código de golfe. Aplicam-se regras de código padrão de golfe. Seus programas devem ser escritos em ASCII imprimível. Você não tem permissão para acessar qualquer tipo de banco de dados externo.

Transmissão final

PhiNotPi
fonte
Parece haver um erro de digitação na linha logo acima da seção INPUT ... Suponho que você queira dizer planeta? :-)
Gaffi 13/04/12
Na verdade, todo esse parágrafo parcial precisava ser excluído, as informações são repetidas na seção de saída.
PhiNotPi
1
Eu gostaria disso melhor com a física um pouco menos alterada ... este site poderia lidar com mais problemas que também envolvem um pouco de aritmética de ponto flutuante caro.
deixou de girar contra-
1
@leftaroundabout Esse pode ser o meu próximo desafio.
PhiNotPi
Quão perto de um planeta ele precisa estar para colidir com ele?
Peter Taylor

Respostas:

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");}}

A versão não-gasta (e levemente refatorada) está disponível em http://pastebin.com/yAKYvwQf

Versão em execução: https://compilify.net/1n9 Isso foi ligeiramente modificado para ser executado no complify:

  • nenhuma criação implícita de array - ex: new[]{1,2}
  • usa em return <string>vez de Console.WriteLine, porque é assim que o compilify.net funciona
Cristian Lupascu
fonte