Код Гольф: какова судьба космического корабля? [ASCII художественная версия]

14

Фон

В галактике (и, возможно, во вселенной) далеко-далеко ... был космический корабль и множество планет. Неисправность на борту заставила космический корабль исчерпать топливо. Теперь он движется с опасно медленной скоростью возле скопления планет, из которого он должен сбежать! Какова будет судьба экипажа?

Соревнование

Вы являетесь ведущим программистом USS StackExchange. Таким образом, вы хотите написать симулятор, который покажет, обречен ли вам обрушиться на планету, уйдет ли она из планетарной системы или застрянет на орбите навсегда.

Однако взрыв на вашем космическом корабле означает, что вычислительные ресурсы были очень ограниченными. Ваша программа должна быть как можно меньше. Кроме того, это означает, что единственный возможный способ ввода симуляций - это искусство ASCII.

Симуляция

В этом квадранте мультивселенной законы физики немного изменены, чтобы приспособиться к искусству ASCII. Это означает, что космос разделен на клетки. Движение будет описано в единицах ячеек, а время будет в единицах временных шагов.

Сам корабль имеет импульс. Если на предыдущем шаге времени корабль переместился на +2 клетки по оси x и -1 на ось y (сокращенно (2, -1)), а гравитационное поле отсутствует, то корабль будет двигаться с точным та же скорость на следующем шаге по времени.

Будет несколько планет, каждая из которых создает гравитационное поле на восьми клетках, непосредственно окружающих его, что повлияет на скорость корабля и притянет корабль ближе к планете. Находясь на «севере» от планеты, поле будет тянуть корабль на одну клетку на «юг» с силой (-1,0). Находясь на «северо-востоке» планеты, вы столкнетесь с силой, тянущей корабль на одну клетку на «юг» и одну единицу на «запад» с силой (-1, -1).

Гравитационные поля добавляют вектор к импульсу корабля, когда он покидает клетку с гравитацией. Если корабль только что переместил (2, -1) клетки и теперь находится в гравитационном поле (-1,1), то на следующем шаге он переместит (1,0) клетки. Если корабль находится в непосредственной близости от нескольких планет, то будет добавлено несколько векторов.

вход

На STDIN вы получите художественное представление ASCII о планетной системе, которое покажет координаты планет и текущую скорость вашего корабля. Там будет несколько планет в виде знаков @, а будет один космический корабль в виде знака av ^ <>. Выбор символа для корабля указывает текущую скорость корабля (до добавления гравитации). Например, <означает скорость одной ячейки к западу, а ^ означает скорость одной ячейки к северу. Все пустое пространство будет состоять из периодов, которые дополняют каждую строку одинаковой шириной. Пустая строка представляет конец ввода. Вот пример ввода:

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

Выход

Вывод будет одним словом на STDOUT, который скажет, избежит ли корабль гравитации, столкнется с землей на планете или будет вращаться навсегда.

Выход из гравитации определяется как движение корабля по карте. Если корабль убегает, то ваша программа должна напечатать слово «escape».

Аварийная посадка - это когда корабль проходит над планетой или попадает в одну и ту же ячейку в течение временного шага. Обратите внимание, что недостаточно просто рассчитать, где находится корабль, каждый раз. Корабль, движущийся со скоростью (5,5), упадет на планету, расположенную в точке (1,1), хотя прямые вычисления будут означать, что он никогда не посетит эту клетку. Однако корабль со скоростью (5,6) не врезается в землю. Если произошел сбой вашего космического корабля, то ваша программа должна вывести слово «crash».

Орбитальное движение может быть самым трудным для обнаружения. Орбитальное движение происходит всякий раз, когда космический корабль дважды посещает одну и ту же клетку с одинаковой скоростью. Если корабль движется по орбите, вы должны напечатать слово «орбита».

Вот вывод для приведенного выше примера:

escape

объяснение

Вот карта, показывающая, куда космический корабль путешествовал в каждом временном шаге в приведенном выше примере:

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

Он пошел на юг, повернул на запад, прошел по коридору, повернул на север и узко сбежал между планетами с высокой скоростью, все из-за гравитации.


Больше дел для экспертизы

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

Правила, положения и примечания

Это код гольф. Применяются стандартные правила игры в гольф. Ваши программы должны быть написаны в формате ASCII для печати. Вам не разрешен доступ к какой-либо внешней базе данных.

Конец передачи

PhiNotPi
источник
Кажется, что в строке чуть выше секции INPUT есть опечатка ... Я предполагаю, что вы имеете в виду планету? :-)
Gaffi
На самом деле, весь этот частичный абзац необходимо удалить, информация повторяется в разделе вывода.
PhiNotPi
1
Я хотел бы, чтобы это было лучше с немного меньшей физикой ... этот сайт мог бы справиться с большим количеством проблем, которые также включают в себя немного дорогую арифметику с плавающей точкой.
перестал поворачиваться против часовой стрелки
1
@leftaroundabout Это может быть моей следующей проблемой.
PhiNotPi
Насколько близко должна быть планета, чтобы в нее врезаться?
Питер Тейлор

Ответы:

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

Развернутая (и слегка переработанная) версия доступна по адресу http://pastebin.com/yAKYvwQf

Рабочая версия: https://compilify.net/1n9 Это было немного изменено для запуска на complify:

  • неявное создание массива - например: new[]{1,2}
  • использует return <string>вместо Console.WriteLine, потому что так работает compilify.net
Кристиан Лупаску
источник