O yılan nereye gidiyor?


35

Herhangi bir sayıdaki sütun ve satırın iki boyutlu bir dizisini alan bir işlevi (mümkün olduğunca az bayt kullanarak) yazın:

  • 0 boş bloğu temsil eder,
  • 1 yılan bloğunu temsil eder.

İşlev, yılanın kat ettiği olası yolların sayısını döndürmelidir.

Örnek 1:

Giriş:

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

Çıktı: 2

Yukarıdaki örnekte, işlev dönecektir, 2çünkü cevap aşağıdakilerden biridir:

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

Örnek 2:

Giriş:

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

Çıktı: 6

Bu örnekte, işlev geri dönecektir, 6çünkü cevap aşağıdakilerden biridir:

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

Not:

Girişi değerlendirirken, aşağıdakileri varsayabilirsiniz:

  • Sütunları temsil eden diziler her zaman aynı boyutlara sahip olacaktır (yani diziler dikdörtgendir);
  • En az 1 geçerli yol var;
  • Yılan kenarlardan geçemez (bazı yılan versiyonlarında olduğu gibi);
  • Yılan her zaman en az 2 blok olacak;
  • Yılan çapraz olarak hareket edemez;
  • Yollar yönlendirildi. (yani, farklı konumlarda biten, ancak tam olarak aynı görünen iki yol aynı yol değildir, toplamı ekler)

13
PPCG'ye Hoşgeldiniz! Güzel ilk meydan okuma.
Laikoni

5
Küçük not: "Her zaman en az bir satır olacak ve bir sütun olacak", yılanın her zaman en az 2 bloğa sahip olması koşuluyla, gereksizdir.
Stewie Griffin

2
Önerilen test durumları: @StewieGriffin ve tarafından verilen [[0,0,1,1],[0,0,1,1],[0,0,1,1]]. Çoğu cevaplar 16 vermek, ama bir 15. verir
Kevin Cruijssen

2
Görünen o ki, şimdiye kadar herkes (benimle birlikte), farklı pozisyonlarda biten 2 yolun aynı yolla aynı olduğu anlamına geldiğini varsayıyor. Bunun açıkça belirtilmesi gerektiğini düşünüyorum.
Arnauld

2
@Arnauld - bu doğru. Farklı konumlarda biten ancak tam olarak aynı görünen iki yol aynı yol değildir , toplamı ekleyecektir. Örnekte yanılmıyorsam toplam 16 olmalıdır - şu an doğru bir şekilde hesaplayamıyorum ama bu konuyu anlıyorsunuz
Adelin

Yanıtlar:


11

Wolfram Dili (Mathematica) , 16 + 83 = 99 bayt

Kütüphane içe aktarma ifadesi (16 bayt):

