Code Golf: Jaki jest los statku kosmicznego? [Wersja artystyczna ASCII]

14

tło

W galaktyce (i prawdopodobnie we wszechświecie) daleko, daleko ... był statek kosmiczny i wiązka planet. Awaria na pokładzie spowodowała, że ​​w statku kosmicznym zabrakło paliwa. Porusza się teraz z niebezpiecznie małą prędkością w pobliżu gromady planet, z której musi uciec! Jaki będzie los załogi?

Wyzwanie

Jesteś wiodącym programistą w USS StackExchange. Jako taki, chcesz napisać symulator, który ujawni, czy jesteś skazany na rozbicie lądu na planetę, ucieknie z układu planetarnego lub utknie na orbicie na zawsze.

Eksplozja na twoim statku kosmicznym oznacza jednak, że zasoby obliczeniowe były bardzo ograniczone. Twój program musi być jak najmniejszy. Oznacza to również, że jedynym możliwym sposobem wprowadzenia symulacji do uruchomienia jest sztuka ASCII.

Symulacja

W tej ćwiartce multiwersum prawa fizyki są nieco zmienione, aby uwzględnić sztukę ASCII. Oznacza to, że kosmos jest podzielony na komórki. Ruch zostanie opisany w jednostkach komórek, a czas w jednostkach czasu.

Sam statek ma rozpęd. Jeśli statek przesunął +2 komórki na osi x i -1 komórkę na osi y (w skrócie (2, -1)) w poprzednim kroku czasowym, a nie ma pola grawitacyjnego, wówczas statek ruszy z dokładną dokładnością ta sama prędkość w następnym kroku czasowym.

Będzie kilka planet, z których wszystkie wywierają pole grawitacyjne na osiem bezpośrednio otaczających je komórek, co wpłynie na prędkość statku i przyciągnie statek bliżej planety. Będąc „na północ” planety, pole pociągnie statek o jedną komórkę na „południe” z siłą (-1,0). Będąc „na północny wschód” planety, siła pociągnie statek o jedną komórkę na „południe” i jedną na „zachód” z siłą (-1, -1).

Pola grawitacyjne dodają wektor do pędu statku, gdy opuszcza on komórkę wraz z grawitacją. Jeśli statek właśnie przesunął (2, -1) komórki i znajduje się teraz w polu grawitacyjnym (-1,1), to w następnym kroku czasowym przeniesie (1,0) komórki. Jeśli statek znajduje się w pobliżu wielu planet, do dodania będzie wiele wektorów.

Wejście

Na STDIN otrzymasz ASCII artystyczną reprezentację układu planetarnego, która pokaże współrzędne planet i aktualną prędkość twojego statku. Będzie kilka planet w postaci znaków @, natomiast będzie jeden statek kosmiczny w postaci znaku av ^ <>. Wybór symbolu statku wskazuje aktualną prędkość statku (przed dodaniem grawitacji). Na przykład a <oznacza prędkość jednej komórki na zachód, a ^ oznacza prędkość jednej komórki na północ. Cała pusta przestrzeń będzie się składać z kropek, które wypełniają każdą linię tak, aby miała tę samą szerokość. Pusty wiersz oznacza koniec wprowadzania. Oto przykład danych wejściowych:

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

Wynik

Wyjście będzie pojedynczym słowem na STDOUT, które powie, czy statek ucieknie grawitacji, zderzy się z lądem na planecie, czy okrąży na zawsze.

Ucieczka od grawitacji jest definiowana jako statek ruszający się z mapy. Jeśli statek ucieknie, wówczas twój program musi wydrukować słowo „ucieczka”.

Awaria lądowania ma miejsce, gdy statek przelatuje bezpośrednio nad planetą lub ląduje w tej samej komórce podczas kroku czasowego. Pamiętaj, że nie wystarczy po prostu obliczyć, gdzie statek jest za każdym razem. Statek poruszający się z prędkością (5,5) zderzy się z planetą znajdującą się w (1,1), chociaż proste obliczenia będą oznaczały, że nigdy nie odwiedzi tej komórki. Statek o prędkości (5,6) nie wyląduje jednak na planecie. Jeśli katastrofa statku kosmicznego wyląduje, wówczas program musi wydrukować słowo „katastrofa”.

Orbitowanie może być najtrudniejsze do wykrycia. Orbitowanie ma miejsce za każdym razem, gdy statek kosmiczny odwiedza tę samą komórkę dwukrotnie i z tą samą prędkością. Jeśli statek krąży po orbicie, należy wydrukować słowo „orbitować”.

Oto wynik dla powyższego przykładu:

escape

Wyjaśnienie

Oto mapa pokazująca drogę statku kosmicznego na każdym etapie w powyższym przykładzie:

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

Poszedł na południe, skręcił na zachód, przeszedł korytarzem, skręcił na północ i wąsko uciekł między planetami z dużą prędkością, wszystko z powodu grawitacji.


Więcej przypadków do zbadania

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

Zasady, przepisy i uwagi

To jest kod golfowy. Obowiązują standardowe zasady gry w golfa. Twoje programy muszą być napisane w drukowanym formacie ASCII. Nie masz dostępu do żadnej zewnętrznej bazy danych.

Zakończ transmisję

PhiNotPi
źródło
Wygląda na to, że w linii tuż nad sekcją WEJŚCIE jest literówka ... Zakładam, że masz na myśli planetę? :-)
Gaffi,
W rzeczywistości cały ten częściowy akapit musiał zostać usunięty, informacje są powtarzane w sekcji wyników.
PhiNotPi
1
Chciałbym to lepiej z nieco mniej zmienioną fizyką ... ta strona mogłaby poradzić sobie z większymi problemami, które obejmują również trochę ładną, kosztowną arytmetykę zmiennoprzecinkową.
przestał obracać przeciwnie do zegara
1
@leftaroundabout To może być moje następne wyzwanie.
PhiNotPi
Jak blisko planety musi być, żeby się w nią zderzyć?
Peter Taylor

Odpowiedzi:

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

Wersja bez golfa (i nieco przebudowana) jest dostępna na stronie http://pastebin.com/yAKYvwQf

Działająca wersja: https://compilify.net/1n9 Zostało to nieznacznie zmodyfikowane, aby można było uruchomić na compify:

  • brak niejawnego tworzenia tablicy - np .: new[]{1,2}
  • używa return <string>zamiast Console.WriteLine, ponieważ tak działa compilify.net
Cristian Lupascu
źródło