Código Golf: Qual é o destino da nave espacial? [versão em ponto flutuante]

12

Esta questão é um pouco mais difícil que a versão artística ASCII. Não há arte, e agora você pode fazer uma aritmética de ponto flutuante!

O desafio

O USS StackExchange estava viajando pelo campo de gravidade do planeta cg-00DLEF quando ocorreu uma explosão astronômica a bordo. Como chefe de programação do navio, é seu trabalho simular a trajetória do navio, a fim de prever se você será forçado a cair em terra no sistema solar da cg-00DELF. Durante a explosão, seu navio foi fortemente danificado. Devido ao DEEEPRAROM * limitado e limitado da nave espacial, você deve escrever seu programa com o mínimo de caracteres possível.

* Acesso aleatório programável dinamicamente executável apagável eletronicamente, memória somente leitura

A Simulação

Um pouco como a versão artística ASCII, haverá a idéia de etapas do tempo. Na outra versão, um passo no tempo era uma quantidade relativamente grande de tempo: a nave poderia viajar muito além da gravidade de um planeta em um único passo no tempo. Aqui, o intervalo de tempo é uma unidade de tempo muito menor devido às maiores distâncias envolvidas. Uma grande diferença, no entanto, é a inexistência de células. A localização atual e a velocidade da espaçonave serão números de ponto flutuante, juntamente com as forças gravitacionais envolvidas. Outra mudança é o fato de que os planetas agora têm um tamanho muito maior.

Haverá até três planetas na simulação. Todos os três terão um local, raio e gravidade específicos. A gravidade de cada planeta é um vetor que exerce uma força diretamente em direção ao centro do planeta. A fórmula para encontrar a força desse vetor é (Gravity)/(Distance**2)onde a distância é a distância exata da nave até o centro do planeta. Isso significa que não há limite para onde a gravidade pode chegar.

A qualquer momento específico, a nave espacial tem uma velocidade, que é a distância e o ângulo que ela percorreu desde o último passo no tempo até agora. O navio também tem impulso. A distância percorrida entre o passo de tempo atual e o próximo é a soma de sua velocidade atual adicionada a todos os vetores de gravidade em sua localização. Isso se torna a nova velocidade da nave espacial.

Cada simulação tem um limite de tempo de 10000 etapas. Se a nave espacial viaja dentro de um planeta (é mais próxima do centro do planeta do que o raio do planeta), ela colide com o planeta. Se a nave espacial não colidir com nenhum planeta até o final da simulação, presume-se que ela tenha escapado da gravidade. É improvável que a nave possa estar alinhada tão perfeitamente que consiga permanecer em órbita por 10000 intervalos de tempo, enquanto colidir com o 10001º intervalo de tempo.

Entrada

A entrada terá quatro linhas para STDIN. Cada linha consiste em quatro números delimitados por vírgula. Aqui está o formato dos números:

ShipLocX,ShipLocY,ShipVelX,ShipVelY
Planet1LocX,Planet1LocY,Planet1Gravity,Planet1Radius
Planet2LocX,Planet2LocY,Planet2Gravity,Planet2Radius
Planet3LocX,Planet3LocY,Planet3Gravity,Planet3Radius

Se houver menos de três planetas, as linhas restantes serão preenchidas com zeros para todos os valores. Aqui está um exemplo de entrada:

60,0,0,10
0,0,4000,50
100,100,4000,50
0,0,0,0

Isso significa que a nave espacial está localizada em (60,0) e está viajando em linha reta "para cima / norte" a uma taxa de 10 unidades / intervalo de tempo. Existem dois planetas, um localizado em (0,0) e outro em (100,100). Ambos têm uma gravidade de 4000 e um raio de 50. Embora todos sejam números inteiros, eles nem sempre serão números inteiros.

Resultado

A saída será uma única palavra para STDOUT para dizer se a nave espacial caiu ou não. Se o acidente do navio cair, imprima crash. Caso contrário, imprima escape. Aqui está a saída esperada para a entrada acima:

crash

Você pode estar se perguntando o que aconteceu. Aqui está um post de Pastebin que possui um registro de voo detalhado para a nave espacial. Os números não são muito bons para ajudar as pessoas a visualizar o evento, então aqui está o que aconteceu: A nave espacial consegue escapar da gravidade do primeiro planeta (a oeste) com a ajuda da gravidade do segundo planeta (a nordeste). Ele se move para o norte e depois passa um pouco para o oeste do segundo planeta, quase sem perceber. Em seguida, curva-se ao redor do lado norte do planeta e colide com o lado oriental do segundo planeta.

Mais alguns casos para exame

60,0,10,-10
0,0,2000,50
100,100,1357.9,47.5
0,0,0,0

fuga (devido à lei do quadrado inverso, 2000 não é muita gravidade se você estiver a 60 unidades de distância)

0,0,0,0
100,100,20000,140
-50,-50,50,50
-100,-100,50,50

