Algoritmo da Torre de Hanói: Python, C++ Code

O que é a Torre de Hanói?

A Torre de Hanói é um quebra-cabeça matemático composto por três hastes e vários discos colocados uns sobre os outros. Também é conhecida como Torre de Brahma ou Torre de Lucas, como o matemático francês Edouard Lucas a introduziu em 1883. Este quebra-cabeça é baseado em lendas sobre o movimento de discos de ouro entre três hastes.

Este quebra-cabeça possui três hastes e um número variável de discos empilhados. Essas hastes são projetadas como torres cíclicas. Assim, os discos maiores em diâmetro são empilhados na parte inferior e os discos menores são empilhados na parte superior.

Inicialmente, recebemos três estacas ou hastes. E um deles (A, mostrado no exemplo) tem todos os discos empilhados. Nosso objetivo é mover uma pilha inteira de discos de uma haste (A) para outra (C) obedecendo a algumas regras específicas.

Aqui está a configuração inicial do quebra-cabeça-

Problema da Torre de Hanói
Problema da Torre de Hanói

E este é o objetivo final-

Torre de Hanói

Regras da Torre de Hanói

Aqui estão algumas regras essenciais para a Torre de Hanói:

  • No estado inicial deste quebra-cabeça, todos os discos serão empilhados na haste um.
  • O estado final é que todos os discos da barra um serão empilhados na barra dois ou na barra três.
  • Podemos mover um disco de uma haste para outra a qualquer momento.
  • Só podemos mover o disco superior da haste.
  • Um disco não pode ser colocado sobre outro disco, que é menor.

A lenda original era sobre a movimentação de 64 discos. Os sacerdotes podiam mover um disco de cada vez de acordo com as regras. Segundo a lenda, havia uma profecia de que o mundo acabaria se eles conseguissem completar o ato. Na seção de complexidade de tempo, mostraremos que uma configuração da Torre de Hanói com n discos custaria 2^n – 1 movimento.

Portanto, se os sacerdotes precisassem de 1 segundo para mover os discos, o tempo total necessário para resolver o quebra-cabeça seria 2 ^ 64 – 1 segundo ou 584,942,417,356 anos, 26 dias, 7 horas e 15 segundos.

Algoritmo para Torre de Hanói

Uma maneira geral de resolver a Torre de Hanói é um algoritmo recursivo. Primeiro, precisamos decidir sobre duas hastes ou estacas como origem e destino, e a estaca sobressalente seria auxiliar ou auxiliar.

Aqui estão as etapas para resolver o quebra-cabeça da Torre de Hanói:

  • Mova os discos n-1 superiores do pino de origem para o pino auxiliar.
  • Depois, mova o enésimo disco do pino de origem para o pino de destino.
  • Finalmente, mova os n-1 discos restantes do pino auxiliar para o pino de destino.

Note: Se tivermos um único disco, podemos movê-lo diretamente da origem ao destino.

Como resolver o quebra-cabeça da Torre de Hanói

Vamos ilustrar o algoritmo para três discos e considerar o pino A como origem, o pino B como auxiliar e o pino C como destino

Passo 1) Inicialmente, todos os discos serão empilhados no pino A.

Resolva o quebra-cabeça da Torre de Hanói

Nesta fase:

Fonte = Peg A
Destino = Peg C
Ajudante = Peg B

Agora, precisamos mover os n-1 discos superiores da origem para o auxiliar.

Nota: Embora só possamos mover um disco por vez, isso divide nosso problema de um problema de 3 discos para um problema de 2 discos, que é uma chamada recursiva.

Passo 2) Como chamamos uma chamada recursiva do pino A e o destino é o pino B, usaremos o pino C como auxiliar.

Observe que estamos novamente no estágio um para o mesmo problema da torre de Hanói para dois discos.

Agora precisamos mover n-1 ou um disco da origem para o auxiliar, movendo o menor disco do pino A para o pino C.

Resolva o quebra-cabeça da Torre de Hanói

Nesta fase:

Fonte = pino A
Destino = pino B
Auxiliar = pino C

Passo 3) Então, de acordo com nosso algoritmo, o enésimo ou segundo disco necessário deve ser transferido para o destino ou pino B.

Resolva o quebra-cabeça da Torre de Hanói

Nesta fase:

Fonte = pino A
Destino = pino B
Auxiliar = pino C

Passo 4) Agora, moveremos os n-1 discos ou disco um do auxiliar ou pino C para o destino ou pino B de acordo com o terceiro estágio de nosso algoritmo.

Resolva o quebra-cabeça da Torre de Hanói

Nesta fase:

Fonte = pino A
Destino = pino B
Auxiliar = pino C

Passo 5) Após concluir a chamada recursiva, retornaremos à nossa configuração anterior no primeiro estágio do algoritmo.

Passo 6) Agora, no segundo estágio, moveremos nossa origem para nosso destino, que é mover o disco 3 do pino A para o pino C.

