らせんシーケンス


29

バックグラウンド

OEISシーケンスA272573は、六角形グリッド上のスパイラルを次のように記述しています。

最初の六角形をa(1)= 1として、六角形のタイルで数字のらせんを開始します。a(n)は、その隣に等しくない、または以前に隣接していない最小の正の整数です。

シーケンスが始まります

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

スパイラルパターンの図を次に示します。 ここに画像の説明を入力してください

  • a(11) != 1その後、理由312箇所の隣接するだろう。
  • a(11) != 2その後、理由322箇所の隣接するだろう。
  • a(11) != 3それ3は、それ自体に隣接するからです。
  • a(11) != 4その後、理由342箇所の隣接するだろう。
  • したがってa(11) = 5

チャレンジ

課題は、A272573を計算するプログラムを作成することです。これはなので、最短のコードが優先されます。


ここでブロックされているため画像が表示されないため、何か不足している可能性がありますが、例ではa(11)= 4を示していますが、シーケンスリストではa(11)は5です。
Geobits

ただのミス。キャッチしてくれてありがとう。
ピーターケイジー

7
このOEISシーケンスは、明らかに自分で提出されました。いいね :)
アーナウド

nの制限は何ですか?時間制限はありますか?
Setop

5
六角形の答えを待っています...
ジョナサン・アラン

回答:


23

JavaScript(ES6)、 267 .. 206  199バイト

を含む配列を返します Nシーケンスの 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]])

オンラインでお試しください!

どうやって?

定義

慣例により、コーナーセルを、スパイラルの前の層と共通のエッジを1つだけ持つセルと呼びます。は前のレイヤーと共通のエッジを2つ持つセルます。提案 Ourousによって、我々はまた、それぞれ、順番-1細胞と注文-2細胞と考えることができます。

コーナーセルは下に黄色で表示されます。他のすべてのセルはサイドセルです(特殊なケースである中央のセルを除く)。

細胞型

セルネイバーについて

グリッド上のセルの座標を追跡する必要はありません。知っておくべき唯一のことは、スパイラル内の各セルの隣接セルのリストです。

次の図では、前のレイヤーの隣は明るい色で表示され、現在のレイヤーの追加の隣は暗い色で表示されています。

次の場合、セルには前のセルの間に2つの隣接セルがあります。

  • 新しいレイヤーの最初のサイドセル(8など)
  • または、それはコーナーセルですが、レイヤーの最後のセルではありません(9など

2人の隣人

次の場合、セルは前のセルの間に3つの隣接セルを持ちます。

  • それはサイドセルですが、レイヤーの最初のものではありません( 10など
  • または、現在のレイヤーの最後のコーナーセル(19など

3人の隣人

セルネイバーの実装

1nA[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
]                    //

上記のコードでは:

  • L1
  • j16×L
  • d

map()kk

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

シーケンスの次の用語を見つける

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)

素晴らしい説明。考えられる改善の1つは、水平スクロールを必要とせずに、コードブロック内の説明を完全に表示できるようにすることです(ゴルフのコードには関係ありません)。Firefoxで表示すると、最初の説明コードブロックには5つの非表示列があり、2番目には6つの非表示列があります。
trichoplax

@trichoplaxコメントと提案をありがとう。使用しているFirefoxのバージョンとプラットフォームを指定できますか?説明ブロックを常にフォーマットして、水平スクロールが必要ないようにします。現在Firefox 65 / Win10を使用していますが、非表示の列はありません。
アーナルド

家に帰るとFirefoxのバージョンを確認しますが、Fedoraを使用しているためかもしれません。別のOSを確認してお知らせします
trichoplax

1
OSによって異なるようです。いくつかの証拠を収集する機会があった場合、MSEでこれを提起します(まだ証拠がない場合)
trichoplax

1
私がしましたMSEでこれを提起しました。水平スクロールバーを表示する他のOS /ブラウザの組み合わせが表示された場合は、自由に編集してください。
trichoplax

7

クリーン284の 279 272 262バイト

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]])[]

オンラインでお試しください!

シーケンスを永久に生成します。

六角形マッピング

ほとんどのコードは六角形を(x,y)座標に一意にマッピングするため、すべてのポイントマッピングに適用される隣接関係を決定するための単一の単純な関数があります。

マッピングされたポイントは次のようになります。

              ---
        --- < 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.
              ---

そこから、隣接関係を判断することは簡単で、次のいずれかの場合に発生します。

  • x1 == x2 そして abs(y1-y2) == 1
  • y1 == y2 そして abs(x1-x2) == 1
  • y1 == y2 - 1 そして x2 == x1 - 1
  • y1 == y2 + 1 そして x2 == x1 + 1
  • x1 == x2 そして y1 == y2

ポイント生成

六角形をらせん状にトラバースすると、レイヤーごとに違いが繰り返されることに注意してくださいn

  1. n のステップ (1,0)
  2. n-1 のステップ (1,-1)
  3. n のステップ (0,-1)
  4. n のステップ (-1,0)
  5. n のステップ (-1,1)
  6. n のステップ (0,1)

これにより、このシーケンスのプレフィックスの合計を取得することにより、正しい順序でポイントが生成されます。

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]]

一緒にする

質問から実際にシーケンスを見つけるコードは次のとおりです。

$[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]]

これは、主に and[r<>j\\(u,v)<-m|c h u,(p,q)<-m|q==v,(i,j)<-m|c p i]

このフィルターは、m(既にマップされたポイントのリスト)から次のポイントを取得します。

  • 任意に等しい自然数を無視する j
  • 隣接するすべての(i,j)場所ip
  • (p,q)qが等しいすべてのv
  • 現在のポイントに隣接するすべての(u,v)場所についてu
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.