Mathematica, 111 105 104 octets
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&
Explication:
r=Floor[(1+Sqrt[(4#-1)/3])/2]&
définit une fonction r
qui prend une entrée #
et calcule la distance (en nombre de cellules) à la cellule 0. Elle le fait en exploitant le motif dans les dernières cellules de chaque distance / anneau: 0 = 3 (0 ^ 2 + 0), 6 = 3 (1 ^ 2 + 1), 18 = 3 (2 ^ 2 + 2), 36 = 3 (3 ^ 2 + 3), ... et inverser la formule de ce modèle. Notez que pour la cellule 0, il prend en fait le plancher de (1/2) + i * (sqrt (3) / 6), qu'il calcule par composant pour obtenir 0 + 0 * i = 0.
Avec r
défini, r@#
est l'anneau de cellule #
(à l'intérieur de la définition d'une autre fonction). #+3r@#-3(r@#)^2&
n'apparaît pas exactement dans le code, mais il prend le numéro d'une cellule et soustrait le nombre le plus élevé d'une cellule dans l'anneau intérieur suivant, de sorte qu'il donne la réponse à la question "quelle cellule de l'anneau actuel est-ce?" Par exemple, la cellule 9 est la 3ème cellule de l'anneau 2, ainsi r[9]
sortirait 2 et #+3r@#-3(r@#)^2&[9]
sortirait 3.
Ce que nous pouvons faire avec la fonction ci-dessus, c'est l'utiliser pour trouver l' angle polaire , l' angle anti-horaire du rayon "cellule 0, cellule 17, cellule 58" à la cellule en question. La dernière cellule de chaque anneau est toujours à un angle Pi / 6, et nous contournons un anneau par incréments de Pi / (3 * ring_number). Donc, en théorie, nous devons calculer quelque chose comme Pi / 6 + (which_cell_of_the_current_ring) * Pi / (3 * ring_number). Cependant, la rotation de l'image n'affecte rien, nous pouvons donc éliminer la partie Pi / 6 (pour économiser 6 octets). En combinant cela avec la formule précédente et en simplifiant, nous obtenonsPi(#/(3r@#)+1-r@#)&
Malheureusement, cela n'est pas défini pour la cellule 0 car son numéro de sonnerie est 0, nous devons donc contourner cela. Une solution naturelle serait quelque chose comme t=If[#==0,0,Pi(#/(3r@#)+1-r@#)]&
. Mais comme nous ne nous soucions pas de l'angle pour la cellule 0 et parce que r@#
c'est répété, nous pouvons réellement enregistrer un octet ici avect=Limit[Pi(#/(3x)+1-x),x->r@#]&
Maintenant que nous avons le numéro d'anneau et l'angle, nous pouvons trouver la position d'une cellule (centre) afin que nous puissions tester l'adjacence. Trouver la position réelle est ennuyeux car les anneaux sont hexagonaux, mais nous pouvons simplement prétendre que les anneaux sont des cercles parfaits afin que nous considérions le numéro de l'anneau comme la distance au centre de la cellule 0. Ce ne sera pas un problème car l'approximation est assez jolie proche. En utilisant la forme polaire d'un nombre complexe , nous pouvons représenter cette position approximative dans le plan complexe avec une fonction simple:p = r@#*Exp[I*t@#] &;
La distance entre deux nombres complexes sur le plan complexe est donnée par la valeur absolue de leur différence, puis nous pouvons arrondir le résultat pour prendre soin des erreurs de l'approximation et vérifier si cela est égal à 1. La fonction qui finalement fait ce travail n'a pas de nom, mais l'est Round@Abs[p@#-p@#2]==1&
.
Vous pouvez l' essayer en ligne dans le sandbox Wolfram Cloud en collant du code comme celui-ci et en cliquant sur Gear -> "Evaluer la cellule" ou en appuyant sur Maj + Entrée ou sur le pavé numérique Entrée:
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]
Ou pour tous les cas de test:
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}}]]&