Bir sarmal dizisi


29

Arka fon

OEIS dizisi A272573 , altıgen bir ızgara üzerinde aşağıdaki gibi bir spiral tarif eder:

Bir altıgen fayans üzerinde sayıların bir spiralini başlatın, ilk altıgeni (1) = 1 olarak ayarlayın. A (n), komşularına eşit veya daha önce bitişik olmayan en küçük pozitif tamsayıdır.

Dizi başlar

1, 2, 3, 4, 5, 6, 7, 4, 6, 8, 5, 9, 8, 10, 2, 11, ...

İşte spiral modelin bir örneği: görüntü tanımını buraya girin

  • a(11) != 1daha sonra da 3ve 1iki yerde bitişik olacaktır.
  • a(11) != 2daha sonra da 3ve 2iki yerde bitişik olacaktır.
  • a(11) != 3çünkü o 3zaman kendisine bitişik olur.
  • a(11) != 4daha sonra da 3ve 4iki yerde bitişik olacaktır.
  • Bu nedenle a(11) = 5.

Meydan okuma

Buradaki zorluk A272573'ü hesaplayan bir program yazmaktır . Bu , yani en kısa kod kazanır.


Görüntüyü burada engellenmiş olarak göremiyorum, bu yüzden belki bir şeyleri özlüyorum, ancak örneğin bir (11) = 4 gösteriyor, ancak sıralama listenizde bir (11) 5'tir.
Geobits

Sadece bir hata - yakaladığınız için teşekkürler.
Peter Kagey

7
Bu OEIS dizisi görünüşte kendiniz tarafından verildi. Güzel. :)
Arnauld,

n'nin sınırı nedir? zaman sınırı var mı
Setop

5
Hexagony cevap bekliyorum ...
Jonathan Allan,

Yanıtlar:


23

JavaScript (ES6),  267 .. 206  199 bayt

N

n=>(F=v=>++i<n?F([...v,(A=N[i]=[1,!j++||d+1,j%L?d:(j%=L*6)?++d:L++&&d++].map(k=>N[k=i-k].push(i)&&k),g=k=>v[E='every']((V,x)=>V-k|N[x][E](y=>A[E](z=>v[y]-v[z])))?k:g(-~k))()]):v)([L=1],N=[[i=j=d=0]])

Çevrimiçi deneyin!

Nasıl?

Tanımlar

Geleneksel olarak köşe hücresine , önceki sarmal katmanla ortak olarak yalnızca bir kenarı olan bir hücreyi ve yan hücreyi önceki katmanla ortak iki kenarı olan bir hücre olarak adlandıracağız. Gibi önerilen Ourous tarafından, biz de sırasıyla, sipariş-1 hücreleri ve sipariş-2 hücreleri olarak kendilerine düşünebiliriz.

Köşe hücreleri aşağıda sarı renkte gösterilmiştir. Diğer tüm hücreler yan hücrelerdir (özel bir durum olan merkez hücre hariç).

hücre tipleri

Hücre komşuları hakkında

Izgaradaki hücrelerin koordinatlarını takip etmemize gerek yok. Bilmemiz gereken tek şey, herhangi bir zamanda spiraldeki her bir hücre için komşu hücrelerin listesidir.

Aşağıdaki diyagramlarda, önceki katmandaki komşular açık gölgede ve mevcut katmandaki koyu renkteki ek komşular gösterilmektedir.

Bir hücrenin önceki hücreler arasında 2 komşusu varsa:

  • yeni bir katmanın ilk yan hücresidir ( 8 gibi )
  • ya da bir köşe hücresidir, ancak katmanın sonuncusu değildir ( 9 gibi )

2 komşu

Bir hücrenin önceki hücreler arasında 3 komşusu varsa:

  • bu bir yan hücredir, fakat katmanın ilki değildir ( 10 gibi )
  • veya mevcut katmanın son köşe hücresi ( 19 gibi )

3 komşu

Hücre komşularının uygulanması

1inA[n]

11

[                    //
  1,                 // the previous cell is always a neighbor of the current cell
  !j++ || d + 1,     // if this is not the first cell of the layer, the cell at -(d + 1)
                     // is a neighbor (otherwise, we insert 1 twice; doing it that way
                     // saves bytes and having duplicate neighbors is not a problem)
  j % L ?            // if this is a side-cell:
    d                //   the cell at -d is a neighbor
  :                  // else (corner-cell):
    (j %= L * 6) ?   //   if this is not the last cell:
      ++d            //     insert the dummy duplicate neighbor at -(d + 1); increment d
    :                //   else (last cell):
      L++ && d++     //     the cell at -d is a neighbor; increment L; increment d
]                    //

Yukarıdaki kodda:

  • L1
  • j16×L
  • d

map()kik

.map(k =>
  N[k = i - k].push(i) && k
)

Dizinin bir sonraki terimini bulma

k

nv[n]

