Hanoi torni algoritm: Python, C++ kood

Mis on Hanoi torn?

Hanoi torn on matemaatiline pusle, mis koosneb kolmest vardast ja paljudest üksteise peale asetatud ketastest. Seda tuntakse ka kui Brahma torni või Lucase torni, kuna prantsuse matemaatik Edouard Lucas tutvustas seda juba aastal 1883. See pusle põhineb legendidel kuldketaste liigutamisest kolme varda vahel.

Sellel puslel on kolm varrast ja muutuv arv virnastatud kettaid. Need vardad on konstrueeritud tsükliliste tornidena. Niisiis, suurema läbimõõduga kettad on virnastatud põhja ja väiksemad kettad on virnastatud.

Esialgu antakse meile kolm pulka või varda. Ja ühes neist (näites näidatud A) on kõik kettad virnastatud. Meie eesmärk on teisaldada terve virn kettaid ühelt vardalt (A) teisele (C), järgides teatud reegleid.

Siin on mõistatuse esialgne seadistus -

Hanoi torni probleem
Hanoi torni probleem

Ja see on viimane eesmärk -

Hanoi torn

Hanoi torni reeglid

Siin on mõned olulised reeglid Hanoi torni jaoks:

  • Selle pusle esialgne olek, kõik kettad on virnastatud varras üks.
  • Lõppseisund on see, et kõik need esimese varda kettad asetatakse teise või kolmanda varda peale.
  • Saame igal ajal liigutada ketta ühelt vardalt teisele.
  • Saame varda küljest liigutada ainult kõige ülemist ketast.
  • Ketast ei saa asetada teise ketta peale, mis on väiksem.

Algne legend rääkis 64 ketta teisaldamisest. Preestrid võisid vastavalt reeglitele liigutada ühte ketast korraga. Legendi järgi oli ennustus, et maailmalõpp saabub, kui nad teo lõpule jõuavad. Ajalise keerukuse osas näitame, et n kettast koosnev Tower of Hanoi seadistus maksaks 2^n – 1 liigutus.

Seega, kui preestrid võiksid nõuda ketaste liigutamiseks 1 sekundit, oleks mõistatuse lahendamiseks kuluv koguaeg 2^64 – 1 sekund ehk 584,942,417,356 26 7 15 aastat, XNUMX päeva, XNUMX tundi ja XNUMX sekundit.

Hanoi torni algoritm

Üks üldine viis Hanoi torni lahendamiseks on rekursiivne algoritm. Esiteks peame allika ja sihtkohana otsustama kahe varda või pulga kasuks ning varupulk oleks abi- või abipulk.

Siin on sammud Hanoi torni mõistatuse lahendamiseks:

  • Liigutage ülemised n-1 kettad lähtepulgalt abipulgale.
  • Seejärel liigutage n-s ketas lähtepunktist sihtpunkti.
  • Lõpuks teisaldage ülejäänud n-1 ketast abipulgalt sihtpunkti.

märkused: kui meil on üks ketas, saame selle otse allikast sihtkohta teisaldada.

Kuidas lahendada Hanoi torni mõistatus

Illustreerime kolme ketta algoritmi ja vaatleme allikana pulka A, abimehena pulti B ja sihtkohana puud C.

Step 1) Esialgu asetatakse kõik kettad pulgale A.

Lahenda Hanoi torni mõistatus

Selles etapis:

Allikas = Peg A
Sihtkoht = pulk C
Abimees = pulk B

Nüüd peame ülemised n-1 kettad allikast abistajasse teisaldama.

Märge: Kuigi me saame liigutada ainult ühte ketast korraga, muudab see meie probleemi kolme ketta probleemist kahe ketta probleemiks, mis on rekursiivne kõne.

Step 2) Kuna me nimetame rekursiivset kõnet pulgalt A ja sihtpunktiks on pulk B, kasutame abivahendina pulti C.

Pange tähele, et oleme taas esimeses etapis sama Hanoi torni kahe ketta probleemi jaoks.

Nüüd peame teisaldama n-1 ehk ühe ketta allikast abistaja juurde, liigutades väikseima ketta pulgalt A pulgale C.

Lahenda Hanoi torni mõistatus

Selles etapis:

Allikas = pulk A
Sihtkoht = pulk B
Abimees = pulk C

