Mathematica, 111 105 104 байта
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&
Объяснение:
r=Floor[(1+Sqrt[(4#-1)/3])/2]&
определяет функцию, r
которая принимает входные данные #
и вычисляет расстояние (в количестве ячеек) до ячейки 0. Это делается путем использования шаблона в последних ячейках каждого расстояния / кольца: 0 = 3 (0 ^ 2 + 0), 6 = 3 (1 ^ 2 + 1), 18 = 3 (2 ^ 2 + 2), 36 = 3 (3 ^ 2 + 3), ... и инвертируя формулу для этого шаблона. Обратите внимание, что для ячейки 0 она фактически принимает значение (1/2) + i * (sqrt (3) / 6), которое вычисляется по компонентам, чтобы получить 0 + 0 * i = 0.
С r
определяется, r@#
является кольцо для ячейки #
(внутри определения другой функции). #+3r@#-3(r@#)^2&
не появляется в коде точно, но он берет номер ячейки и вычитает наибольшее число ячеек в следующем внутреннем кольце, так что это дает ответ на вопрос "какая ячейка текущего кольца это?" Например, ячейка 9 - это третья ячейка кольца 2, поэтому r[9]
выведите 2 и #+3r@#-3(r@#)^2&[9]
выведите 3.
Что мы можем сделать с помощью функции выше, так это использовать ее для нахождения полярного угла , угла против часовой стрелки от луча «ячейка 0, ячейка 17, ячейка 58» к рассматриваемой ячейке. Последняя ячейка каждого кольца всегда находится под углом Pi / 6, и мы обходим кольцо с шагом Pi / (3 * ring_number). Итак, теоретически нам нужно вычислить что-то вроде Pi / 6 + (which_cell_of_the_current_ring) * Pi / (3 * ring_number). Однако поворот изображения ни на что не влияет, поэтому мы можем отбросить часть Pi / 6 (чтобы сохранить 6 байт). Объединяя это с предыдущей формулой и упрощая, мы получаемPi(#/(3r@#)+1-r@#)&
К сожалению, это не определено для ячейки 0, так как ее номер звонка равен 0, поэтому нам нужно обойти это. Естественное решение было бы что-то вроде t=If[#==0,0,Pi(#/(3r@#)+1-r@#)]&
. Но так как нас не волнует угол для ячейки 0 и поскольку r@#
он повторяется, мы можем сохранить здесь байт с помощьюt=Limit[Pi(#/(3x)+1-x),x->r@#]&
Теперь, когда у нас есть номер кольца и угол, мы можем найти положение ячейки (центра), чтобы мы могли проверить смежность. Поиск фактической позиции раздражает, потому что кольца гексагональные, но мы можем просто притвориться, что кольца являются идеальными кругами, так что мы рассматриваем число колец как расстояние до центра ячейки 0. Это не будет проблемой, так как приближение довольно близко. Используя полярную форму комплексного числа , мы можем представить это приблизительное положение в комплексной плоскости с помощью простой функции:p = r@#*Exp[I*t@#] &;
Расстояние между двумя комплексными числами на комплексной плоскости определяется абсолютной величиной их разности, и затем мы можем округлить результат, чтобы учесть любые ошибки из аппроксимации, и проверить, равно ли это 1. Функция, которая в конечном итоге У этой работы нет имени, но есть Round@Abs[p@#-p@#2]==1&
.
Вы можете попробовать его онлайн в песочнице Wolfram Cloud , вставив код, подобный приведенному ниже, и щелкнув Gear -> «Оценить ячейку» или нажав Shift + Enter или цифровую клавишу 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]
Или для всех тестовых случаев:
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}}]]&