( g =                 // g = recursive function taking
  k =>                // the candidate value k
    v.every((V, x) => // for each previous cell of value V at position x, make sure that:
      V - k           //   V is not equal to k
      |               //   OR
      N[x].every(y => //   for each neighbor y of x:
        A.every(z =>  //     for each neighbor z of the current cell:
          v[y] - v[z] //       the value of y is not equal to the value of z
        )             //     end
      )               //   end
    )                 // end
    ?                 // if the above conditions are fulfilled:
      k               //   stop recursion and return k
    :                 // else:
      g(-~k)          //   try again with k + 1
)()                   // initial call to g with k undefined (this will cause V - k to be
                      // evaluated as NaN and force the 1st iteration to fail)

Harika bir açıklama. Olası bir gelişme: Kod bloklarındaki açıklamaların yatay kaydırmaya gerek olmadan tamamen görünmesini sağlamak (golf kodu için önemli değil). Firefox’da görüntülenen ilk açıklama kod bloğunda 5 gizli sütun ve ikinci gizli 6 sütun vardır.
trichoplax

@trichoplax Yorumunuz ve öneriniz için teşekkür ederiz. Hangi Firefox sürümünü kullandığınızı ve hangi platformda kullanabileceğinizi belirleyebilir misiniz? Açıklama bloklarını daima yatay kaydırmaya gerek kalmayacak şekilde biçimlendirmeye çalışırım. Şu anda Firefox 65 / Win10'dayım ve hiçbir gizli sütunum yok.
Arnauld

Eve döndüğümde Firefox sürümünü kontrol edecek, ancak Fedora'da olduğum için olabilir. Başka bir işletim sistemi kontrol edecek ve size bildireceğiz
trichoplax

1
İşletim sistemine göre değişiyor gibi görünüyor. Bazı kanıtları toplamak için bir şansım olduğunda
MSE’de

1
Bunu MSE'de büyüttüm . Yatay kaydırma çubukları gösteren diğer işletim sistemi / tarayıcı kombinasyonlarını gören varsa düzenleme yapmaktan çekinmeyin.
trichoplax

7

Temiz , 284 279 272 262 bayt

import StdEnv
l=[0,-1,-1,0,1,1]
c(u,v)(p,q)=(u-p)^2+(v-q)^2<2||(u-p)*(q-v)==1
$[h:t]m=hd[[e: $t[(h,e):m]]\\e<-[1..]|and[e<>j\\(u,v)<-m|c h u,(p,q)<-m|q==v,(i,j)<-m|c p i]]

$(scan(\(a,b)(u,v)=(a-u,b-v))(0,0)[(i,j)\\n<-[1..],i<-[1,1:l]&j<-l,_<-[max(~j<<i)1..n]])[]

Çevrimiçi deneyin!

Sonsuza kadar diziyi oluşturur.

Altıgen Eşleme

Kodun çoğu, (x,y)eşgüdümleri benzersiz şekilde eşleştirmek için tüm nokta eşlemelerini tutan bitişikliği belirleyen tek, basit bir işlev olacak şekilde eşleşir.

Haritalanan noktalar şuna benzer:

              ---
        --- < 2,-2> ---       x-axis ___.X'
  --- < 1,-2> === < 2,-1> ---  /__.X'
< 0,-2> === < 1,-1> === < 2, 0>'
  === < 0,-1> === < 1, 0> ===
<-1,-1> === < 0, 0> === < 1, 1>
  === <-1, 0> === < 0, 1> ===
<-2, 0> === <-1, 1> === < 0, 2>.__
  --- <-2, 1> === <-1, 2> ---  \  'Y.___
        --- <-2, 2> ---       y-axis    'Y.
              ---

Oradan, bitişikliği belirlemek önemsizdir ve şunlardan biri olduğunda oluşur:

  • x1 == x2 ve abs(y1-y2) == 1
  • y1 == y2 ve abs(x1-x2) == 1
  • y1 == y2 - 1 ve x2 == x1 - 1
  • y1 == y2 + 1 ve x2 == x1 + 1
  • x1 == x2 ve y1 == y2

Nokta Üretimi

Altıgen bir spiral halinde hareket ederken, farkların her katman için yinelendiğine dikkat edin n:

  1. n adımları (1,0)
  2. n-1 adımları (1,-1)
  3. n adımları (0,-1)
  4. n adımları (-1,0)
  5. n adımları (-1,1)
  6. n adımları (0,1)

Bu, bu sıranın öneklerinin toplamlarını alarak doğru sıradaki noktaları oluşturur:

scan(\(a,b)(u,v)=(a-u,b-v))(0,0)[(i,j)\\n<-[1..],i<-[1,1:l]&j<-l,_<-[max(~j<<i)1..n]]

Bir araya getirmek

Aslında sorudan sırayı bulan kod şudur:

$[h:t]m=hd[[e: $t[(h,e):m]]\\e<-[1..]|and[e<>j\\(u,v)<-m|c h u,(p,q)<-m|q==v,(i,j)<-m|c p i]]

Hangi sırayla çoğunlukla tarafından filtreleme and[r<>j\\(u,v)<-m|c h u,(p,q)<-m|q==v,(i,j)<-m|c p i]

Bu filtre şu ana kadar m(zaten haritalanmış noktaların listesinden) puan alır :

  • Herhangi birine eşit olan doğal sayıları dikkate almamak j
  • Bitişik her (i,j)yerdeip
  • (p,q)Değerin qeşit olduğu her yer içinv
  • Geçerli noktaya bitişik olan her (u,v)yer uiçin
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.