-63 byte grazie a @Arnauld. Wow.
n=>(E=(x,y,d,k,h)=>V[k=[x+=1-(d%=3),y+=~d%3+1,d]]?0:(V[k]=1,h=H.find(h=>h[0]==x&h[1]==y))?(d^(t=2-h[2])?E(x,y,t)||E(x,y,h[2]*2):E(x,y,t+2)):[x,y,0],I=c=>c.map(([x,y,t])=>[x-g(0),y-g(1),t],g=p=>Math.min(...c.map(h=>h[p]))).sort(),S=e=>(V={},e=E(0,0,0))?(--n&&H.pop(H.push(e),S(),S(e[2]=1),S(e[2]=2)),++n):n-1||E[I(c=H)]||[0,0,0,++N,0,0].map(r=>E[I(c=c.map(([x,y,t])=>[-x-y,r?y:x,(r?t*2:t+1)%3]))]=1))(H=[[N=0,0,1]])&&N
Provalo online!
In primo luogo, rispetta Arnauld la cui risposta mi ha dato l'ispirazione per scavare più a fondo. Ho cercato di essere originale con i miei algoritmi, anche se ho modificato intenzionalmente parte del mio codice per utilizzare le stesse variabili di Arnauld in modo che il codice potesse essere confrontato più facilmente.
Alla ricerca di esagoni vuoti
La ricerca di creature è:
- Inizializza l'elenco di tessere con la tessera 1 a 0,0
- ricorsivamente:
- Cerca un esagono vuoto necessario per completare la creatura
- Se trovato esagono vuoto
- Aggiungi ogni tipo di tessera 0,1,2 all'esagono vuoto e ricomincia
- Se esagono vuoto non trovato
- Se la creatura ha le dimensioni corrette e non è già nello zoo
- Incrementa il numero di creature distinte trovate da una
- Aggiungi tutte le rotazioni e i riflessi della creatura allo zoo
La ricerca di esagoni vuoti ha scoperto un'interessante simmetria. Arnauld scoprì che una delle sei direzioni poteva essere ignorata, ma in realtà tre su sei possono essere ignorate!
Ecco la direzione originale di Arnauld e il tasto piastrella:
Immagina di iniziare dalla tessera A di tipo 1 nel punto blu. Sembra che dobbiamo ricorrere in d = 0 e d = 5. Comunque, qualunque tessera sia posizionata in d = 0, avrà sicuramente un'uscita in d = 4, che visiterà lo stesso esagono che esce dalla tessera A in d = 5. Questa è la scoperta di Arnauld, ed è ciò che mi ha fatto pensare.
Notare che:
Ciò significa che dobbiamo solo considerare le direzioni 0,2,4. Qualsiasi uscita nelle direzioni 1,3,5 può essere ignorata perché gli esagoni raggiungibili nelle direzioni 1,3,5 possono invece essere raggiunti da un esagono adiacente usando le direzioni 0,2 o 4.
Quant'è fico!?
Indicazioni rietichettate
Quindi ho rietichettato le direzioni e le tessere in questo modo (immagine di Arnauld modificata):
Ora abbiamo la seguente relazione tra tessere, voci ed uscite:
| t=0 | t=1 | t=2
----+-------+-------+-------
d=0 | 0,2 | 1,2 | 2
d=1 | 0,2 | 0 | 0,1
d=2 | 1 | 1,2 | 0,1
Quindi le uscite sono: d + t == 2? (4-t)% 3: 2-t e 2 * t% 3
Rotazioni e riflessioni esagonali
Per rotazioni e riflessioni, ho deciso di provare le coordinate assiali esagonali x, y invece delle coordinate del cubo x, y, z.
-1,2 0,2 1,2 2,2
0,1 1,1 2,1
0,0 1,0 2,0 3,0
In questo sistema, la rotazione e la riflessione erano più semplici di quanto mi aspettassi:
120 Rotation: x=-x-y y=x t=(t+1)%3
Reflection: x=-x-y y=y t=(t*2)%3
Per ottenere tutte le combinazioni che ho eseguito: marciume, marciume, marciume, riflesso, marciume, marciume
Codice (480 byte originale)
f=n=>(
// H:list of filled hexes [x,y,tile] during search for a complete creature
// N:number of distinct creatures of size n
// B:record of all orientations of all creatures already found
H=[[0,0,1]],N=0,B={},
// E: find an empty hex required to complete creature starting in direction d from x,y
E=(x,y,d,k,h)=>(
x+=1-d,
y+=1-(d+1)%3,
// V: list of visited hexes during this search in E
V[k=[x,y,d]] ?
0
: (V[k]=1, h=H.find(h=>h[0]==x&&h[1]==y)) ?
// this hex is filled, so continue search in 1 or 2 directions
(d==2-h[2] ? E(x,y,(4-h[2])%3) : (E(x,y,2-h[2]) || E(x,y,h[2]*2%3)))
: [x,y,0] // return the empty hex
),
// I: construct unique identifier for creature c by moving it so x>=0 and y>=0
I=c=>(
M=[0,1].map(p=>Math.min(...c.map(h=>h[p]))),
c.map(([x,y,t])=>[x-M[0],y-M[1],t]).sort()
),
// A: add complete creature c to B
A=c=>{
n==1&&!B[I(c)]&&(
// creature is correct size and is not already in B
N++,
[0,0,0,1,0,0].map(
// Add all rotations and reflections of creature into B
// '0' marks a rotation, '1' marks a (vertical) reflection
// rotation: x=-x-y y=x t=(t+1)%3
// reflection: x=-x-y y=y t=(t*2)%3
r=>B[I(c=c.map(([x,y,t])=>[-x-y,r?y:x,(r?t*2:t+1)%3]))]=1)
)
},
// S: recursively search for complete creatures starting with hexes H
S=e=>{
V={};
(e=E(0,0,0)) ?
// e is a required empty hex, so try filling it with tiles 0,1,2
(--n && (H.push(e),S(),S(e[2]=1),S(e[2]=2),H.pop()), ++n)
: A(H) // creature is complete, so add it to B
},
S(),
N
)
Codice (Arnauld 417 byte)
Arnauld ha gentilmente presentato un salvataggio di 63 byte che ha usato trucchi che mi hanno impiegato un po 'di tempo per avvolgermi la testa. Dal momento che ha molte modifiche interessanti, ho pensato di mettere il suo codice di seguito (ho aggiunto i miei commenti) in modo che possa essere contrastato con la mia versione.
f=n=>(
// E:find an empty hex required to complete creature starting in direction d from x,y
E=(x,y,d,k,h)=>
V[k=[x+=1-(d%=3),y+=~d%3+1,d]] ?
0
:(V[k]=1,h=H.find(h=>h[0]==x&h[1]==y)) ?
(d^(t=2-h[2]) ? E(x,y,t) || E(x,y,h[2]*2) : E(x,y,t+2))
:[x,y,0],
// I: construct unique identifier for creature c by moving it so x>=0 and y>=0
I=c=>c.map(([x,y,t])=>[x-g(0),y-g(1),t],g=p=>Math.min(...c.map(h=>h[p]))).sort(),
// S: recursively search for complete creatures starting with hexes H
S=e=>
(V={},e=E(0,0,0)) ?
(--n&&H.pop(H.push(e),S(),S(e[2]=1),S(e[2]=2)),++n)
:n-1
||E[I(c=H)]
// creature is the correct size and has not been seen before
// so record all rotations and reflections of creature in E[]
||[0,0,0,++N,0,0].map(r=>E[I(c=c.map(([x,y,t])=>[-x-y,r?y:x,(r?t*2:t+1)%3]))]=1)
)
// This wonderfully confusing syntax initializes globals and calls S()
(H=[[N=0,0,1]]) && N
n=10
TIO." - se si tratta di un requisito di velocità di esecuzione, utilizzare code-challenge anziché code-golf , quest'ultimo si riferisce a un'attività di ottimizzazione dei byte puri.