Araban sadece sağa döner!


49

Giriş

Engelli bir parkurda kaçak bir arabanın içinde sıkışıp kalmış olmanın talihsizliğine sahipsiniz. Aracın tüm özellikleri hassas değil, hasarlı direksiyon sistemi için tasarruf sağlıyor. Düz sürebilir veya sağa dönebilir. Araç güvenliğe yönlendirilebilir mi?

mekanik

Arabanız 8x8'lik bir haritanın sol üst köşesinde başlar ve sağ alt köşede güvenlik sağlamaya çalışıyor. Otomobilin 90 derecelik artışlarla ölçülen bir yönü (başlangıçta sağa) vardır. Araba iki işlemden birini gerçekleştirebilir:

  1. Bir kare ileri sür veya
  2. Saat yönünde 90 derece çevirin, sonra bir kare ileri doğru sürün

Otomobilin tek bir kare üzerinde 180 derecelik bir dönüş yapmak için yeterince keskin bir şekilde dönemediğini unutmayın.

Karelerin bazıları engeldir. Araba bir engel karesine girerse, çarpıyor. 8x8 parkurun dışındaki her şeyin engel olduğu varsayılır, bu nedenle parkurun dışına çıkmak çarpmaya eşdeğerdir.

Sağ alt kare, aracın engel parkurundan kaçmasına izin veren güvenli karedir. Başlangıç ​​meydanı ve güvenli meydanın engel olmadığı varsayılır.

Görev

Girişini engelleme kursunu temsil eden 8x8 dizisi (matris, liste listesi vb.) Alan bir program veya işlev yazmalısınız. Program bir Boole veya benzer bir şekilde hakikaten bir şey döndürür veya yazdırır. Otomobilin çarpmadan güvenli bir kareye ulaşması mümkün ise (yani, harita çözülebilirse), çıkış budur True, aksi halde False.

puanlama

Standart kod golf kuralları - kazanan en az baytlık koddur.

Bonuslar:

  • Çözülebilir bir harita için kodunuz, aracı güvenli bir kareye yönlendiren geçerli bir sürücü girişi dizisi çıkarırsa, puanınızdan 10 yüzde puan düşün. Örnek bir çıktı formatı olabilir SRSSR(Düz, Sağ, Düz, Düz, Sağ). Bu çıkış standart Trueçıktının yerine geçecektir .

  • Çözülemeyen bir harita için, kodunuzun çıktısı, bir çarpışmanın kaçınılmaz olduğu durumlar ile sonsuza dek engel parkurunda sonsuza kadar sürmenin mümkün olduğu durumlar arasında ayrım yaparsa, puanınızdan 10 yüzde puan düşün. Bir örnek çıktı Crash, bir çarpışma kaçınılmaz ise veya Stuckaraç sonsuza dek engel parkurunda sıkıştıysa olabilir. Bu çıkışlar Falseçözülemeyen bir harita için standart çıktının yerini alacak .

Örnek

Programa bunun gibi bir 8x8 dizi verilirse:

[[0, 0, 0, 0, 0, 1, 0, 0],
 [0, 0, 0, 0, 0, 0, 1, 0], 
 [1, 1, 0, 0, 0, 0, 0, 0], 
 [0, 1, 0, 1, 0, 0, 0, 0], 
 [0, 0, 1, 1, 0, 0, 0, 0], 
 [0, 0, 0, 0, 1, 0, 1, 0], 
 [0, 0, 0, 0, 0, 0, 1, 0], 
 [0, 1, 1, 0, 0, 0, 1, 0]]

Böyle bir harita olarak yorumlanır, siyah kareler engelleri gösterir:

görüntü tanımını buraya girin

Ve olası bir çözüm olabilir:

görüntü tanımını buraya girin

Bir çözüm bulunduğundan, program Truebu harita için geri dönmeli / yazdırmalıdır . Burada gösterilen hareketlerin sırası SSSSRSRRRSRSSRRRSSRSSS.


2
Bazı yazdı inanılmaz basit test durumları Crashve Stuck. Ne kadar zaman oldukları için buradalar . Satır 2 dolu, her şey boş -> Crash. Satır 7 dolu, her şey boş ->Stuck
undergroundmonorail

