Czysty , 284 279 272 262 bajtów
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]])[]
Wypróbuj online!
Generuje sekwencję na zawsze.
Mapowanie sześciokątne
Większość kodu (x,y)służy do mapowania sześciokątów unikatowo na współrzędne, dzięki czemu istnieje jedna, prosta funkcja określająca przyleganie, które obowiązuje dla wszystkich mapowań punktów.
Mapowane punkty wyglądają następująco:
---
--- < 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.
---
Stamtąd określenie przylegania jest banalne i występuje, gdy:
x1 == x2 i abs(y1-y2) == 1
y1 == y2 i abs(x1-x2) == 1
y1 == y2 - 1 i x2 == x1 - 1
y1 == y2 + 1 i x2 == x1 + 1
x1 == x2 i y1 == y2
Generowanie punktów
Zauważ, że podczas przemierzania sześciokąta po spirali różnice powtarzają się dla każdej warstwy n:
n kroki z (1,0)
n-1 kroki z (1,-1)
n kroki z (0,-1)
n kroki z (-1,0)
n kroki z (-1,1)
n kroki z (0,1)
To generuje punkty we właściwej kolejności, biorąc sumy prefiksów tej sekwencji:
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]]
Łącząc to razem
Kod, który faktycznie znajduje sekwencję z pytania, to po prostu:
$[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]]
Co z kolei jest głównie filtrowane and[r<>j\\(u,v)<-m|c h u,(p,q)<-m|q==v,(i,j)<-m|c p i]
Ten filtr pobiera punkty z m(listy już zmapowanych punktów) według:
- Ignorowanie liczb naturalnych, które są równe dowolnemu
j
- Do każdego
(i,j)miejsca iprzylegap
- Dla każdego,
(p,q)gdzie wartość qjest równav
- Dla każdego
(u,v)miejsca usąsiaduje z bieżącym punktem