Mathematica, 111 105 104 bytes
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&
Explicación:
r=Floor[(1+Sqrt[(4#-1)/3])/2]&
define una función r
que toma la entrada #
y calcula la distancia (en número de celdas) a la celda 0. Hace esto explotando el patrón en las últimas celdas de cada distancia / anillo: 0 = 3 (0 ^ 2 + 0), 6 = 3 (1 ^ 2 + 1), 18 = 3 (2 ^ 2 + 2), 36 = 3 (3 ^ 2 + 3), ... e invirtiendo la fórmula para ese patrón. Tenga en cuenta que para la celda 0, en realidad toma el piso de (1/2) + i * (sqrt (3) / 6), que calcula por componentes para obtener 0 + 0 * i = 0.
Con r
definido, r@#
es el anillo para la celda #
(dentro de la definición de otra función). #+3r@#-3(r@#)^2&
no aparece exactamente en el código, pero toma el número de una celda y resta el número más alto de una celda en el siguiente anillo interno, de modo que da la respuesta a la pregunta "¿qué celda del anillo actual es esta?" Por ejemplo, la celda 9 es la tercera celda del anillo 2, por r[9]
lo que generaría 2 y #+3r@#-3(r@#)^2&[9]
generaría 3.
Lo que podemos hacer con la función anterior es usarla para encontrar el ángulo polar , el ángulo en sentido antihorario desde el rayo "celda 0, celda 17, celda 58" hasta la celda en cuestión. La última celda de cada anillo siempre está en un ángulo Pi / 6, y vamos alrededor de un anillo en incrementos de Pi / (3 * ring_number). Entonces, en teoría, necesitamos calcular algo como Pi / 6 + (which_cell_of_the_current_ring) * Pi / (3 * ring_number). Sin embargo, la rotación de la imagen no afecta nada, por lo que podemos descartar la parte Pi / 6 (para guardar 6 bytes). Combinando esto con la fórmula anterior y simplificando, obtenemosPi(#/(3r@#)+1-r@#)&
Desafortunadamente, esto no está definido para la celda 0 ya que su número de anillo es 0, por lo que debemos evitarlo. Una solución natural sería algo así t=If[#==0,0,Pi(#/(3r@#)+1-r@#)]&
. Pero como no nos importa el ángulo de la celda 0 y porque r@#
se repite, podemos guardar un byte aquí cont=Limit[Pi(#/(3x)+1-x),x->r@#]&
Ahora que tenemos el número de anillo y el ángulo, podemos encontrar la posición de una celda (centro) para poder comprobar la adyacencia. Encontrar la posición real es molesto porque los anillos son hexagonales, pero podemos simplemente pretender que los anillos son círculos perfectos para que tratemos el número de anillo como la distancia al centro de la celda 0. Esto no será un problema ya que la aproximación es bastante cerca. Usando la forma polar de un número complejo , podemos representar esta posición aproximada en el plano complejo con una función simple:p = r@#*Exp[I*t@#] &;
La distancia entre dos números complejos en el plano complejo viene dada por el valor absoluto de su diferencia, y luego podemos redondear el resultado para encargarnos de cualquier error de la aproximación, y verificar si es igual a 1. La función que finalmente ¿Este trabajo no tiene un nombre, pero es Round@Abs[p@#-p@#2]==1&
.
Puede probarlo en línea en el sandbox de Wolfram Cloud pegando código como el siguiente y haciendo clic en Gear -> "Evaluar celda" o presionando Shift + Enter o el teclado numérico Enter:
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]
O para todos los casos de prueba:
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}}]]&