3
Yüzde puan (kafamın aksine) konusunda kafam karıştı . Her iki bonusu almak, puanınızı 0,9 ile çarpar. Her ikisini de almak, onu 0.8 veya 0.9 ^ 2 ile çarpıyor mu?
undergroundmonorail

3
Tabii, S ve C iyi. Çıktılarım sadece öneriydi.
fosgen

13
“İki yanlış haklı değil, üç sol yapıyor.” - Baba
HoosierEE

2
"Aracınız sadece sıfır veya üç sol yapabilir!"
feersum

Yanıtlar:


17

JavaScript (ES6) - 122 124 148 162 172 178 187 190 190 193 208 bayt

Bu kodun nasıl geliştirileceğine dair faydalı öneriler için Doktor ve DocMax'a teşekkür ederiz:

F=a=>(D=(x,y,d)=>!D[i=[x,y,d]]&&(D[i]=1,x-=~d%2,y-=~-~d%2,x*y==49||!((x|y)&8||a[y][x])&&(D(x,y,d)||D(x,y,~-d%4))),D(-1,0))

İade trueçözülebilir ve için (truthy) falseçözülemeyen için (falsy).

Yalnızca JavaScript 1.7 özellikleri nedeniyle bugün Firefox'ta çalışır.

Test Kurulu


1
Bu 193 bayt: D=(x,y,d,t,a)=>!t[i=x+y*8+d*64]&&(t[i]=1,x+=d==0?1:d==2?-1:0,y+=d==1?1:d==3?-1:0,x==7&&y==7||!((x|y)&~7||a[y][x])&&G(x,y,d,t,a));G=(x,y,d,t,a)=>D(x,y,d,t,a)||D(x,y,d+1&3,t,a);F=a=>G(0,0,0,[],a).
Doktor,

1
172: D=d=>!t[i=x+y*8+d/4]&&(t[i]=1,x+=d?d^2?0:-1:1,y+=d^1?d^3?0:-1:1,x==7&&y==7||!((x|y)&~7||b[y][x])&&G(x,y,d));G=(X,Y,d)=>D(d,x=X,y=Y)||D(d+1&3,x=X,y=Y);F=a=>G(0,0,0,b=a,t={})- Test edildi.
Doktor 15

1
@Optimizer Hala ikinci test durumu için doğru alıyorum [[0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]]. Bu yanlış vermeli.
ben ve

2
Çünkü olmasıdır xve yher iki globaller, sen ... sayfayı yeniden önce iki testcases koşamam
Doktoru

1
Sen değiştirerek 9 daha toplam kaydedebilirsiniz x+=d?d^2?0:-1:1ile x+=d&1?0:1-dve y+=d^1?d^3?0:-1:1ile y+=d&1&&2-d.
DocMax

10

Python 2 - 123 125 133 146 148 150 154 160

Truebaşarıda, Falsebaşarısızlıkta.

def f(h=1,v=0,b=0,x=0,y=0,c=[]):s=x,y,h,v;a=b,x+h,y+v,c+[s];return(s in c)==(x|y)&8==b[y][x]<(x&y>6or f(h,v,*a)|f(-v,h,*a))

Gibi giriş sağlamalısınız f(b=var_containing_board).

Lambda versiyonu - 154

0Başarısızlık, Truebaşarı için döndürür (sahte) .

F=lambda b,x=0,y=0,h=1,v=0,c=[]:0if[x,y,h,v]in c or x|y>7or x|y<0 or b[y][x]else x&y==7or F(b,x+h,y+v,h,v,c+[[x,y,h,v]])or F(b,x+h,y+v,-v,h,c+[[x,y,h,v]])

Fonksiyonu lambda'dan daha kısa yapmak için Will ve Brandon'a teşekkürler. Daha fazla yatay kaydırma eklemek için ayrıca: D

Üstün buruşma ve mantık için xnor'a teşekkürler!

Notu düzenle: b[y][x]Menzil dışına çıkarken asla yürütülmeyeceğine eminim . Kurulun dışında olduğumuz için tarihçe kontrolü s in cyapılacak False. Ardından sınır kontrolü (x|y)&8yapılacaktır 8. Öyleyse ==, ilk iki zaten farklı olduğundan python son değerini bile kontrol etmez .


