Code Golf: Uzay gemisinin kaderi nedir? [ASCII sanat sürümü]


14

Arka fon

Uzakta bir galakside (ve muhtemelen bir evrende) ... bir uzay gemisi ve bir grup gezegen vardı. Gemideki bir arıza, uzay gemisinin yakıtının bitmesine neden oldu. Şimdi kaçmak zorunda olduğu bir gezegen kümesinin yakınında tehlikeli derecede yavaş bir hızda hareket ediyor! Mürettebatın kaderi ne olacak?

Meydan okuma

USS StackExchange'te lider programcısınız. Bu nedenle, bir gezegene karayı çarpmaya mahkum olup olmadığınızı, gezegen sisteminden kaçıp kaçmayacağınızı veya sonsuza kadar yörüngeye sıkışıp kalmayacağınızı ortaya çıkaran bir simülatör yazmak istersiniz.

Bununla birlikte, uzay geminizdeki patlama, çok sınırlı hesaplama kaynaklarının olduğu anlamına gelir. Programınız mümkün olduğunca küçük olmalıdır. Ayrıca, bu, simülasyonları çalıştırmak için girmenin tek olası yolunun ASCII sanatı aracılığıyla olduğu anlamına gelir.

Simülasyon

Çoklu evrenin bu çeyreğinde, ASCII sanatına uyum sağlamak için fizik yasaları biraz değiştirilir. Bu, kozmosun hücrelere ayrıldığı anlamına gelir. Hareket, hücre birimlerinde tarif edilecek ve zaman, zaman adımları biriminde olacaktır.

Geminin kendisinin momentumu var. Eğer gemi önceki zaman adımında x ekseninde +2 hücreleri ve y ekseninde -1 hücresini ((2, -1) olarak kısaltılmış) hareket ettirdiyse ve yerçekimi alanı yoksa, gemi tam olarak sonraki hızda aynı hız.

Hemen etrafını çevreleyen sekiz hücre üzerinde yerçekimsel bir alan uygulayan birkaç gemi olacak, bu da geminin hızını etkileyecek ve gemiyi gezegene yaklaştıracak. Bir gezegenin sadece "kuzeyi" olmak, bir alanın (-1,0) kuvvetiyle gemiyi bir hücre "güneye" çekmesine neden olur. Bir gezegenin sadece "kuzeydoğu" olması, geminin bir hücresini "güneye" ve bir birimi "batıya" (-1, -1) kuvvetiyle çekmesine neden olur.

Yerçekimi alanları, hücreyi yerçekimi ile terk ettiği için geminin momentumuna bir vektör ekler. Bir gemi daha önce (2, -1) hücreleri hareket ettirdiyse ve şimdi (-1,1) 'in yerçekimi alanındaysa, bu sonraki adım adımında (1,0) hücreleri hareket ettirecektir. Gemi birden fazla gezegene yakınsa, eklenecek birden fazla vektör olacaktır.

Giriş

STDIN'de, gezegenlerin koordinatlarını ve geminizin mevcut hızını gösterecek bir ASCII gezegen sisteminin sanat temsilini alacaksınız. @ İşaretleri şeklinde birkaç gezegen olacakken, av ^ <> işareti şeklinde bir uzay gemisi olacak. Geminin sembol seçimi geminin mevcut hızını gösterir (yerçekimi eklenmeden önce). Örneğin, <, bir hücrenin batıya doğru hızı anlamına gelirken, ^, bir hücrenin kuzeye doğru bir hızı anlamına gelir. Tüm boş alanlar, her satırın aynı genişlikte olmasını sağlayan noktalardan oluşacaktır. Boş satır girişin sonunu temsil eder. İşte bir giriş örneği:

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

Çıktı

Çıktı, geminin yerçekiminden kaçıp kaçmayacağını, karayı bir gezegene çarpıp çakmayacağını veya sonsuza kadar yörüngeye döneceğini söyleyen STDOUT'ta tek bir kelime olacak.

Yerçekiminden kaçmak, haritadan hareket eden gemi olarak tanımlanır. Gemi kaçarsa, programınız "kaçış" kelimesini yazdırmalıdır.

Çöküş inişi, bir geminin doğrudan bir gezegenin üzerinden geçmesi veya bir zaman adımı sırasında aynı hücreye girmesidir. Her seferinde geminin nerede olduğunu hesaplamanın yeterli olmadığını unutmayın. (5,5) hızında hareket eden bir gemi, (1,1) 'de bulunan bir gezegene çarpacak olsa da, doğrudan hesaplama, o hücreyi asla ziyaret etmeyeceği anlamına gelecektir. Hızı (5,6) olan bir gemi, gezegene karayı çarpmayacaktır. Eğer uzay gemisi kazanız inerse, o zaman program "crash" kelimesini yazdırmak gerekir.

Yörüngeyi tespit etmek en zor olanı olabilir. Yörünge, uzay gemisi aynı hücreyi iki kez ve aynı hızda ziyaret ettiğinde gerçekleşir. Gemi yörüngede ise "yörünge" kelimesini yazdırmalısınız.

Yukarıdaki örnek için çıktı:

escape

açıklama

Yukarıdaki örnekte, uzay gemisinin her zaman adımında nereye gittiğini gösteren bir harita:

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

Güneye gitti, batıya döndü, bir koridordan aşağıya indi, kuzeye döndü ve yerçekimi nedeniyle yüksek hızda gezegenlere dar bir şekilde kaçtı.


Muayene için daha fazla vaka

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

Kurallar, Düzenlemeler ve Notlar

Bu kod golf. Standart kod golf kuralları geçerlidir. Programlarınız yazdırılabilir ASCII'de yazılmalıdır. Herhangi bir harici veritabanına erişmenize izin verilmiyor.

İletimi Sonlandır


GİRİŞ bölümünün hemen üstündeki satırda bir yazım hatası var gibi görünüyor ... Sanırım gezegen mi demek istiyorsun? :-)
Gaffi

Aslında, tüm kısmi paragrafın silinmesi gerekiyordu, bilgiler çıktı bölümü altında tekrarlanır.
PhiNotPi

1
Biraz daha az değiştirilmiş fizik ile bunu daha iyi istiyorum ... Bu site de biraz güzel pahalı kayan nokta aritmetiği içeren daha fazla sorunla yapabilirdi.
counterclockwis'i

1
@ leftaroundabout Bu benim bir sonraki görevim olabilir.
PhiNotPi

Bir gezegene çarpmak için ne kadar yakın olması gerekir?
Peter Taylor

Yanıtlar:


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

Çözülmemiş (ve biraz yeniden düzenlenmiş) sürümü http://pastebin.com/yAKYvwQf adresinde bulabilirsiniz.

Çalışan sürüm: https://compilify.net/1n9 Bu, uyumluluk için çalıştırılacak şekilde biraz değiştirildi:

  • örtülü dizi oluşturma yok - ör .: new[]{1,2}
  • return <string>yerine kullanır Console.WriteLine, çünkü compilify.net böyle çalışır
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.