Mathematica, 111 105 104 byte
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&
Spiegazione:
r=Floor[(1+Sqrt[(4#-1)/3])/2]&
definisce una funzione r
che accetta input #
e calcola la distanza (in numero di celle) dalla cella 0. Lo fa sfruttando il modello nelle ultime celle di ogni distanza / anello: 0 = 3 (0 ^ 2 + 0), 6 = 3 (1 ^ 2 + 1), 18 = 3 (2 ^ 2 + 2), 36 = 3 (3 ^ 2 + 3), ... e invertendo la formula per quel modello. Si noti che per la cella 0, in realtà prende il pavimento di (1/2) + i * (sqrt (3) / 6), che calcola dal punto di vista del componente per ottenere 0 + 0 * i = 0.
Con r
definito, r@#
è l'anello per cella #
(all'interno della definizione di un'altra funzione). #+3r@#-3(r@#)^2&
non appare esattamente nel codice, ma prende il numero di una cella e sottrae il numero più alto di una cella nell'anello interno successivo, in modo che dia la risposta alla domanda "quale cella dell'anello corrente è questa?" Ad esempio, la cella 9 è la terza cella dell'anello 2, quindi l' r[9]
uscita 2 e l' #+3r@#-3(r@#)^2&[9]
uscita 3.
Quello che possiamo fare con la funzione sopra è usarlo per trovare l' angolo polare , l'angolo in senso antiorario dal raggio "cella 0, cella 17, cella 58" alla cella in questione. L'ultima cella di ogni anello ha sempre un angolo Pi / 6 e facciamo un giro con incrementi di Pi / (3 * numero_anello). Quindi, in teoria, dobbiamo calcolare qualcosa come Pi / 6 + (which_cell_of_the_current_ring) * Pi / (3 * ring_number). Tuttavia, la rotazione dell'immagine non influisce su nulla, quindi possiamo scartare la parte Pi / 6 (per salvare 6 byte). Combinando questo con la formula precedente e semplificando, otteniamoPi(#/(3r@#)+1-r@#)&
Sfortunatamente, questo non è definito per la cella 0 poiché il suo numero di squillo è 0, quindi dobbiamo aggirare questo. Una soluzione naturale sarebbe qualcosa di simile t=If[#==0,0,Pi(#/(3r@#)+1-r@#)]&
. Ma poiché non ci interessa l'angolo per la cella 0 e poiché r@#
viene ripetuto, possiamo effettivamente salvare un byte qui cont=Limit[Pi(#/(3x)+1-x),x->r@#]&
Ora che abbiamo il numero di squillo e l'angolo, possiamo trovare la posizione di una cella (al centro) in modo da poter verificare l'adiacenza. Trovare la posizione effettiva è fastidioso perché gli anelli sono esagonali, ma possiamo semplicemente far finta che gli anelli siano cerchi perfetti in modo da considerare il numero dell'anello come la distanza dal centro della cella 0. Questo non sarà un problema poiché l'approssimazione è carina vicino. Usando la forma polare di un numero complesso , possiamo rappresentare questa posizione approssimativa nel piano complesso con una semplice funzione:p = r@#*Exp[I*t@#] &;
La distanza tra due numeri complessi sul piano complesso è data dal valore assoluto della loro differenza, e quindi possiamo arrotondare il risultato per occuparci di eventuali errori dall'approssimazione e verificare se questo è uguale a 1. La funzione che infine questo lavoro non ha un nome, ma lo è Round@Abs[p@#-p@#2]==1&
.
Puoi provarlo online nella sandbox di Wolfram Cloud incollando il codice come il seguente e facendo clic su Gear -> "Valuta cella" o premendo Maiusc + Invio o il tastierino numerico Invio:
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 per tutti i casi di 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}}]]&