Punchcard

Hanoi Tower

Jul 8th, 2023 (edited)
159
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.02 KB | Source Code | 0 0
  1. #include <cmath>
  2. #include <string>
  3. #include <iostream>
  4. #include <stdexcept>
  5. #include <vector>
  6.  
  7. using namespace std;
  8.  
  9. class Tower {
  10. public:
  11.     // конструктор и метод SetDisks нужны, чтобы правильно создать башни
  12.     Tower(int disks_num) {     
  13.         FillTower(disks_num);
  14.     }
  15.  
  16.     int GetDisksNum() const {
  17.         return disks_.size();
  18.     }
  19.  
  20.     void SetDisks(int disks_num) {
  21.         FillTower(disks_num);
  22.     }
  23.  
  24.     // добавляем диск на верх собственной башни
  25.     // обратите внимание на исключение, которое выбрасывается этим методом
  26.     void AddToTop(int disk) {
  27.         int top_disk_num = disks_.size() - 1;
  28.         if (0 != disks_.size() && disk >= disks_[top_disk_num]) {
  29.             throw invalid_argument("Unable to place larger on top of a smaller");
  30.         } else {
  31.             disks_.push_back(disk);
  32.             // допишите этот метод и используйте его в вашем решении
  33.         }
  34.     }
  35.    
  36.     int FetchFromTop() {
  37.        
  38.         return disks_.back();
  39.     }  
  40.    
  41.     int RemoveFromTop () {
  42.        
  43.         if(disks_.empty()) throw invalid_argument("No more disks left on this tower");
  44.         int ret = disks_.back();
  45.         disks_.pop_back();
  46.         return ret;
  47.     }
  48.    
  49.  
  50.     void MoveDisk (Tower& from, Tower& to) {
  51.        
  52.         int disk = from.FetchFromTop();
  53.         i++;
  54.         try {
  55.             to.AddToTop(disk);
  56.             from.RemoveFromTop();
  57.         } catch (...) {
  58.             try {
  59.                 disk = to.FetchFromTop();
  60.                 from.AddToTop(disk);
  61.                 to.RemoveFromTop();
  62.             } catch (...) {
  63.                 return;
  64.             }
  65.         }
  66.     }
  67.    
  68.     // disks_num - количество перемещаемых дисков
  69.     // destination - конечная башня для перемещения
  70.     // buffer - башня, которую нужно использовать в качестве буфера для дисков
  71.     void MoveDisksEven(int disks_num, Tower& destination, Tower& buffer) {
  72.        
  73.         if (destination.GetDisksNum() == disks_num) return;
  74.        
  75.         MoveDisk(*this, buffer);
  76.        
  77.         MoveDisk(*this, destination);
  78.        
  79.         MoveDisk(buffer, destination);     
  80.    
  81.         MoveDisksEven(disks_num, destination, buffer);
  82.          
  83.         return;
  84.     }      
  85.    
  86.     void MoveDisksOdd(int disks_num, Tower& destination, Tower& buffer) {
  87.        
  88.         if (destination.GetDisksNum() == disks_num) return;
  89.         MoveDisk(*this, destination);
  90.         if (destination.GetDisksNum() == disks_num) return;
  91.         MoveDisk(*this, buffer);
  92.         if (destination.GetDisksNum() == disks_num) return;
  93.         MoveDisk(buffer, destination);     
  94.    
  95.         MoveDisksOdd(disks_num, destination, buffer);
  96.          
  97.         return;
  98.     }              
  99.    
  100.     void MoveDisks(int disks_num, Tower& destination, Tower& buffer) {
  101.        
  102.        
  103.         if (destination.GetDisksNum() == disks_num) return;
  104.         bool if_even = (disks_num % 2) == 0;
  105.        
  106.         if (if_even)
  107.             MoveDisk(*this, buffer);
  108.         else
  109.             MoveDisk(*this, destination);
  110.         if (destination.GetDisksNum() == disks_num) return;
  111.        
  112.         if (if_even)
  113.             MoveDisk(*this, destination);
  114.         else
  115.             MoveDisk(*this, buffer);       
  116.         if (destination.GetDisksNum() == disks_num) return;            
  117.  
  118.         MoveDisk(buffer, destination);     
  119.    
  120.         MoveDisks(disks_num, destination, buffer);
  121.          
  122.         return;
  123.     }          
  124.  
  125.     string PrintTower() {
  126.  
  127.         string ret;
  128.         for (int disk : disks_) {
  129.             ret += to_string(disk) + " "s;
  130.         }
  131.         return ret;
  132.     }
  133.  
  134.     // вы можете дописывать необходимые для вашего решения методы
  135.     int64_t i = 0;
  136. private:
  137.     vector<int> disks_;
  138.  
  139.     // используем приватный метод FillTower, чтобы избежать дубликации кода
  140.     void FillTower(int disks_num) {
  141.         for (int i = disks_num; i > 0; i--) {
  142.             disks_.push_back(i);
  143.         }
  144.     }
  145. };
  146.  
  147.  
  148.  
  149.  void SolveHanoi(vector<Tower>& towers) {
  150.      int disks_num = towers[0].GetDisksNum();
  151.      // запускаем рекурсию
  152.      // просим переложить все диски на последнюю башню
  153.      // с использованием средней башни как буфера
  154.    
  155.     towers[0].MoveDisks(disks_num, towers[2], towers[1]);
  156.    
  157.  }
  158.  
  159.  
  160. void PrintTowers(vector<Tower>& towers) {
  161.    
  162.     int i = 0;
  163.     for (Tower tower : towers) {
  164.         cout << "Tower "s << ++i << ": "s << tower.PrintTower() << endl;
  165.     }
  166.     cout << endl;
  167. }
  168.  
  169.  
  170. int main() {
  171.     int towers_num = 3;
  172.     int disks_num = 21;
  173.     int d_in = 0;
  174.     cout << "Enter amount of disks (0 - 16):";
  175.     cin >> d_in;
  176.     if (d_in > 0) disks_num = d_in;
  177.     cout << "Total number of disks is "s << disks_num << ", expected number of moves="s << pow(2, disks_num) - 1 << endl;
  178.     vector<Tower> towers;
  179.     // добавим в вектор три пустые башни
  180.     for (int i = 0; i < towers_num; ++i) {
  181.         towers.push_back(0);
  182.     }
  183.     // добавим на первую башню три кольца
  184.     PrintTowers(towers);
  185.     towers[0].SetDisks(disks_num);
  186.     PrintTowers(towers);
  187.     SolveHanoi(towers);
  188.     PrintTowers(towers);
  189.     cout << towers[0].i << endl;
  190. }
Advertisement
Add Comment
Please, Sign In to add comment