# Torre di Hanoi

La Torre di Hanoi (anche conosciuta come Torre di Lucas dal nome del suo inventore) è un rompicapo matematico composto da tre paletti e un certo numero di dischi di grandezza decrescente, che possono essere infilati in uno qualsiasi dei paletti.
Il gioco inizia con tutti i dischi incolonnati su un paletto in ordine decrescente, in modo da formare un cono. Lo scopo del gioco è portare tutti i dischi su un paletto diverso, potendo spostare solo un disco alla volta e potendo mettere un disco solo su un altro disco più grande, mai su uno più piccolo.

## Origini

Il gioco fu inventato nel 1883 dal matematico francese Édouard Lucas che diffuse il gioco sotto lo pseudonimo di N. Claus de Siam, mandarino del collegio di Li-Sou-Stian. La leggenda secondo la quale in un tempio Indù alcuni monaci sono costantemente impegnati a spostare su tre colonne di diamante 64 dischi d'oro secondo le regole della Torre di Hanoi (a volte chiamata Torre di Brahmā) è stata inventata dalla ditta che per prima ha messo in commercio il rompicapo. La leggenda narra che quando i monaci avranno completato il lavoro il mondo finirà.
Esistono anche versioni videoludiche del rompicapo.

## Soluzione

La proprietà matematica base è che il numero minimo di mosse necessarie per completare il gioco è $2^{n}-1$, dove n è il numero di dischi (ad esempio, per spostare 3 dischi il numero minimo di mosse è 7). Di conseguenza secondo la leggenda, in cui $n=64$, i monaci di Hanoi dovrebbero effettuare almeno $2^{64}-1$ = 18.446.744.073.709.551.615 mosse prima che il mondo finisca. In altri termini, anche supponendo che i monaci facciano una mossa al secondo, il mondo finirebbe tra 5.845.580.504 secoli.
La soluzione generale è data dall'algoritmo seguente.

### Algoritmo ricorsivo

La soluzione base del gioco della torre di Hanoi si formula in modo ricorsivo.
Siano i paletti etichettati con A, B e C, e i dischi numerati da 1 (il più piccolo) a n (il più grande). L'algoritmo si esprime come segue:
* Sposta i primi n-1 dischi da A a B. (Questo lascia il disco n da solo sul paletto A)
* Sposta il disco n da A a C
* Sposta n-1 dischi da B a C
Per spostare n dischi si richiede di compiere un'operazione elementare (spostamento di un singolo disco) ed una complessa, ossia lo spostamento di n-1 dischi. Tuttavia anche questa operazione si risolve nello stesso modo, richiedendo come operazione complessa lo spostamento di n-2 dischi. Iterando questo ragionamento si riduce il processo complesso ad uno elementare, ovvero lo spostamento di n-(n-1)=1 disco.
Questo è un algoritmo ricorsivo, di complessità esponenziale.
L'implementazione in linguaggio C dell'algoritmo è stata pubblicata sul numero 3 di hitzone.
È interessante notare che il rompicapo è risolvibile per qualsiasi "n", con una dimostrazione per ricorrenza: Supponiamo di avere una torre in A composta da N dischi, e supponiamo che N sia il numero massimo di dischi ammessi per risolvere il gioco. Al termine dello spostamento della torre da A a B, aggiungiamo un ulteriore disco ad A, di grandezza pari a N+1, e ipotizziamo che questo disco sia stato fermo tutto il tempo sotto gli altri. A questo punto, spostiamo semplicemente il disco da A a C, e certamente riusciremo a spostare la torre da B a C, seguendo gli stessi passaggi che si sono resi necessari per spostarla da A a B. Avendo dimostrato che una torre di N dischi è spostabile da una colonna all'altra, è dimostrato che si può spostare anche una torre di N+1 dischi.

### Soluzione iterativa

Una soluzione semplice per il gioco è alternare le mosse tra il disco più piccolo e un disco diverso dal più piccolo. Quando muovi il disco più piccolo, spostalo sempre nella posizione successiva nella stessa direzione (a destra se il numero iniziale di dischi è pari, a sinistra se il numero iniziale di dischi è dispari). Se non c'è una torre sulla quale spostare il disco nella direzione scelta, sposta il pezzo all'estremità opposta, ma poi continua a muoverti nella direzione corretta. Ad esempio, se hai iniziato con tre dischi, sposta il disco più piccolo all'estremità opposta, quindi continua verso sinistra. Quando devi muovere un disco diverso dal più piccolo, resta solo una mossa consentita. In questo modo completerai il gioco nel minor numero di mosse possibile.

#### Procedura più semplice per la soluzione iterativa

Per un numero pari di dischi:
* Fai la mossa consentita tra i paletti A e B (in entrambe le direzioni),
* Fai la mossa consentita tra i paletti A e C (in entrambe le direzioni),
* Fai la mossa consentita tra i paletti B e C (in entrambe le direzioni),
* Ripeti fino al completamento.
Per un numero dispari di dischi:
* Fai la mossa consentita tra i paletti A e C (in entrambe le direzioni),
* Fai la mossa consentita tra i paletti A e B (in entrambe le direzioni),
* Fai la mossa consentita tra i paletti B e C (in entrambe le direzioni),
* Ripeti fino al completamento.
Dopo ogni mossa controlla se il paletto C è completo. In ogni caso, vengono effettuate in totale 2$^n$ − 1 mosse.

#### Soluzione iterativa equivalente

Un altro modo per generare l'unica soluzione iterativa ottimale:
Numera i dischi da 1 a n (dal più grande al più piccolo).
* Se n è dispari, la prima mossa è dal paletto A al paletto C.
* Se n è pari, la prima mossa è dal paletto A al paletto B.
Ora, aggiungi questi vincoli:
* Nessun disco dispari può essere posizionato direttamente su un disco dispari.
* Nessun disco pari può essere posizionato direttamente su un disco pari.
* A volte ci saranno due possibili paletti su cui spostare il disco: uno avrà i dischi e l'altro sarà vuoto. Sposta il disco sul paletto non vuoto.
* Non spostare mai lo stesso disco due volte di seguito.
Rispettando questi vincoli dopo la prima mossa, c'è solo una mossa consentita per ogni turno successivo.
La sequenza di queste mosse uniche è una soluzione ottimale al problema equivalente alla soluzione iterativa descritta sopra.

## Problema generalizzato

Il problema può essere generalizzato, supponendo ad esempio che il numero dei paletti non sia fissato a tre ma genericamente estendibile.
Supposta tale generalizzazione sono noti esempi di strategie ottimali per il completamento del gioco, sotto specifiche ipotesi, fin dal 1941. Esse sono state trovati separatamente da diversi autori.
La dimostrazione che tali strategie sono quelle ottimali in ogni condizione è invece un risultato del 2017. La principale difficoltà della dimostrazione era implicata dalla non unicità, nel caso con più di tre paletti, della strategia ottimale da seguire durante la risoluzione. Nel caso generale, di fatti, dopo ogni mossa è possibile cambiare strategia pur restando nel numero minimo di quelle necessarie a risolvere il puzzle, creando un complesso albero di percorsi risolutivi che impiegano lo stesso numero minimo di passi per risolvere il problema. Tale non unicità non è da intendersi nell'ovvio senso delle permutazioni, ma nel modo più generale possibile.