1
İşlevsel sürüm, her ikisi de geri dönen iki if'leri birleştirebilir; Dönüş yalnız falsy olduğu None döndürür olarak, ayrıca lehine dönen .sadece 0 döndürür gerekmez;)
Will

Eğer çek çevirmek ise sen de her iki IFS birleştirebilirsiniz
Will

Her iki return ifadesini birleştirebilir misiniz?
Brandon,

1
@ Teşekkür ederim, bunu yapmanın daha iyi bir yolu olduğunu biliyordum: D Bana, sözdizimi hatası vermeyen bir yer bulamadım. Neden x|y>7orişe yaradığını anlayamıyorum ama işe x|y<0or
yaramadı

1
Sekizli bir edebi harfle başlayabilirsiniz 0o.
feersum

9

C (GNU-C), 163 bayt * 0.9 = 146.7

#C (GNU-C), 186 bayt * 0.9 = 167.4

Yeni sürümümde imzasız bir tamsayı yerine işaretli bir dosya kullanılıyor. Daha önce imzalı sağa kaymadan korktum, ancak işaret biti hedef kare olduğu için farkettim, bundan sonra ne olacağı önemli değil.

İşlev, 64 bitlik bir tamsayı biçiminde bir bit dizisini (olanlar engellenen kareleri temsil eder) alır. Bitler en az en önemlilerine göre bir kitap okuduğunuz şekilde düzenlenmiştir. Bir çarpışma için -1, sonsuza kadar sürüş için 0, sağ alt köşeye kaçmak için 1 döndürür.

g(long long o) {
    typeof(o) a=0,i=255,r=1,u=0,l=0,d=0,M=~0LLU/i,D;
    for( ;i--;d = D<<8&~o)
        a |= D = d|r,
        r = (r|u)*2&~M&~o,
        u = (u|l)>>8&~o,
        l = ((l|d)&~M)/2&~o;
    return a<0?:-!(d|r|u|l);
}

Test programı

f(long long o){typeof(o)a=0,i=255,r=1,u=0,l=0,d=0,M=~0LLU/i,D;for(;i--;d=D<<8&~o)a|=D=d|r,r=(r|u)*2&~M&~o,u=(u|l)>>8&~o,l=((l|d)&~M)/2&~o;return a<0?:-!(d|r|u|l);}
{
    char* s[] = {"Crash", "Stuck", "Escape"};
    #define P(x) puts(s[f(x)+1])
    L ex = 0x4640500C0A034020;
    P(ex);
    L blocked = 0x4040404040404040;
    P(blocked);

    L dead = 0x10002;
    P(dead);

    return 0;
}

Çıktı

Escape
Stuck
Crash

Python dizi-onaltılık dönüştürücü:

a2b=lambda(A):"0x%X"%sum(A[i/8][i%8]<<i for i in range(64))

1
memset(&M,~1,8)(14 karakter) ile değiştirin ( M=~(-1ULL/255)14 karakter).
R. ..

@R .. Güzel bir! Bundan -4 bayt.
feersum

2
Giriş formatını beğendim - çok havalı!
fosgen

