Kararlı Yaşam Oyunu


19

Meydan okuma:

0s ve 1s'lik bir matris (veya 2d dizisi) verildiğinde, Conway'in yaşam oyununun sabit bir duruma ulaşması için gereken adım sayısını veya hiç birine ulaşmazsa -1 sayısını çıktılayın. Kararlı bir durum, her adımda hiçbir hücrenin açılmadığı veya kapatılmadığı bir durumdur. Oyun, verilen matriste, üst ve alt bağlı ve yanlar bağlı olarak çalışmalıdır. (yani 4x3'lük bir matris verildiğinde bir 4x3'lük torus üzerinde çalışmalıdır) Giriş matrisi 15x15'ten daha büyük olmayacaktır.

Not: Matris kararlı bir durumda başlarsa, çıkış 0 olmalıdır.

Örnekler:

Giriş:

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

Çıktı:

2

İşlem: (bunun görüntülenmesine gerek yoktur)

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

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

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

Giriş:

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

Çıktı:

2

Süreci:

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

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

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

Giriş:

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

Çıktı:

-1

Süreci:

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

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

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

sonsuza kadar tekrarlamak

Giriş:

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

Çıktı:

4

Süreci:

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

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

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

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

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

Giriş:

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

Çıktı:

0

Süreci:

Başlangıç ​​durumu sabittir.

Yaşam Oyunun Kuralları

Kapalı (0) olan bir hücre (1) hücresinin tam olarak üç yanındaysa, açıktır. Aksi takdirde kapalı kalır. Açık olan bir hücre karelerde 2 veya 3'ün yanındaysa, açıktır. Aksi takdirde kapalıdır.


Öyleyse, desen sonsuza dek tekrarlanırsa ne çıkarılmalıdır?
Monica'nın Davası

2
Olası giriş formatları? Matris boyutlarında sınır var mı? Değilse, 100x100 matrisimiz varsa ne olur? Ayrıca, muhtemelen kendi kendine yeten soruya Yaşam Oyunu kurallarının bir özetini koymalısınız.
El'endia Starman

3
Ah anlıyorum. Örneklerden birini yanlış okudum. Yine de başka bir soru - hangi noktada sabit hale gelmediğini varsaymalıyız? Çünkü eminim ki yüzlerce ya da binlerce tekrardan sonra kararlı hale gelen pek çok model vardır. Bunun için bir kategori bile var: Methuselah
Monica'nın Davası

18
Eminim bu meydan okuma aslında "durma problemini çöz" soruyor.
Mego

6
250 nesli göstermek için bir karşı örnek her zaman yeterli değildir: 15 ila 14 matris için, aksi takdirde boş bir arenada tek bir planör orijinal durumuna geri dönmek için 15 * 14 * 4 = 840 nesil alacaktır. Bu uzun yolun sonu 2 x 2 blok tarafından engellenirse, planör istikrarlı bir konfigürasyon bırakarak imha edecektir. Bu, başlangıçta planörü yok etmekten kaçınmak için yolun sonundan birkaç satır kısa olacak, ancak istikrardan önce hala 600 nesilden fazla olacak.
trichoplax

Yanıtlar:


10

Mathematica, 130 129 bayt

#&@@FirstPosition[Partition[CellularAutomaton[{224,{2,{{2,2,2},{2,1,2},{2,2,2}}},{1,1}},#,2^Length[Join@@#]],2,1],{x_,x_},0,1]-1&

Sonsuza kadar (ve çok fazla bellek) alacak çünkü 4x4'den fazla giriş denemenizi tavsiye etmem .

açıklama

Bu basitçe hayat oyununu taklit 2 N adımda , N giriş hücre sayısıdır. Bu, sistem kararlı bir duruma geçerse, sisteme ulaştığımızı garanti eder. Daha sonra, simüle edilmiş tarihte birbirini takip eden özdeş devletlerin ilk çiftini buluruz.

