Çin daması en uzun hamle


12

Gelen Çince dama , bir parça, herhangi bir başka parça üzerinde sıçrama veya şerbetçiotu bir dizi yaparak hareket edebilir. Göreviniz mümkün olan en uzun atlama sırasını bulmaktır.

Giriş

Her biri bir tahta üzerinde bir yeri temsil eden 121 sıfır veya bir dizi. Sıfır, yerin boş olduğu anlamına gelir; bir yer işgal edilmiş demektir. Pozisyonlar soldan sağa doğru listelenir; yukarıdan aşağıya. Örneğin, giriş bu kurulum olurdu

1011110011000001000000000000000000000000100000000001000000000000000000000000000001000000000000000000000001000001100111111

Açıklama:

En üstteki yer yeşil bir parça tarafından işgal edilir, bu nedenle girişteki ilk basamaktır 1. İkinci sıranın bir boş pozisyonu ve sonra bir dolu pozisyonu vardır, bu yüzden sırada 01gelir. Üçüncü sıra tamamen dolu, yani 111. Dördüncü sıranın iki boş ve iki işgal edilmiş alanı vardır (soldan sağa doğru) 0011. Sonra 0bir sonraki satır için beş , a 1ve yedi geliyor 0vb.

Bu kurulumda olduğu gibi, yukarı dönük bir köşe var. Tahtada herhangi bir sayıda parça olabilir (1'den 121'e kadar). Farklı renkteki parçaların farklı temsil edilmediğini unutmayın.

Çıktı

Tahtadaki herhangi bir parçayı kullanarak yasal bir şeridin maksimum uzunluğu. Aynı yeri bir kereden fazla ziyaret edemezsiniz (başlangıç ​​ve bitiş konumları dahil). Ancak, aynı parçayı bir kereden fazla atlayabilirsiniz. Yasal bir sıçrama yoksa çıktı 0. Yasal bir hop-olmayan hareket olup olmadığını düşünmeyin.

Örneğin, yukarıda açıklanan kurulumun çıktısıdır 3.

Giriş ve çıkış stdin ve stdout, komut satırı bağımsız değişkenleri, işlev çağrıları veya benzer herhangi bir yöntemle yapılabilir.

Test Durumları

Giriş:

0100000010000000000000000100000000000000000000000000000001010010000000000000000000000101000000000000000000100000000100001

Çıktı: 0(iki parça yan yana değildir)


Giriş:

0000000000111100000000011100000000011000000000100000000000000000000000000000000000000000000000000000000000000000000000000

Çıktı: 1(sol üst köşedeki bir oyuncu için ilk kurulum)


Bunu büyük teyzemle oynuyorum; ikimiz de oldukça iyiyiz. Bu ilginç bir zorluk.
cjfaure

1
Belki de girdinin nasıl saklandığı / hangi bitlerin nereye gittiğiyle ilgili daha fazla bilgi belirtmelisiniz.
TheDoctor

Hangi parçaları "atlayabilirsiniz"? Annem ve ben eskiden oynadığımız gibi, yolda herhangi bir parça olmadığı sürece, herhangi bir mesafeden (atladığınız parçanın karşı noktasına) herhangi bir mesafeden 6 parçadan birine atlayabilirsiniz. o hop için bir yol. Diğerleri sadece bitişik parçaların üzerine atlayabileceğinizi oynarlar.
Joe Z.

1
@TheDoctor Daha ayrıntılı bir açıklama ekledim.
Ypnypn

Bir ayrıntıyı açıklayabilir misiniz: Aynı pozisyonu iki kez işgal etmeme izin veriliyor mu? Sonsuz döngü yapamayacağımı varsayıyorum, ancak sola-sağa hareket eden bir yere vurabilir ve daha sonra tekrar sola-sağa hareket ederek vurabilirsem, olasılıkları açar.
Devon Parsons

Yanıtlar:


1

Perl, 345 322

Düzenleme: hafif golf.

Daha fazla test örneği iyi olurdu, ancak şimdilik işe yarıyor gibi görünüyor. Gerekirse daha sonra yorum ekleyeceğim. Okunabilirlik için yeni satırlar ve girinti ile:

$_=<>;
$s=2x185;
substr$s,(4,22,unpack'C5(A3)*','(:H[n129148166184202220243262281300')[$i++],0,$_ 
    for unpack A.join A,1..4,13,12,11,10,9..13,4,3,2,1;
$_=$s;
sub f{
    my(@a,%h)=@_;
    $h{$_}++&&return for@a;
    $-+=$#a>$-;
    $s=~/^.{$a[0]}$_/&&f($+[1],@a)
        for map{("(?=.{$_}1.{$_}(0))","(?<=(0).{$_}1.{$_}.)")}0,17,18
}
f$+[0]while/1/g;
print$-