<<Combinatorica`

Gerçek işlev gövdesi (83 bayt):

Length@HamiltonianCycle[MakeGraph[#~Position~1~Join~{1>0},##||Norm[#-#2]==1&],All]&

Çevrimiçi deneyin!


Sorunun sadece grafikteki Hamilton yolunun sayısını sorduğunu unutmayın.

Ancak, (nedense) HamiltonianPathişlev, yönlendirilmiş grafikle gerçekten çalışmaz ( örnek ). Bu nedenle, bu Mathematica.SE sorusunda açıklanan geçici çözümü kullandım :

  • TrueDiğer tüm köşelere bağlı bir tepe noktası (adı verilen ) ekleyin .
  • Elde edilen grafikteki Hamiltonian döngüsü sayısını sayın.

Grafik kullanılarak MakeGraph(sinir bozucu olarak doğrudan eşdeğer bir yerleşik yoktur), boolean işlevi kullanılarak oluşturulur ##||Norm[#-#2]==1&, bu Trueyalnızca argümanlardan biri Trueveya iki köşe arasındaki mesafe olup olmadığını döndürür 1.


Tr[1^x]yerine kullanılamaz Length@xve <2yerine kullanılamaz ==1.


HamiltonianPathGrafik yönlendirilmemişse, işlev gövdesi 84 bayt (geçerli gönderimden tam olarak 1 bayt daha fazla) alırsa kullanılabilir :

Length@HamiltonianPath[MakeGraph[#~Position~1,Norm[#-#2]==1&,Type->Undirected],All]&

Çevrimiçi deneyin!


10

JavaScript (ES6), 154 134 bayt

m=>m.map((r,Y)=>r.map(g=(_,x,y,r=m[y=1/y?y:Y])=>r&&r[x]&&[-1,0,1,2].map(d=>r[r[x]=0,/1/.test(m)?g(_,x+d%2,y+~-d%2):++n,x]=1)),n=0)|n/4

Çevrimiçi deneyin!

Nasıl?

Yöntem

Mümkün olan her hücreden başlayarak, matrisi doldurup yoldaki tüm hücreleri temizleriz. Ne zaman matris artık 1 'ler içermiyorsa , olası yolların n sayısını artırırız.

Her geçerli yol son hücre üzerinde seçilen yönden dolayı 4 kez sayılır, ki bu aslında önemli değildir. Bu nedenle, sonuç n / 4'tür .

Özyinelemeli fonksiyonu

Özyinelemeli işlevi g () ikinci haritanın geri çağrısından () çağırmak yerine ...

m=>m.map((r,y)=>r.map((_,x)=>(g=(x,y,r=m[y])=>...g(x+dx,y+dy)...)(x,y)))

... biz özyinelemeli fonksiyon tanımlama ) g ( geri arama doğrudan bir harita () :

m=>m.map((r,Y)=>r.map(g=(_,x,y,r=m[y=1/y?y:Y])=>...g(_,x+dx,y+dy)...))

Oldukça uzun formül rağmen y=1/y?y:Ybaşlangıç değerini ayarlamak için gerekli olan y , bu genel 2 bayt kaydeder.

Yorumlanan kod

m =>                           // given the input matrix m[][]
  m.map((r, Y) =>              // for each row r[] at position Y in m[][]:
    r.map(g = (                //   for each entry in r[], use g() taking:
      _,                       //     - the value of the cell (ignored)
      x,                       //     - the x coord. of this cell
      y,                       //     - either the y coord. or an array (1st iteration),
                               //       in which case we'll set y to Y instead
      r = m[y = 1 / y ? y : Y] //     - r = the row we're currently located in
    ) =>                       //       (and update y if necessary)
      r && r[x] &&             //     do nothing if this cell doesn't exist or is 0
      [-1, 0, 1, 2].map(d =>   //     otherwise, for each direction d,
        r[                     //     with -1 = West, 0 = North, 1 = East, 2 = South:
          r[x] = 0,            //       clear the current cell
          /1/.test(m) ?        //       if the matrix still contains at least one '1':
            g(                 //         do a recursive call to g() with:
              _,               //           a dummy first parameter (ignored)
              x + d % 2,       //           the new value of x
              y + ~-d % 2      //           the new value of y
            )                  //         end of recursive call
          :                    //       else (we've found a valid path):
            ++n,               //         increment n
          x                    //       \_ either way,
        ] = 1                  //       /  do r[x] = 1 to restore the current cell to 1
      )                        //     end of map() over directions
    ),                         //   end of map() over the cells of the current row
    n = 0                      //   start with n = 0
  ) | n / 4                    // end of map() over the rows; return n / 4

10

Jöle , 12 11 bayt

ŒṪŒ!ạƝ€§ÐṂL

Çevrimiçi deneyin!


Açıklama.

ŒṪ               Positions of snake blocks.
  Œ!             All permutations.
                 For each permutation:
    ạƝ€             Calculate the absolute difference for each neighbor pair
       §            Vectorized sum.
                 Now we have a list of Manhattan distance between snake
                    blocks. Each one is at least 1.
        ÐṂL      Count the number of minimum values.
                    Because it's guaranteed that there exists a valid snake,
                    the minimum value is [1,1,1,...,1].

Yeni özellikler son derece yararlı olduğunu kanıtladı.
user202729

Bir bayt kurtarmak §ỊMLyerine, nasıl §ỊP€Sçalışması gerektiğini düşünüyorum?
Jonathan Allan

... ya §ÐṂLda biraz daha hızlı.
Jonathan Allan,

@JonathanAllan Yalnızca sonuç sıfır değilse çalışır.
user202729

@JonathanAllan Bu yüzden aslında işe yarıyor.
user202729

8

Piton 2 , 257 246 241 234 233 227 214 210 bayt

lambda b:sum(g(b,i,j)for j,l in e(b)for i,_ in e(l))
e=enumerate
def g(b,x,y):d=len(b[0])>x>-1<y<len(b);c=eval(`b`);c[d*y][d*x]=0;return d and b[y][x]and('1'not in`c`or sum(g(c,x+a,y)+g(c,x,y+a)for a in(1,-1)))

Çevrimiçi deneyin!


Kayıtlı

  • -8 bayt, Kevin Cruijssen sayesinde
  • -14 bayt, user202729 sayesinde


1
İş için doğru dil?
Neil

5

Python 2, 158 bayt

E=enumerate
g=lambda P,x,y:sum(g(P-{o},*o)for o in P if x<0 or abs(x-o[0])+abs(y-o[1])<2)+0**len(P)
lambda L:g({(x,y)for y,r in E(L)for x,e in E(r)if e},-1,0)

Çevrimiçi deneyin!


3

Haskell , 187 155 bayt

r=filter
l=length
(a,b)?(x,y)=abs(a-x)+abs(b-y)==1
l#x=sum[p!r(/=p)l|p<-x]
p![]=1
p!l=l#r(p?)l
f x|l<-[(i,j)|i<-[0..l x-1],j<-[0..l(x!!0)-1],x!!i!!j>0]=l#l

Çevrimiçi deneyin!

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.