P(0x00fefefefefefefe);= İçin 'kilitlenme' alıyorum ((Sağ üste düz atış, bir dönüş, düz köşeye. Aynı) P(0x00eeeeeeeeeeeeee);(4. sütunda çıkmaz). aBaşlangıçta atamanız gerektiğini sanmıyorum .

@tolos Satır / sütun ana emrini aktardınız. Üst satırın ve sağ sütunun açık olması için olması gerekir 0x7f7f7f7f7f7f7f00. Ayrıca başlatılması gerekir açünkü daha sonra yalnızca ek bitlerde ORing ile değiştirilir, bu nedenle başlangıçta istenmeyen bir bit ayarlayamam.
feersum

6

Python, 187 213

207 karakter, yazdırma yolu için% 10 bonus

b=map(ord," "*9+" ".join("".join("o "[i]for i in j)for j in input())+" "*9)
def r(p,d,s):
 p+=(1,9,-1,-9)[d]
 if b[p]&1<<d:b[p]^=1<<d;return(s+"S")*(p==79)or r(p,d,s+"S")or r(p,(d+1)%4,s+"R")
print r(8,0,"")

Test girişinde biraz farklı bir yol bulur: SSSSRSRSRRSSRSSRRSRSSRSSSSS

Genel yaklaşım ilk önce girişi boşluk ve os'ye çevirmektir . Boşlukların altıgen altı vardır 20, bu yüzden dört alt bitin tümü ayarsızdır. oonaltılık bir değere sahiptir 6F, bu yüzden düşük dört bitin hepsi ayarlanır.

oTahtanın etrafına bir s sınırı yerleştirilir, böylece kötü endekslerden endişe etmemize gerek kalmaz.

Tahta üzerinde yürürken, o taraftan gelirken geçmemize izin verilip verilmediğini görmek için her bir döşemedeki bitleri kullanırız. Bu şekilde sonsuz döngülerden kaçınırız. Çıkış yönünüz giriş yönünüze bağlı olduğundan döşeme başına tek bir boole olması yeterli değildir, böylece döşemeler iki kez ziyaret edilebilir.

Daha sonra güvenli bir yol için özyinelemeli bir araştırma yaparız.


3
"Aracınız 8x8 haritanın sol üst köşesinde başlıyor" - 9yerine kod yazamaz w=len(b[0])+1mısınız?
FryAmTheEggman

@FryAmTheEggman teşekkür ederim, nasıl görmezden gelebilirdim? : D
Will

Eğer üçlü deyimi tersine çevirmek ve yerini alabilir p==79ile p-79. Bundan önce boşluk olmadan bu iki yolu da yaparken sözdizimi hatası aldım else. Bence bu numara sadece işe yarıyor if.
FryAmTheEggman

@FryAmTheEggman Derinlik testinin tekrarlamadan önce yapması gerektiğini düşünüyorum. Bunun yerine Boolean ile çarpma ile oynuyorum.
Will

7
Sadece çok temiz bir numara buldum. Muhtemelen bunu biliyorsunuz -~x== x+1ancak her iki unary operatörü çarpma, bölme ve modüllerden daha yüksek önceliğe sahip! Öyle (d+1)%4olabilir -~d%4! Bu da işe yarayacaktı x-1ama ~-xonun yerine kullanacaktı .
FryAmTheEggman

6

Javascript - 270 - 20% = 216 262 - 20% = 210 bayt

Her iki primi de kazanan (ve saçma bir yığın derinliğine yol açmayan en az bir çözüm olması gerektiğinden) ...

minified:

V=I=>{n=[N=[0,0,0]];v={};v[N]='';O='C';for(S='';n[0];){m=[];n.map(h=>{[x,y,d]=h;D=i=>[1,0,-1,0][d+i&3];p=v[h];for(j=2;j--;){O=v[c=[X=x+D(j),Y=y+D(3-3*j)),d+j&3]]?'K':O;J=X|Y;J<0||J>7||I[Y][X]||v[c]?O:(m.push(c),v[c]=p+'SR'[j])}S=(x&y)>6?p:S});n=m;}return S||O;};

Expanded:

V = I => {
    n = [N=[0,0,0]];
    v = {};
    v[N] = '';
    O = 'C';

    for( S = ''; n[0]; ) {
        m = [];
        n.map( h => {
            [x,y,d] = h;
            D = i => [1,0,-1,0][d+i&3];
            p = v[h];
            for( j = 2; j--; ) {
                O = v[c = [X = x+D(j),Y = y+D(3-3*j),d+j&3]] ? 'K' : O;
                J = X|Y;
                J<0 || J>7 || I[Y][X] || v[c] ? O : (
                    m.push( c ),
                    v[c] = p + 'SR'[j]
                );
            }

            S = (x&y) > 6 ? p : S;
        } );
        n = m;
    }
    return S || O;
};

v(x,y,d)(x, y) koordinatına ve giriş yönüne karşılık gelen durum üçlüsü olan tuşlara sahip bir etikettir d. Her anahtar, anahtarın temsil ettiği duruma ulaşmak için gereken S(düz) ve R(sağa dönüş) hareketlerinin dizesi olan ilişkili bir değere sahiptir .

