Mathematica, 111 105 104 bajtów
r=Floor[(1+Sqrt[(4#-1)/3])/2]&;t=Limit[Pi(#/(3x)+1-x),x->r@#]&;p=r@#*Exp[I*t@#]&;Round@Abs[p@#-p@#2]==1&
Wyjaśnienie:
r=Floor[(1+Sqrt[(4#-1)/3])/2]&
definiuje funkcję, r
która pobiera dane wejściowe #
i oblicza odległość (w liczbie komórek) do komórki 0. Robi to poprzez wykorzystanie wzorca w ostatnich komórkach każdej odległości / pierścienia: 0 = 3 (0 ^ 2 + 0), 6 = 3 (1 ^ 2 + 1), 18 = 3 (2 ^ 2 + 2), 36 = 3 (3 ^ 2 + 3), ... i odwracanie formuły dla tego wzorca. Zauważ, że dla komórki 0 faktycznie zajmuje ona podłogę (1/2) + i * (sqrt (3) / 6), którą oblicza w oparciu o komponenty, aby uzyskać 0 + 0 * i = 0.
Z r
zdefiniowane r@#
jest pierścień dla komórki #
(wewnątrz definicji innej funkcji). #+3r@#-3(r@#)^2&
nie pojawia się dokładnie w kodzie, ale pobiera numer komórki i odejmuje najwyższą liczbę komórek w następnym pierścieniu wewnętrznym, aby dać odpowiedź na pytanie „która to komórka bieżącego pierścienia?” Na przykład komórka 9 jest trzecią komórką pierścienia 2, więc r[9]
wyprowadziłaby 2 i #+3r@#-3(r@#)^2&[9]
wyprowadziłaby 3.
Z powyższą funkcją możemy skorzystać, aby znaleźć kąt biegunowy, kąt przeciwny do ruchu wskazówek zegara od promienia „komórka 0, komórka 17, komórka 58” do danej komórki. Ostatnia komórka każdego pierścienia jest zawsze pod kątem Pi / 6, a my obchodzimy pierścień w odstępach co Pi / (3 * liczba_pierścienia). Teoretycznie musimy obliczyć coś takiego jak Pi / 6 + (który_komórka_prądu_ring) * Pi / (3 * numer_krętu). Obrót obrazu nic jednak nie wpływa, więc możemy odrzucić część Pi / 6 (aby zaoszczędzić 6 bajtów). Łącząc to z poprzednią formułą i upraszczając, otrzymujemyPi(#/(3r@#)+1-r@#)&
Niestety nie jest to zdefiniowane dla komórki 0, ponieważ jej numer dzwonka to 0, więc musimy to obejść. Naturalnym rozwiązaniem byłoby coś takiego t=If[#==0,0,Pi(#/(3r@#)+1-r@#)]&
. Ale ponieważ nie dbamy o kąt dla komórki 0 i ponieważ r@#
się powtarza, możemy faktycznie zapisać bajt tutajt=Limit[Pi(#/(3x)+1-x),x->r@#]&
Teraz, gdy mamy numer pierścienia i kąt, możemy znaleźć pozycję komórki (środka), abyśmy mogli przetestować sąsiedztwo. Znalezienie rzeczywistej pozycji jest denerwujące, ponieważ pierścienie są sześciokątne, ale możemy po prostu udawać, że pierścienie są idealnymi okręgami, więc traktujemy numer pierścienia jako odległość do środka komórki 0. To nie będzie problem, ponieważ przybliżenie jest dość blisko. Używając postaci biegunowej liczby zespolonej , możemy przedstawić tę przybliżoną pozycję w płaszczyźnie zespolonej za pomocą prostej funkcji:p = r@#*Exp[I*t@#] &;
Odległość między dwiema liczbami zespolonymi na płaszczyźnie zespolonej jest podawana przez wartość bezwzględną ich różnicy, a następnie możemy zaokrąglić wynik, aby zająć się wszelkimi błędami z przybliżenia i sprawdzić, czy jest to równe 1. Funkcja, która w końcu czy ta praca nie ma nazwy, ale jest Round@Abs[p@#-p@#2]==1&
.
Możesz wypróbować go online w piaskownicy Wolfram Cloud , wklejając poniższy kod i klikając Gear -> „Oceń komórkę” lub naciskając Shift + Enter lub Enter na klawiaturze numerycznej:
r=Floor[(1+Sqrt[(4#-1)/3])/2]&;t=Limit[Pi(#/(3x)+1-x),x->r@#]&;p=r@#*Exp[I*t@#]&;Round@Abs[p@#-p@#2]==1&[24,45]
Lub dla wszystkich przypadków testowych:
r=Floor[(1+Sqrt[(4#-1)/3])/2]&;t=Limit[Pi(#/(3x)+1-x),x->r@#]&;p=r@#*Exp[I*t@#]&;Round@Abs[p@#-p@#2]==1&//MapThread[#,Transpose[{{0,1},{7,18},{8,22},{24,45},{40,64},{64,65},{6,57},{29,90},{21,38},{38,60},{40,63},{41,39},{40,40}}]]&