Şimdi kodu inceleyelim:

2^Length[Join@@#]

Bir 2D listesini düzleştirmek için kullanıldığından , bu 2 N'yi hesaplar Join@@.

CellularAutomaton[{224,{2,{{2,2,2},{2,1,2},{2,2,2}}},{1,1}},#,...]

Bu, 2 N kuşaktır Yaşam Oyununu simüle eder . 3x3 matrisi, bütüncül bir 2D otomatının mahallesini belirtir ve 224standart Hayat Oyunu'nun kural numarasıdır. Mathematica.SE'de bu sayının nasıl hesaplanacağı hakkında yazdım .

Partition[...,2,1]

Bu, tüm ardışık (örtüşen) kuşak çiftlerini alır.

FirstPosition[...,{x_,x_},0,1]

Bu, 0hiçbirinin bulunup bulunmadığını varsayılan olarak belirleyen ve aramayı derinlikle sınırlayan ilk özdeş nesil çiftini bulur 1. Böyle bir çifti ise edilir bulundu, sonuç olsa bir listede döndürülür. Bu yüzden kullanıyoruz:

#&@@...

Bu listeden ilk öğeyi çıkarmak için ( 0atomik olan varsayılan değeri bundan etkilenmez).

...-1

Sonunda bir tane çıkarırız çünkü meydan okuma 0temelli endeksler ve -1başarısızlık bekler .


8

Lua 531 509 488 487 464 424 405 404 bayt

Kim muazzam bir teslimiyet ister? \Ö/

Düzenleme: Geliştirilmiş, ancak artık golf nasıl bilmiyorum, bu yüzden ... açıklamalar geliyor yorum eklendi :)

@ KennyLau'nun yardımıyla ~ 60 bayt kaydedildi

adlandırma ile küçük bir golf kesici bir daha bayt aiçine Yinlined onaltılı dönüşümünü önlemek için

function f(m)c={}t=table.concat::z::c[#c+1]={}p=c[#c]Y={}for i=1,#m do k=m[i]p[#p+1]=t(k)Y[i]={}for j=1,#k
do v=m[i%#m+1]l=j%#k+1w=m[(i-2)%#m+1]h=(j-2)%#k+1Y[i][j]=v[l]+k[l]+w[l]+v[h]+v[j]+w[h]+w[j]+k[h]end
end s=''for i=1,#m do k=m[i]for j=1,k do
x=Y[i][j]k[j]=k[j]>0 and((x<2or x>3)and 0or 1)or (x==3 and 1or 0)end
s=s..t(k)end for i=1,#c do
if(s==t(c[i]))then return#c>i and-1or i-1
end end goto z end

Ungolfed

function f(m)                -- takes a 2D array of 0 and 1s as input
  c={}                       -- intialise c -> contains a copy of each generation
  t=table.concat             -- shorthand for the concatenating function 
  ::z::                      -- label z, used to do an infinite loop
    c[#c+1]={}               -- initialise the first copy 
    p=c[#c]                  -- initialise a pointer to this copy
    a={}                     -- initialise the 2D array of adjacency
    for i=1,#m               -- iterate over the lines of m
    do
      k=m[i]                 -- shorthand for the current line
      p[#p+1]=t(k])          -- saves the current line of m as a string
      a[i]={}                -- initialise the array of adjacency for the current line
      for j=1,#k             -- iterate over each row of m
      do
                             -- the following statements are used to wraps at borders
        v=m[i%#m+1]          -- wrap bottom to top
        l=j%#k+1             -- wrap right to left
        w=m[(i-2)%#m+1]      -- wrap top to bottom
        h=(j-2)%#k+1         -- wrap left to right

        a[i][j]= v[l]        -- living cells are 1 and deads are 0
                +k[l]        -- just add the values of adjacent cells
                +w[l]        -- to know the number of alive adjacent cells
                +v[h]
                +v[j]
                +w[h]
                +w[j]
                +k[h]
      end
    end

    s=''                     -- s will be the representation of the current generation
    for i=1,#m               -- iterate over each line
    do
      k=m[i]                 -- shorthand for the current line
      for j=1,#k             -- iterate over each row
      do
        x=a[i][j]            -- shorthand for the number of adjacent to the current cell
                             -- the next line change the state of the current cell
        k[j]=k[j]>0          -- if it is alive
                and((x<2     --   and it has less than 2 adjacent
                    or x>3)  --   or more than 3 adjacent
                  and 0      --     kill it
                  or 1)      --     else let it alive
                or           -- if it is dead
                  (x==3      --   and it has 3 adjacent
                  and 1      --     give life to it
                  or 0)      --     else let it dead
      end
      s=s..t(k)              -- save the representation of the current line
    end
    for i=1,#c               -- iterate over all the generation done until now
    do                       
      if(s==t(c[i]))         -- if the representation of the current generation
      then                   -- is equal to one we saved
        return#c>i           -- check if it is the latest generation
              and-1          -- if it isn't, it means we are in a loop -> return -1
              or i-1         -- if it is, we did 2 generations without changing
                             --  -> return the number of generation
      end
    end
  goto z                     -- if we reach that point, loop back to the label z
end

Test senaryoları

İşte bazı test senaryoları

function f(m)c={}t=table.concat::z::c[#c+1]={}p=c[#c]a={}for i=1,#m do k=m[i]p[#p+1]=t(k)a[i]={}for j=1,#k
do v=m[i%#m+1]l=j%#k+1w=m[(i-2)%#m+1]h=(j-2)%#k+1
a[i][j]=v[l]+k[l]+w[l]+v[h]+v[j]+w[h]+w[j]+k[h]end
end s=''for i=1,#m do k=m[i]for j=1,k do
x=a[i][j]k[j]=k[j]>0 and((x<2or x>3)and 0or 1)or (x==3 and 1or 0)end
s=s..t(k)end for i=1,#c do
if(s==t(c[i]))then return#c>i and-1or i-1
end end goto z end




print(f({{0,0,0},{0,1,1},{0,1,0}}))
print(f({{0,1,0,0},{0,1,0,0},{0,1,0,0},{0,0,0,0}}))
-- 53 generation, 15x15, takes 50-100 ms on a bad laptop
print(f({{0,0,0,0,1,1,0,1,0,0,0,0,1,0,0},
       {0,1,1,0,1,1,1,1,1,1,1,0,0,0,0},
       {0,1,1,1,0,1,0,1,0,0,0,0,1,0,0},
       {0,0,1,0,1,1,1,0,0,1,1,1,0,1,1},
       {1,1,0,0,1,1,1,0,1,1,0,0,0,1,0},
       {0,0,0,0,1,1,0,1,0,0,0,0,1,0,0},
       {0,1,1,0,1,1,1,1,1,1,1,0,0,0,0},
       {0,1,1,1,0,1,0,1,0,0,0,0,1,0,0},
       {0,0,1,0,1,1,1,0,0,1,1,1,0,1,1},
       {1,1,0,0,1,1,1,0,1,1,0,0,0,1,0},
       {0,0,1,0,1,1,1,0,0,1,1,1,0,1,1},
       {1,1,0,0,1,1,1,0,1,1,0,0,0,1,0},
       {0,0,0,0,1,1,0,1,0,0,0,0,1,0,0},
       {0,0,0,0,1,1,0,1,0,0,0,0,1,0,0},
       {0,1,1,0,1,1,1,1,1,1,1,0,0,0,0}}))
-- Glider on a 15x14 board
-- 840 distinct generation
-- loop afterward -> return -1
-- takes ~4-5 seconds on the same bad laptop
print(f({{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,1,0,0,0,0,0,0,0,0,0,0},
       {0,0,0,0,0,1,0,0,0,0,0,0,0,0,0},
       {0,0,0,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,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,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}}))

5

Jöle, 26 25 bayt

ṙ-r1¤SZµ⁺_|=3
ÇÐĿ-LiṪÇ$$?

Çevrimiçi deneyin! veya tüm test senaryolarını doğrulayın .

Daha büyük test senaryoları ( @ Katenkyo'nun cevabından ): 15 × 15 kararlı | 15 × 14 planör

Nasıl çalışır

ṙ-r1¤SZµ⁺_|=3  Helper link. Argument: G (grid)
               This link computes the next state of G.

    ¤          Evaluate the three links to the left as a niladic chain.
 -               Yield -1.
   1             Yield 1.
  r              Range; yield [-1, 0, 1].
ṛ              Rotate the rows of G -1, 0 and 1 units up.
     S         Compute the sum of the three resulting grids.
               Essentially, this adds the rows directly above and below each given
               row to that row.
      Z        Zip; transpose rows and columns.
       µ       Convert the preceding chain into a link and begin a new chain.
        ⁺      Apply the preceding chain once more.
               This zips back and adds the surrounding columns to each column.
         _     Subtract G from the result.
               Each cell now contains the number of lit cells that surround it.
          |    That the bitwise OR of the result and G.
               Notably, 3|0 = 3|1 = 2|1 = 3.
           =3  Compare each resulting number with 3.


ÇÐĿ-LiṪÇ$$?    Main link. Argument: G (grid)

ÇÐL            Repeatedly apply the helper link until the results are no longer
               unique. Collect all unique results in a list.
         $     Evaluate the two links to the left as a monadic chain:
        $        Evaluate the two links to the left as a monadic chain:
      Ṫ            Pop the last element of the list of grids.
       Ç           Apply the helper link to get the next iteration.
     i           Get the index of the grid to the right (the first non-unique one)
                 in the popped list of grids. This yields 0 iff the popped list
                 doesn't contain that grid, i.e., the grid reached a stable state.
          ?    If the index is non-zero:
   -             Return -1.
    L            Else, return the length of the popped list of grids.

5

Perl, 154 151 144 140 137 133 129 bayt

İçin +3 içerir -ap0

Girdi ile boşlukla ayrılmış basamak grupları satırı olarak çalıştır

life.pl <<< "0000 0001 0111 0010"

Bu sadece girişin hemen kararlı olması durumunda gereklidir. Diğer tüm durumlarda, daha rahat bir şekilde ayrı basamak satırları olarak da verebilirsiniz:

life.pl
0000
0001
0111
0010
^D

Ancak bu şekilde girdi vermek, hemen kararlı bir yapılandırma için 0 yerine 1 verir.

life.pl:

#!/usr/bin/perl -ap0
map{@f=map$F[$_%@F]x3,$i-1..++$i;s%.%"0+($&+33)=~grep\$_,map{(//g)[@--1..@+]}\@f"%eeg}@Q=@F;$_=/@Q/?keys%n:$n{$_="@Q"}--||redo

Mathematica'yı neredeyse yeniyor ...

Yalnızca eski perl sürümlerinde (sabit olarak değişken olarak kullanabileceğiniz yerlerde) bu 126 baytlık çözüm çalışır:

#!/usr/bin/perl -p0a
map{@f=map$F[$_++%@F]x2,-1..1;s%.%"0+($&+33)=~grep\$_,map{(//g)[@--1..@+]}\@f"%eeg}@Q=@F;$_=/@Q/?keys%n:$n{$_="@Q"}--||redo

En az 2 satır olması gerektiğinde, bu 123 baytlık çözüm tüm perl sürümlerinde çalışır:

#!/usr/bin/perl -p0a
@F=@F[-$#F..!s%.%"0+($&+33)=~grep\$_,map{(//g,//g)[@--1..@+]}\@F[-1..1]"%eeg]for@Q=@F;$_=/@Q/?keys%n:$n{$_="@Q"}--||redo

1

yakut, 207 bayt

->a{r=[];(r<<a;a=(0...a.size).map{|i|(0...a[i].size).map{|j|n=0;(-1..1).map{|u|(-1..1).map{|v|n+=a[(i+u)%a.size][(j+v)%a[i].size]}};[n==3,n>2&&n<5][a[i][j]]?1:0}})while(!r.index(a));(a==r[-1])?r.index(a):-1}

Her tahtanın bir tarihçesini saklıyorum, bu yüzden iki şeyden birinin olduğunu bilmeden önce gördüğüm bir tahta alırsam. birincisi, istikrarlı bir pozisyon bulmuş olabiliriz, bu durumda tarihimizdeki en kızgın olacaktır. diğer olasılık ise bir döngümüz olması.


15x15 matris, 2 ^ 225 olası tahtaya sahip olduğumuz anlamına gelir, dünyadaki tüm bilgisayarların hafızasını kullanarak bu matrisleri bile ezberleyebileceğinizden şüpheliyim (çoğu oyun muhtemelen 1000'den az kartla bitse bile) .. 64 bit makineler.
GameDeveloper

1
@DarioOO 15x14 kartındaki bir planör bile ilk durumuna geri dönmeden önce "sadece" 840 jenerasyonuna ihtiyaç duyacaktır, böylece neredeyse her şeyin 1000 gens'in altında olmasını bekleyebiliriz. Ayrıca, 32 bit tamsayı kullanan bir 15x15 üzerinde 1000 gens, 15*15*4*1000-> 900 KB bellek kullanımı ile sonuçlanır, 10k + gens'e ihtiyaç duyacağımız durumlar için yeterince iyi :).
Katenkyo

1

Julia, 92 88 bayt

f(x,r...)=x∈r?(r[k=end]==x)k-1:f(sum(i->circshift(x,[i÷3,i%3]-1),0:8)-x|x.==3,r...,x)

Doğrulama

julia> f(x,r...)=x∈r?(r[k=end]==x)k-1:f(sum(i->circshift(x,[i÷3,i%3]-1),0:8)-x|x.==3,r...,x)
f (generic function with 1 method)

julia> f([0 0 0;0 1 1;0 1 0])
2

julia> f([0 0 1 1;0 1 1 1;0 1 0 0;0 1 1 1])
2

julia> f([0 1 0 0;0 1 0 0;0 1 0 0;0 0 0 0])
-1

julia> f([0 0 0 0;0 0 0 1;0 1 1 1;0 0 1 0])
4

julia> f([0 0 0 0;0 1 1 0;0 1 1 0;0 0 0 0])
0

julia> f([0 0 0 0 1 1 0 1 0 0 0 0 1 0 0;0 1 1 0 1 1 1 1 1 1 1 0 0 0 0;0 1 1 1 0 1 0 1 0 0 0 0 1 0 0;0 0 1 0 1 1 1 0 0 1 1 1 0 1 1;1 1 0 0 1 1 1 0 1 1 0 0 0 1 0;0 0 0 0 1 1 0 1 0 0 0 0 1 0 0;0 1 1 0 1 1 1 1 1 1 1 0 0 0 0;0 1 1 1 0 1 0 1 0 0 0 0 1 0 0;0 0 1 0 1 1 1 0 0 1 1 1 0 1 1;1 1 0 0 1 1 1 0 1 1 0 0 0 1 0;0 0 1 0 1 1 1 0 0 1 1 1 0 1 1;1 1 0 0 1 1 1 0 1 1 0 0 0 1 0;0 0 0 0 1 1 0 1 0 0 0 0 1 0 0;0 0 0 0 1 1 0 1 0 0 0 0 1 0 0;0 1 1 0 1 1 1 1 1 1 1 0 0 0 0])
53

julia> f([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 1 0 0 0 0 0 0 0 0 0 0;0 0 0 0 0 1 0 0 0 0 0 0 0 0 0;0 0 0 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 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 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])
-1
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.