Nesta fase:

Fonte = pino A
Destino = pino C
Auxiliar = pino B

Passo 7) Agora podemos ver isso

Resolva o quebra-cabeça da Torre de Hanói

d é mover os discos restantes do auxiliar (ponto B) para o destino (ponto C). Usaremos a fonte inicial ou pino A como auxiliar neste caso.

Passo 8) Como não podemos mover dois discos simultaneamente, chamaremos uma chamada recursiva para o disco 1. De acordo com o último passo e nosso algoritmo, um destino nesta etapa é o pino A.

Resolva o quebra-cabeça da Torre de Hanói

Nesta fase:

Fonte = pino B
Destino = pino A
Auxiliar = pino C

Passo 9) Nossa chamada recursiva está concluída agora. Em seguida, movemos o disco 2 da origem para o destino.

Resolva o quebra-cabeça da Torre de Hanói

Nesta fase:

Fonte = pino B
Destino = pino C
Auxiliar = pino A

Passo 10) Em seguida, movemos nosso n-1 ou disco 1 restante do auxiliar para o destino.

Resolva o quebra-cabeça da Torre de Hanói

Nesta fase:

Fonte = pino A
Destino = pino C
Auxiliar = pino B

Pseudocódigo da Torre de Hanói

START
Procedure Tower_Of_Hanoi(disk, source, dest, helper)
  		IF disk == 1, THEN
      			move disk from source to dest             
   		ELSE
     			Tower_Of_Hanoi (disk - 1, source, helper, dest)     
      			move disk from source to dest          
      			Tower_Of_Hanoi (disk - 1, helper, dest, source)     
   		END IF   
END Procedure

Código do programa em C++

#include <bits/stdc++.h>
using namespace std;
void tower_of_hanoi(int num, string source, string dest, string helper) {
  if (num == 1) {
    cout << " Move disk 1 from tower " << source << " to tower " << dest << endl;
    return;
  }
  tower_of_hanoi(num - 1, source, helper, dest);
  cout << " Move disk " << num << " from tower " << source << " to tower " << dest << endl;
  tower_of_hanoi(num - 1, helper, dest, source);
}
int main() {
  int num;
  cin >> num;
  printf("The sequence of moves :\n");
  tower_of_hanoi(num, "I", "III", "II");
  return 0;
}

saída

3
The sequence of moves :
Move disk 1 from tower I to tower III
Move disk 2 from tower I to tower II
Move disk 1 from tower III to tower II
Move disk 3 from tower I to tower III
Move disk 1 from tower II to tower I
Move disk 2 from tower II to tower III
Move disk 1 from tower I to tower III

Código do programa em Python

def tower_of_hanoi(n, source, destination, helper):
	if n==1:
		print ("Move disk 1 from peg", source," to peg", destination)
		return
	tower_of_hanoi(n-1, source, helper, destination)
	print ("Move disk",n," from peg", source," to peg", destination)
	tower_of_hanoi(n-1, helper, destination, source)		
# n = number of disks
n = 3
tower_of_hanoi(n,' A','B','C')

Saída:

Move disk 1 from peg A to peg B
Move disk 2 from peg A to peg C
Move disk 1 from peg B to peg C
Move disk 3 from peg A to peg B
Move disk 1 from peg C to peg A
Move disk 2 from peg C to peg B
Move disk 1 from peg A to peg B

Complexidade da Torre de Hanói

Aqui está a complexidade de tempo e espaço da Torre de Hanói:

1) Complexidade de tempo:

Se olharmos novamente para o nosso algoritmo, podemos ver que estamos introduzindo uma chamada recursiva para (n-1) discos duas vezes. Essas chamadas recursivas para (n-1) discos podem ser divididas em outros ((n-1)-1) e assim por diante até conseguirmos mover apenas um disco.

Para três discos-

  • O disco 3 chama uma função recursiva para o disco dois duas vezes.
  • O disco 2 chama uma função recursiva para o disco um duas vezes.
  • O disco 1 pode se mover dentro de um tempo constante e um tempo para resolver três discos.

= 2*(Tempo para resolver dois discos) + constante Tempo para mover o disco 3

= 2*(2*tempo para resolver um disco + tempo constante para mover o disco 2) + tempo constante para mover o disco 3

= (2*2) (tempo constante para mover o disco 1) + 2*tempo constante para mover o disco 2 + tempo constante para mover o disco 3

Para n discos, pode ser escrito como –

(2n-1 * tempo constante para mover o disco 1 + 2n-2 * tempo constante para mover o disco 2 +….

Esta progressão geométrica resultará em O(2n-1) ou O (2n), que é exponencial.

2) Complexidade espacial

A complexidade espacial da Torre de Hanói é 0(n). Isso porque precisamos armazenar a sequência das placas. Quando usamos a recursão, estamos usando a pilha. E o tamanho máximo da pilha pode ser “n”. É por isso que a complexidade do espaço se torna O(n).