acidente (o primeiro planeta é extremamente massivo e extremamente próximo)

0,0,0,0
0,0,0,0
0,0,0,0
0,0,0,0

escape (este é um caso extremo: não há planetas e uma interpretação direta sugere que a espaçonave está diretamente sobre os planetas)

Regras, restrições e notas

Isso é código de golfe. Aplicam-se regras de código padrão de golfe. Seu programa deve ser escrito apenas em caracteres ASCII imprimíveis. Você não pode acessar nenhum tipo de banco de dados externo. Você pode escrever entradas em qualquer idioma (que não seja especializado em solucionar esse desafio).

Transmissão final

PhiNotPi
fonte
rofl DEEEPRAROM! - A interação gravitacional dos planetas não deveria ser simulada? Ainda não é exatamente caro numericamente, mas é justo o suficiente. - Suponho que a simulação de referência use a integração padrão da Runge-Kutta de 4ª ordem, e nosso programa deve criar resultados equivalentes?
deixou de girar contra-relógiowis
Eu não descobri como fazer vários planetas interagirem. O problema é que eles tendem a colidir um com o outro imediatamente. Para consertar isso, será necessário aumentar a escala da simulação incrivelmente.
PhiNotPi
Quanto ao método Runge-Kutta, sinceramente ainda não sou tão avançado em matemática. :( O que fiz foi calcular a gravidade no local atual do navio e adicioná-lo à velocidade do navio, gerando a nova velocidade do navio. Fiz isso para cada etapa do tempo. Sei que isso não é completamente preciso, mas descobri que dividindo a velocidade a partir do navio e gravidade dos planetas por 10 aumenta a precisão da simulação.
PhiNotPi
Ah, esse seria o método de Euler. Por etapas de tempo suficientemente pequenas, essa também é precisa; no entanto, Runge-Kutta ou algo mais sofisticado seria mais interessante para implementar a IMO. Talvez eu deva conceber meu próprio desafio, não consigo ser facilmente satisfatório ...
deixou de girar no sentido contrário
@leftaroundabout Vá em frente. Você pode criar algo como "simular todo o sistema solar usando equações diferenciais" ou algo sofisticado como esse, ou talvez adicionar na terceira dimensão.
PhiNotPi 16/04

Respostas:

6

Python, 178 170 caracteres

p=input
a,b,c,d=p()
x=a+b*1j
v=c+d*1j
P=(p(),p(),p())
R='escape'
for i in' '*10000:
 for a,b,g,r in P:
  d=a+b*1j-x;v+=g*d/abs(d)**3
  if abs(d)<r:R='crash'
 x+=v
print R
Keith Randall
fonte
2
Você está com um humor complexo hoje, não está?
deixou de girar no sentido contrário
8
sim, isou ....
Keith Randall
Como posso competir com isso?
Neil
@ Neil: o código, ou as brincadeiras espirituosas?
Keith Randall
Bem, o código. A brincadeira espirituosa que eu posso acompanhar.
214 Neil
2

Golfrun / GolfScript ?, 243 232 caracteres

10000:M;n%(','%2/{{~}%}/{{M*}%}:_~:v;_:x;'escape':R;{[','%2/{{~M*}%}/]}%:P;
M,{;P{~\x{0\-}%{+~@+@@+[\]}:|~:d.[~0\-]{[+.2%~*\.-2%~*@\-\.3%~*\(;);~*+]}:&~);~sqrt:z
..**\~d@[`~0]\&@M.*/\{1$/}%v|:v;;z\<{'crash':R;}{}if}/x v|:x;}/R puts

Golfrun é uma linguagem em que estou trabalhando, nascida como intérprete do GolfScript C, mas logo se afastou de alguma maneira; Embora eu tenha escrito esse código sem usar recursos Golfrun específicos (intencionalmente sqrt), o teste com o GolfScript original falhou (tive que adicionar o recurso sqrt ao código original, não sou um guru do Ruby, mas acredito que o problema seja não é o meu ajuste).

O primeiro problema com esta solução é que o Golfrun, como o GolfScript, não possui matemática de ponto flutuante. É "simulado" ampliando os números, esperançosamente da maneira correta (mas não estou 100% confiante de ter feito isso de forma coerente). Mesmo assim, a solução não manipula números de ponto flutuante como entrada, então tive que ampliá-los manualmente para ter apenas números inteiros.

Tentando implementar o algoritmo no código Python, também implementei bits de matemática complexa de uma maneira bastante "geral". Manipular o algoritmo para evitar isso e / ou inlining sempre que possível, atrasando as definições, pode salvar outros caracteres ...

Como sei que esse código funciona? Na verdade, não tenho certeza! Mas, dando os exemplos como entrada (depois de "remover" os pontos onde eles aparecem), ele escreveu os resultados esperados, exceto o "caso de canto" (que também gera uma exceção no Python) ...

ShinTakezou
fonte