J , 40 byte
2%~[:+/^:_]<:[:+/&.:*:"1[:-"1/~#~#:i.@^~
Provalo online!
Timeout su TIO per 5 se si utilizza la precisione estesa ( 5x
anziché 5
). Non mi preoccuperò di provare con 6 sul mio computer poiché questo senza dubbio farà bloccare l'interprete.
Alla ricerca di consigli sul golf, in particolare la parte passata alla generazione delle coordinate. Sento che dovrebbe esserci un modo per rimuovere alcuni tappi.
]<:[:+/&.:*:"1
può essere equivalentemente sostituito da *:<:[:+/"1[:*:
.
Spiegazione
Questa spiegazione è fatta sul REPL (tre spazi indicano un comando, nessuno spazio indica un output). Costruirò fino alla risposta.
Generare le coordinate
#~ #: i.@^~
fornisce tutte le coordinate a cui teniamo sul reticolo.
^~
è un numero elevato a se stesso e i.
fornisce l'intervallo [0, n) dove n è il suo input. @
compone quelle funzioni.
i.@^~ 2
0 1 2 3
#~
copia un numero da solo, ad es
#~ 3
3 3 3
#:
converte l'argomento destro nella base specificata dall'array fornito come argomento sinistro. Il numero di cifre nell'array corrisponde al numero di cifre nell'output di base (e puoi avere una base mista) Ad esempio,
3 3 3 #: 0
0 0 0
5 5 #: 120
4 0
NB. If you want 120 base 5 use #.inv
#.inv 120
4 4 0
Quindi, tutti insieme, questo dice enumerare attraverso tutti i valori base n (dove n è l'input) fino a n ^ n, dandoci effettivamente le nostre coordinate.
(#~ #: i.@^~) 2
0 0
0 1
1 0
1 1
Ottenere le distanze tra ogni coppia
Per prima cosa prendiamo la differenza di ciascuna coordinata con tutte le altre usando la diade -table /
e ~
-reflexive. Nota che questo non tiene conto del fatto che l'ordine non ha importanza per le coppie: questo genera distanze duplicate.
NB. 2 {. takes the first two elements (I'm omitting the rest).
2 {. -"1/~ (#~ #: i.@^~) 2
0 0
0 _1
_1 0
_1 _1
0 1
0 0
_1 1
_1 0
Quindi usiamo questo verbo +/&.:*:
su ciascuna coordinata (al "1
livello 1). Questo verbo è sum ( +/
) under ( &.:
) square ( *:
). Sotto applica il verbo destro (quadrato) quindi raccoglie i suoi risultati e lo fornisce come argomento al verbo sinistro (somma). Quindi applica l'inverso del verbo destro (che sarebbe radice quadrata).
+/&.:*: 3 4
5
+/&.:*:"1 ([: -"1/~ #~ #: i.@^~) 2
0 1 1 1.41421
1 0 1.41421 1
1 1.41421 0 1
1.41421 1 1 0
Non sorprende che molte distanze siano uguali.
Contando le distanze maggiori o uguali all'ingresso
L'ultima parte sta vedendo se la distanza è maggiore o uguale all'input usando ]<:
. Quindi tutti i risultati vengono sommati usando +/^:_
(somma fino a convergere), contando il numero di valori di verità. Quindi questo valore viene diviso per 2 ( 2%~
qui ~
significa scambiare l'ordine degli argomenti forniti a %
). Il motivo per cui possiamo dividere per 2 è perché per ogni accoppiamento vero, ce ne sarà un altro per l'ordine invertito, tranne per gli accoppiamenti che sono coordinate con se stesso. Va bene, però, dal momento che quelli porteranno a una distanza di 0.