Kod ayrıca nhenüz işlenmemiş üçlü yığınını (değişken olarak ) tutar. Yığın başlangıçta, aracın (0,0) hücresinde doğru baktığı duruma karşılık gelen sadece üçlü (0,0,0) içerir. Dış döngüde, for( S = ... )rutin işlenmemiş üçlü kalıp kalmayacağını kontrol eder. Eğer öyleyse, işlenmemiş her üçlü iç döngüden geçirir n.map( ....

İç döngü beş şey yapar:

  1. iki olası hareketi (dümdüz sürüş, sağa dönüş) mevcut durumdan hesaplar
  2. Bu hareketlerden herhangi biri, karma tabloda zaten kayıtlı olan bir duruma yol açarsa, daha sonraki işlemler için göz ardı edilir. KAncak FALSE çıkışını (sıkışmış) olarak işaretleriz , çünkü aracın çarpışmadan sonsuza kadar daire çizmeye devam edebileceği en az bir döngü bulduk.
  3. eğer bir devlet yasal ve yeni ise, dış döngünün bir sonraki geçişi için karma ( v) ve işlenmemiş üçlü yığınına ( ) eklenir.m
  4. yeni durum kaydedildiğinde v, değeri kaynak durumun (hamle sırasının) artı Rveya Smevcut hamle bazında değerine ayarlanır.
  5. Eğer xve yvardır 7, kaynak duruma (menşeli durumuna ulaşmak için geçen hareket dizisi) değeri kopyalanır Sbu hareket dizisi soruna bir çözüm için,

İç döngü sona erdikten sonra n(yığın) m(yeni yığın) ile değiştirilir.

Dış döngü sona erdikten sonra (yeni durumlara erişilmez), işlev çıktısını döndürür. (7,7) hücresine ulaşıldıysa, Sbu hücreye giden bir dizi hamle içerecektir ve bu çıkar. Hücreye ulaşılmazsa, Sboş dize olacak ve rutin çıkışa düşüyor O, bu, Kyalnızca bir döngü bulunursa (sıkışmış) ve Caraba kaçınılmaz şekilde çarpışırsa (çarpışma) içerecektir.


1
OP’den onay aldığınızda, C Crash ’ve ame Stuck’ adını C C ’ve S S olarak değiştirebilirsiniz.
FryAmTheEggman

Ah. O zaman biraz tasarruf eder. Teşekkürler. ;)
COTO

Kodunun ne yaptığını açıklayabilir misin? Başlarını veya kuyruklarını yapamam.
fosgen

Phosgene: Ayrıntılı bir açıklama satır içi ekledim.
COTO

Bu akıllıca bir prosedür. Hiçbir şey boşa gitmiyor.
fosgen

4

Python 339 -% 10 = 305 bayt

Başarı ile erkenden sonlandırılan özyinelemeli bir derinlik-ilk arama kullandım exit. Ayrıca şeklinde başarısına yolunu baskı 00001010101010101010101110100111001000, 0düz için 1hakkı için. Cevap, derinlik ilk önce olduğu için optimalden daha uzun olacaktır. Algoritmaya yönelik bazı optimizasyonların bayt sayımını biraz azaltacağından eminim.

b=input()
D=[(-1,0),(0,-1),(1,0),(0,1)]
def a(l):
 x,y=0,0
 v=2
 for d in l:
  if d=='1':v=(v+1) % 4
  x+=D[v][0]
  y+=D[v][1]
  if x<0 or x>7 or y<0 or y>7:return 0,x,y
  if b[y][x]:return -1,x,y
 return 1,x,y
def c(l):
 if len(l) < 39:
  t,x,y=a(l)
  if t==1:
   if (x,y)==(7,7):
    print l;exit(0)
   c(l+"0")
   c(l+"1")
c("")
print 0

3
Bu Python 2 olduğundan, olduğu gibi, girintiler için sekmeler ve boşluklar karıştırabilirsiniz a'ın fordöngü. Ayrıca operatörlerin etrafında boşluklara da ihtiyacınız yoktur, örneğin (v+1) % 4-> (v+1)%4. Satırda ;hiç ifveya yoksa for, vb. Varsa, birden fazla ifadeyi bir satırda birleştirebilirsiniz c(l+"0");c(l+"1"). Diğer bazı çoraplar: x,y,v=0,0,2, x|y>7 or x|y<0, x==y==7. İyi şanslar :)
FryAmTheEggman
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.