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&
Explicação:
r=Floor[(1+Sqrt[(4#-1)/3])/2]&
define uma função r
que recebe entrada #
e calcula a distância (em número de células) para a célula 0. Faz isso explorando o padrão nas últimas células de cada distância / anel: 0 = 3 (0 ^ 2 + 0), 6 = 3 (1 ^ 2 + 1), 18 = 3 (2 ^ 2 + 2), 36 = 3 (3 ^ 2 + 3), ... e invertendo a fórmula para esse padrão. Observe que para a célula 0, na verdade, é usado o piso de (1/2) + i * (sqrt (3) / 6), que calcula em componentes para obter 0 + 0 * i = 0.
Com r
definido, r@#
é o anel para célula #
(dentro da definição de outra função). #+3r@#-3(r@#)^2&
não aparece exatamente no código, mas pega o número de uma célula e subtrai o número mais alto de uma célula no próximo anel interno, para que ele responda à pergunta "qual célula do anel atual é essa?" Por exemplo, a célula 9 é a terceira célula do anel 2; portanto r[9]
, a saída 2 e a #+3r@#-3(r@#)^2&[9]
saída 3.
O que podemos fazer com a função acima é usá-la para encontrar o ângulo polar , no sentido anti-horário, do raio "célula 0, célula 17, célula 58" para a célula em questão. A última célula de cada anel está sempre em um ângulo Pi / 6 e contornamos um anel em incrementos de Pi / (3 * número do anel). Portanto, em teoria, precisamos calcular algo como Pi / 6 + (qual_cell_of_the_current_ring) * Pi / (3 * ring_number). No entanto, a rotação da imagem não afeta nada, portanto podemos descartar a parte Pi / 6 (para economizar 6 bytes). Combinando isso com a fórmula anterior e simplificando, obtemosPi(#/(3r@#)+1-r@#)&
Infelizmente, isso não é definido para a célula 0, pois seu número de toque é 0, por isso precisamos contornar isso. Uma solução natural seria algo parecido t=If[#==0,0,Pi(#/(3r@#)+1-r@#)]&
. Mas como não nos importamos com o ângulo da célula 0 e, como r@#
é repetida, podemos salvar um byte aqui comt=Limit[Pi(#/(3x)+1-x),x->r@#]&
Agora que temos o número do anel e o ângulo, podemos encontrar a posição de uma célula (centro) para testar a adjacência. Encontrar a posição real é irritante porque os anéis são hexagonais, mas podemos simplesmente fingir que os anéis são círculos perfeitos, para que tratemos o número do anel como a distância do centro da célula 0. Isso não será um problema, pois a aproximação é bastante Fechar. Usando a forma polar de um número complexo , podemos representar esta posição aproximada no plano complexo com uma função simples:p = r@#*Exp[I*t@#] &;
A distância entre dois números complexos no plano complexo é dada pelo valor absoluto de sua diferença, e então podemos arredondar o resultado para resolver quaisquer erros da aproximação e verificar se isso é igual a 1. A função que finalmente este trabalho não tem nome, mas é Round@Abs[p@#-p@#2]==1&
.
Você pode experimentá-lo on-line na caixa de proteção Wolfram Cloud colando código como o seguinte e clicando em Equipamento -> "Avaliar célula" ou pressionando Shift + Enter ou o 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]
Ou para todos os casos de teste:
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}}]]&