Step 3) Seejärel tuleks vastavalt meie algoritmile n-nda või 2. ketta vajadus kanda sihtkohta või pulgasse B.

Lahenda Hanoi torni mõistatus

Selles etapis:

Allikas = pulk A
Sihtkoht = pulk B
Abimees = pulk C

Step 4) Nüüd teisaldame n-1 ketast või ketta ühe abimehest või puldist C sihtkohta või pulgasse B vastavalt meie algoritmi kolmandale etapile.

Lahenda Hanoi torni mõistatus

Selles etapis:

Allikas = pulk A
Sihtkoht = pulk B
Abimees = pulk C

Step 5) Pärast rekursiivse kõne lõpetamist naaseme oma eelmise seadistuse juurde, kui algoritmi esimene etapp.

Step 6) Nüüd, teises etapis, teisaldame oma allika sihtkohta, milleks on ketta 3 teisaldamine pulgalt A pulgale C.

Selles etapis:

Allikas = pulk A
Sihtkoht = pulk C
Abimees = pulk B

Step 7) Nüüd näeme seda

Lahenda Hanoi torni mõistatus

d on ülejäänud ketaste teisaldamine abist (pulk B) sihtkohta (pulk C). Kasutame sel juhul abistajana algallikat ehk pulka A.

Step 8) Kuna me ei saa kahte ketast korraga liigutada, kutsume välja ketta 1 rekursiivse kutse. Vastavalt viimasele sammule ja meie algoritm, on selle etapi sihtkoht pulk A.

Lahenda Hanoi torni mõistatus

Selles etapis:

Allikas = pulk B
Sihtkoht = pulk A
Abimees = pulk C

Step 9) Meie rekursiivne kõne on nüüd lõpetatud. Seejärel teisaldame ketta 2 allikast sihtkohta.

Lahenda Hanoi torni mõistatus

Selles etapis:

Allikas = pulk B
Sihtkoht = pulk C
Abimees = pulk A

Step 10) Seejärel viime oma ülejäänud n-1 või ketta 1 abimehest sihtkohta.

Lahenda Hanoi torni mõistatus

Selles etapis:

Allikas = pulk A
Sihtkoht = pulk C
Abimees = pulk B

Hanoi torni pseudokood

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

Programmi kood sisse 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;
}

Väljund

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

Programmi kood sisse 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')

Väljund:

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

Hanoi torni keerukus

Siin on Hanoi torni aja ja ruumi keerukus:

1) Aja keerukus:

Kui vaatame oma algoritmile tagasi, näeme, et me võtame kaks korda sisse (n-1) ketaste rekursiivse kutse. Neid (n-1) ketaste rekursiivseid väljakutseid saab jaotada muudeks ((n-1)-1) ja nii edasi, kuni liigutatakse ainult üks ketas.

Kolme ketta jaoks -

  • Disk 3 kutsub kaks korda rekursiivset funktsiooni kettale kaks.
  • Disk 2 kutsub kaks korda ketta XNUMX rekursiivset funktsiooni.
  • 1. ketas saab liikuda konstantse aja ja kolme ketta lahendamise aja piires.

= 2*(Kahe ketta lahendamise aeg) + konstantne 3. ketta liigutamise aeg

= 2*(2*ühe ketta lahendamise aeg + konstant 2. ketta liigutamise aeg) + konstant 3. ketta liigutamise aeg

= (2*2) (püsiv aeg ketta 1 liigutamiseks) + 2*püsiv aeg ketta 2 liigutamiseks + konstantne aeg ketta 3 liigutamiseks

n ketta puhul saab selle kirjutada järgmiselt -

(2n-1 * konstantne aeg ketta 1 + 2 liigutamiseksn-2 * konstantne aeg ketta 2 liigutamiseks + ….

Selle geomeetrilise progressiooni tulemuseks on O(2n-1) Või O(2n), mis on eksponentsiaalne.

2) Ruumi keerukus

Hanoi torni ruumiline keerukus on 0 (n). Seda seetõttu, et peame salvestama plaatide järjestuse. Kui me kasutame rekursiooni, kasutab see virna. Ja virna maksimaalne suurus võib olla "n". Sellepärast muutub ruumi keerukus O(n).