Code Golf: quel est le sort du vaisseau spatial? [Version d'art ASCII]

14

Contexte

Dans une galaxie (et peut-être un univers) loin, très loin ... il y avait un vaisseau spatial et un tas de planètes. Un dysfonctionnement à bord a fait manquer de carburant au vaisseau spatial. Il se déplace maintenant à une vitesse dangereusement lente près d'un amas de planètes, dont il doit s'échapper! Quel sera le sort de l'équipage?

Le défi

Vous êtes le principal programmeur de l'USS StackExchange. En tant que tel, vous souhaitez écrire un simulateur qui révélera si vous êtes ou non condamné à s'écraser sur une planète, à échapper au système planétaire ou à rester en orbite pour toujours.

L'explosion sur votre vaisseau spatial, cependant, signifie que les ressources de calcul étaient très limitées. Votre programme doit être aussi petit que possible. Cela signifie également que le seul moyen possible de saisir des simulations à exécuter est d'utiliser l'art ASCII.

La simulation

Dans ce quadrant du multivers, les lois de la physique sont légèrement modifiées afin de s'adapter à l'art ASCII. Cela signifie que le cosmos est divisé en cellules. Le mouvement sera décrit en unités de cellules et le temps sera en unités de pas de temps.

Le navire lui-même a un élan. Si le navire a déplacé +2 cellules sur l'axe x et -1 cellule sur l'axe y (en raccourci comme (2, -1)) au pas de temps précédent, et qu'il n'y a pas de champ gravitationnel, alors le navire se déplacera avec l'exact même vitesse sur le pas de temps suivant.

Il y aura plusieurs planètes, qui exerceront toutes un champ gravitationnel sur les huit cellules qui l'entourent immédiatement, ce qui affectera la vitesse du navire et rapprochera le navire de la planète. Être juste "au nord" d'une planète entraînera un champ tirant le vaisseau d'une cellule vers le "sud" avec une force de (-1,0). Être juste au "nord-est" d'une planète entraînera une force tirant le vaisseau d'une cellule au "sud" et d'une unité à "l'ouest" avec une force de (-1, -1).

Les champs gravitationnels ajoutent un vecteur à l'élan du navire alors qu'il quitte la cellule avec la gravité. Si un vaisseau vient juste de déplacer (2, -1) cellules et se trouve maintenant dans un champ gravitationnel de (-1,1), alors dans cette prochaine étape, il déplacera (1,0) cellules. Si le navire est à proximité de plusieurs planètes, il y aura plusieurs vecteurs à ajouter.

Contribution

Sur STDIN, vous recevrez une représentation artistique ASCII du système planétaire qui montrera les coordonnées des planètes et la vitesse actuelle de votre vaisseau. Il y aura plusieurs planètes sous la forme de signes @, tandis qu'il y aura un vaisseau spatial sous la forme d'un signe av ^ <>. Le choix du symbole pour le navire indique la vitesse actuelle du navire (avant l'ajout de la gravité). Par exemple, a <signifie la vitesse d'une cellule à l'ouest, tandis que a ^ signifie la vitesse d'une cellule au nord. Tout espace vide sera composé de points, qui remplissent chaque ligne pour avoir la même largeur. Une ligne vierge représente la fin de l'entrée. Voici un exemple d'entrée:

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

Production

La sortie sera un seul mot sur STDOUT, qui dira si le navire échappera à la gravité, s'écrasera sur une planète ou orbitera pour toujours.

Échapper à la gravité est défini comme le navire qui s'éloigne de la carte. Si le vaisseau s'échappe, alors votre programme doit imprimer le mot "escape".

L'atterrissage forcé se produit lorsqu'un navire passe directement au-dessus d'une planète ou se retrouve dans la même cellule pendant un pas de temps. Notez qu'il ne suffit pas de calculer simplement où se trouve le navire à chaque pas de temps. Un navire se déplaçant à une vitesse de (5,5) va s'écraser sur une planète située à (1,1) même si un calcul simple signifie qu'il ne visitera jamais cette cellule. Un vaisseau avec une vitesse de (5,6) n'écrasera cependant pas la planète. Si votre crash de vaisseau spatial atterrit, votre programme doit imprimer le mot "crash".

L'orbite peut être la plus difficile à détecter. L'orbite se produit chaque fois que le vaisseau spatial visite la même cellule et la même vitesse. Si le navire orbite, vous devez imprimer le mot "orbite".

Voici la sortie de l'exemple ci-dessus:

escape

Explication

Voici une carte montrant où le vaisseau spatial a voyagé à chaque pas de temps dans l'exemple ci-dessus:

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

Il est allé vers le sud, s'est tourné vers l'ouest, a parcouru un couloir, s'est tourné vers le nord et s'est échappé de justesse entre des planètes à grande vitesse, toutes en raison de la gravité.


Plus de cas à examiner

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

Règles, règlements et notes

C'est le golf de code. Les règles de golf à code standard s'appliquent. Vos programmes doivent être écrits en ASCII imprimable. Vous n'êtes pas autorisé à accéder à toute sorte de base de données externe.

Fin de transmission

PhiNotPi
la source
Il semble y avoir une faute de frappe dans la ligne juste au-dessus de la section INPUT ... Je suppose que vous voulez dire planète? :-)
Gaffi
En fait, tout ce paragraphe partiel devait être supprimé, les informations sont répétées dans la section sortie.
PhiNotPi
1
J'aimerais mieux cela avec une physique légèrement moins modifiée ... ce site pourrait faire plus de problèmes qui impliquent également une petite arithmétique en virgule flottante coûteuse.
cessé de tourner dans le sens inverse des aiguilles d'une montre le
1
@leftaroundabout C'est peut-être mon prochain défi.
PhiNotPi
À quelle distance d'une planète doit-elle être pour s'y écraser?
Peter Taylor

Réponses:

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 version non golfée (et légèrement refactorisée) est disponible sur http://pastebin.com/yAKYvwQf

Version en cours d'exécution: https://compilify.net/1n9 Cela a été légèrement modifié pour être exécuté sur complify:

  • pas de création de tableau implicite - ex: new[]{1,2}
  • utilise à la return <string>place de Console.WriteLine, car c'est ainsi que compilify.net fonctionne
Cristian Lupascu
la source