14
\$\begingroup\$

Background

In a galaxy (and possibly a universe) far, far away... there was a spaceship and a bunch of planets. A malfunction on board caused the spaceship to run out of fuel. It is now moving at a dangerously slow speed near a cluster of planets, from which it must escape! What will be the crew's fate?

The Challenge

You are the lead programmer on the U.S.S. StackExchange. As such, you desire to write a simulator that will reveal whether or not you are doomed to crash land onto a planet, will escape the planetary system, or will be stuck in orbit forever.

The explosion on your spaceship, however, means that there was very limited computational resources. Your program must be as small as possible. Also, this means that the only possible way of inputting simulations to run is through ASCII art.

The Simulation

In this quadrant of the multiverse, the laws of physics are slightly altered in order to accommodate ASCII art. This means that the cosmos is divided up into cells. Movement will be described in units of cells, and time will be in units of time steps.

The ship itself has momentum. If the ship moved +2 cells on the x axis and -1 cell on the y axis (shorthanded as (2,-1)) in the previous time step, and there is no gravitational field, then the ship will move with the exact same velocity on the next time step.

There will be several planets, all of which exert a gravitational field on the eight cells immediately surrounding it, which will effect the ship's velocity and will pull the ship closer to the planet. Being just "north" of a planet will result in a field pulling the ship one cell to the "south" with a force of (-1,0). Being just "northeast" of a planet will result in a force pulling the ship one cell to the "south" and one unit to the "west" with a force of (-1,-1).

The gravitational fields add a vector to the ship's momentum as it is leaving the cell with the gravity. If a ship just previously moved (2,-1) cells and is now in a gravitational field of (-1,1), then in this next time step it will move (1,0) cells. If the ship is in close proximity to multiple planets, then there will be multiple vectors to add.

Input

On STDIN, you will receive an ASCII art representation of the planetary system that will show the coordinates of the planets and your ship's current velocity. There will be several planets in the form of @ signs, while there will be one spaceship in the form of a v^<> sign. The choice of symbol for the ship indicates the current velocity of the ship (before gravity has been added). For example, a < means a velocity of one cell to the west, while a ^ means a velocity of one cell to the north. All empty space will consist of periods, which pad every line to be the same width. A blank line represents the end of input. Here is an example of an input:

.................
...@.@........v..
......@..@..@@...
..@..............
.......@..@......
.................

Output

Output will be a single word on STDOUT, which will tell whether the ship will escape gravity, will crash land into a planet, or will orbit forever.

Escaping from gravity is defined as the ship moving off of the map. If the ship escapes, then your program must print the word "escape".

Crash landing is when a ship passes directly over a planet or ends up in the same cell during a time step. Note that it is not enough to simply calculate where the ship is every time step. A ship moving at a velocity of (5,5) will crash into a planet located at (1,1) even though straightforward calculation will mean that it will never visit that cell. A ship with a velocity of (5,6) will not crash land into the planet, however. If your spaceship crash lands, then your program must print the word "crash".

Orbiting may be the most difficult to detect. Orbiting occurs whenever the spaceship visits the same cell twiceand with the same velocity. If the ship orbits, then you should print the word "orbit".

Here is the output for the above example:

escape

Explanation

Here is a map showing where the spaceship traveled in each time step in the above example:

   ^
.................
...@.@........v..
....^.@..@..@@...
..@..<.<<<.<.v...
.......@..@......
.................

It went south, turned to the west, travelled down a corridor, turned to the north, and narrowly escaped between to planets with a high velocity, all becuase of gravity.


More cases for examination

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

Rules, Regulations, and Notes

This is code golf. Standard code golf rules apply. Your programs must be written in printable ASCII. You aren't allowed to access any sort of external database.

End Transmission

\$\endgroup\$
6
  • \$\begingroup\$ There appears to be a typo in the line just above the INPUT section... I assume you mean planet? :-) \$\endgroup\$
    – Gaffi
    Apr 13 '12 at 15:46
  • \$\begingroup\$ Actually, that whole partial paragraph needed to be deleted, the information is repeated under the output section. \$\endgroup\$
    – PhiNotPi
    Apr 13 '12 at 15:49
  • 1
    \$\begingroup\$ I'd like this better with slightly less altered physics... this site could do with more problems that also involve a little nice expensive floating-point arithmetic. \$\endgroup\$ Apr 13 '12 at 16:50
  • 1
    \$\begingroup\$ @leftaroundabout That may be my next challenge. \$\endgroup\$
    – PhiNotPi
    Apr 13 '12 at 17:13
  • \$\begingroup\$ How close to a planet does it need to be to crash into it? \$\endgroup\$ Apr 14 '12 at 10:07
6
\$\begingroup\$

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

The ungolfed (and slightly refactored) version is available at http://pastebin.com/yAKYvwQf

Running version: https://compilify.net/1n9 This has been slightly modified to be run on complify:

  • no implicit array creation - ex: new[]{1,2}
  • uses return <string> instead of Console.WriteLine, because that's how compilify.net works
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.