Code Golf: Яка доля космічного корабля? [Художня версія 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 ^ <>. Вибір символу для корабля вказує поточну швидкість корабля (до додавання сили тяжіння). Наприклад, a <означає швидкість однієї комірки на захід, тоді як ^ означає швидкість однієї комірки на північ. Все порожнє місце буде складатися з періодів, у яких кожен рядок має однакову ширину. Порожній рядок представляє кінець введення. Ось приклад введення:

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

Вихідні дані

Вихід буде одним словом на STDOUT, яке підкаже, чи вдасться кораблю уникнути сили тяжіння, зазнає аварії, приземлившись на планету, або буде орбітою назавжди.

Утеча від тяжкості визначається як корабель, який рухається з карти. Якщо судно втече, то ваша програма повинна надрукувати слово "втеча".

Аварійне приземлення - це коли корабель проходить безпосередньо над планетою або опиняється в тій же клітці під час кроку. Зауважте, що недостатньо просто обчислити, де знаходиться кожен корабель. Корабель, що рухається зі швидкістю (5,5), вріжеться в планету, розташовану в (1,1), навіть якщо прямий розрахунок означатиме, що він ніколи не відвідуватиме цю клітинку. Однак корабель зі швидкістю (5,6) не вріжеться на планету. Якщо ваш крах космічного корабля приземлився, то ваша програма повинна надрукувати слово "аварія".

Орбіта може бути найскладнішою для виявлення. Орбітація відбувається кожного разу, коли космічний корабель двічі відвідує ту саму клітинку і з однаковою швидкістю. Якщо корабель орбітує, то слід надрукувати слово "орбіта".

Ось результат для наведеного вище прикладу:

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 для друку. Ви не маєте доступу до будь-якої зовнішньої бази даних.

Кінцева передача


Здається, що в рядку, що знаходиться над розділом INPUT, є друкарська помилка ... Я припускаю, що ви маєте на увазі планету? :-)
Гаффі

Власне, весь цей частковий абзац потрібно видалити, інформація повторюється під вихідним розділом.
PhiNotPi

1
Мені б хотілося цього краще з трохи менш зміненою фізикою ... Цей сайт міг би мати більше проблем, які також передбачають невелику приємну арифметику з плаваючою комою.
перестали повертати проти годинника,

1
@leftaroundabout Це може бути моїм наступним завданням.
PhiNotPi

Наскільки близько до планети потрібно, щоб її врізати?
Пітер Тейлор

Відповіді:


6

С # 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 Це було трохи змінено для запуску на сумісність:

  • немає неявного створення масиву - наприклад: new[]{1,2}
  • використовує return <string>замість цього Console.WriteLine, тому що так працює compilify.net
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.