Birkaç test vakası ekledim.
Ypnypn

Bunlar iyi çalışıyor, ama çok kolay :-).
user2846289

2

C, 262 260

Golf kodu (hata ayıklama kodu ve gereksiz boşluk kaldırıldı. Stdin üzerinden girişten komut satırı üzerinden girişe değiştirildi ve orada i değişkenini bildirme fırsatından yararlandı. Son düzenleme: kod, foriki noktalı virgül kaydetmek için döngülerin köşelerine taşındı .)

t[420],j,l,x,y;f(p,d){int z,q,k;for(k=6;k--;t[q]&!t[p+z]?t[q]=0,f(q,d+1),t[q]=1:0)z="AST?-,"[k]-64,q=p+z*2;l=d>l?d:l;}main(int i,char**s){for(i=840;i--;x>3&y>5&x+y<23|x<13&y<15&x+y>13?i>420?t[i-420]=49-s[1][j++]:t[i]||f(i,0):0)x=i%20,y=i/20%21;printf("%d",l);}

açıklama

Bu, program başladığında başlangıçta sıfırlarla dolu olan 20x21 kartına dayanır (bu ASCII sanatı programın değiştirilmiş bir sürümü tarafından oluşturuldu ve idöngü aşağı doğru sayarken, sıfır sağ alt köşede bulunur):

....................
....................
...............#....
..............##....
.............###....
............####....
.......#############
.......############.
.......###########..
.......##########...
.......#########....
......##########....
.....###########....
....############....
...#############....
.......####.........
.......###..........
.......##...........
.......#............
....................
....................

Döngü i, bir karenin gerçekte dama tahtasına ait olup olmadığını hesaplamak için x ve y tuşlarını kullanarak bu tahtadan iki kez geçer (bu, x ve y cinsinden 6 ayrı eşitsizlik gerektirir).

Eğer öyleyse, ilk turda kareleri doldurur, 0bir 1(işgal 1edilmiş) için bir 0( falsy) ve bir (boş) için bir ( doğruluk) koyar . Bu ters çevirme önemlidir, çünkü sınır dışı tüm kareler zaten 0 içerir, bu da işgal edilen karelere benzedikleri ve belirli bir kontrole gerek kalmadan atlanamayacakları açıktır.

İkinci turda, kare işgal edilirse (0 içerir) f, hareketleri arayan işlevi çağırır .

fifadede kodlanmış +/- 1 (yatay), +/- 20 (dikey) ve +/- 19 (diyagonal) ile kodlanmış 6 olası yönde yinelemeli olarak arama yapar "AST?-,"[k]-64. İsabet bulduğunda, kendisini tekrar tekrar çağırmadan önce bu hücreyi 0 (dolu) olarak ayarlar, ardından işlev döndürüldüğünde hücreyi 1 (boş) olarak ayarlar. Bu hücreye bir kereden fazla atlamayı önlemek için, yinelemeli çağrıdan önce hücre değeri değiştirilmelidir.

Kod çözülmemiş kod

char s[999];                           //input string.
t[420],i,j,l,x,y;                      //t=board. i=board counter, j=input counter. l=length of longest hop found so far.

f(p,d){                                //p=position, d= recursion depth.
  //printf("%d,%d ",p,d);              //debug code: uncomment to show the nodes visited.
  int k,z,q;                           //k=counter,z=displacement,q=destination
  for(k=6;k--;)                        //for each direction
    z="AST?-,"[k]-64,                  //z=direction
    q=p+z*2,                           //q=destination cell
    t[q]&!t[p+z]?                      //if destination cell is empty (and not out of bounds) and intervening cell is full
      t[q]=0,f(q,d+1),t[q]=1           //mark destination cell as full, recurse, then mark it as empty again.
      :0;
  l=d>l?d:l;                           //if d exceeds the max recorded recursion depth, update l
}

main(){
  gets(s);                             //get input
  for(i=840;i--;)                      //cycle twice through t
    x=i%20,                            //get x
    y=i/20%21,                         //and y coordinates
    x>3&y>5&x+y<23|x<13&y<15&x+y>13?   //if they are in the bounds of the board
      i>420?
        t[i-420]=49-s[j++]             //first time through the array put 0 for a 1 and a 1 for a 0 ('1'=ASCII49)
        :t[i]||f(i,0)                  //second time, if t[i]=0,call f(). 
       //,puts("")                     //puts() formats debug output to 1 line per in-bounds cell of the board
      :0;
  printf("%d",l);                      //print output
}
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.