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 i
przylegap
- Dla każdego,
(p,q)
gdzie wartość q
jest równav
- Dla każdego
(u,v)
miejsca u
sąsiaduje z bieżącym punktem