Advertisement
luisoncpp

Hanoi - Editorial

Feb 5th, 2018
192
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.76 KB | None | 0 0
  1. #include <algorithm>
  2. #include <vector>
  3. #include <deque>
  4. #include <cstdlib>
  5. #include <cassert>
  6. #include "EasyBMP.h"
  7. using namespace std;
  8.  
  9. RGBApixel Black;
  10. RGBApixel White;
  11.  
  12. void initColors() {
  13.     Black.Red = 0x0;
  14.     Black.Blue = 0x0;
  15.     Black.Green = 0x0;
  16.     Black.Alpha = 0xFF;
  17.     White.Red = 0xFF;
  18.     White.Blue = 0xFF;
  19.     White.Green = 0xFF;
  20.     White.Alpha = 0xFF;
  21. }
  22.  
  23. struct Point {
  24.     int x;
  25.     int y;
  26.     Point() {
  27.         x = 0;
  28.         y = 0;
  29.     }
  30.     Point(int x, int y) {
  31.         this->x = x;
  32.         this->y = y;
  33.     }
  34. };
  35.  
  36. struct Rectangle {
  37.     Point lowCorner;
  38.     Point highCorner;
  39.     Rectangle(Point a, Point b) {
  40.         lowCorner = a;
  41.         highCorner = b;
  42.     }
  43.     void fillInBMPwithColor(BMP& bmp, RGBApixel color) {
  44.         for (int i = lowCorner.x; i < highCorner.x; i++) {
  45.             for (int k = lowCorner.y; k < highCorner.y; k++) {
  46.                 bmp.SetPixel(i, k, color);
  47.             }
  48.         }
  49.     }
  50. };
  51.  
  52. void drawBorderedRectangleAtBmp(Rectangle rect, BMP& bmp) {
  53.     rect.fillInBMPwithColor(bmp, Black);
  54.     rect.highCorner = Point(rect.highCorner.x - 2, rect.highCorner.y - 2);
  55.     rect.lowCorner = Point(rect.lowCorner.x + 2, rect.lowCorner.y + 2);
  56.     rect.fillInBMPwithColor(bmp, White);
  57. }
  58.  
  59. void clearBmp(BMP& bmp) {
  60.     Rectangle(Point(0, 0), Point(bmp.TellWidth(), bmp.TellHeight())).fillInBMPwithColor(bmp, White);
  61. }
  62.  
  63. int disks[50];
  64.  
  65. void drawHanoiTowers(BMP& bmp) {
  66.     Rectangle tower(Point(0, 10), Point(20, bmp.TellHeight() - 10));
  67.     int d = 0;
  68.     for(int x = bmp.TellWidth() / 6; x < bmp.TellWidth(); x += bmp.TellWidth() / 3) {
  69.         tower.lowCorner.x = x - 10;
  70.         tower.highCorner.x = x + 10;
  71.         tower.fillInBMPwithColor(bmp, Black);
  72.         int start_disks = d;
  73.         for ( ; d < 50 && disks[d] >= 0; d++) {
  74.  
  75.         }
  76.         int end_disks = d;
  77.         std::sort(disks + start_disks, disks + end_disks);
  78.         std::reverse(disks + start_disks, disks + end_disks);
  79.         int y = bmp.TellHeight() - 10;
  80.         for (int k = start_disks; k < end_disks; k++) {
  81.             int width = disks[k] * 2 + 20;
  82.             Rectangle disk(Point(x - width, y - 6), Point(x + width, y + 6));
  83.             y -= 10;
  84.             // printf("%d %d %d %d\n", disk.lowCorner.x, disk.lowCorner.y, disk.highCorner.x, disk.highCorner.y);
  85.             drawBorderedRectangleAtBmp(disk, bmp);
  86.         }
  87.         d++;
  88.     }
  89. }
  90.  
  91. void fillInputData() {
  92.  for (int i = 0; i < 48; i++) {
  93.     disks[i] = i;
  94.  }
  95.  disks[48] = -1;
  96.  disks[49] = -2;
  97.  for (int k = 0; k < 100; k++) {
  98.     std::random_shuffle(disks, disks + 50);
  99.  }
  100.  // freopen("output.txt", "w", stdout);
  101.  for (int i = 0; i < 51; i++) {
  102.     printf("%d\n", disks[i]);
  103.  }
  104. }
  105.  
  106. class HanoiSolver {
  107. private:
  108.     int movementsRemaining;
  109.     vector<int> tower[3];
  110.     bool isDiskOnTower(int disk, const vector<int>& t) {
  111.         for (auto i : t) {
  112.             if (disk == i) {
  113.                 return true;
  114.             }
  115.         }
  116.         return false;
  117.     }
  118.     int findDisk(int disk) {
  119.         int ret = -1;
  120.         for (int i = 0; i < 3; i++) {
  121.             if(isDiskOnTower(disk, tower[i])) {
  122.                 ret = i;
  123.                 break;
  124.             }
  125.         }
  126.         assert(ret != -1);
  127.         return ret;
  128.     }
  129.     int otherTowerIndex(int a, int b) {
  130.         return 3 - a - b;
  131.     }
  132.     void moveDiskFromTowerToTower(int a, int b) {
  133.         printf("Move from %d to %d\n", a, b);
  134.         assert(tower[a].size() > 0);
  135.         assert(tower[b].size() == 0 || tower[a].back() < tower[b].back());
  136.         int disk = tower[a].back();
  137.         tower[a].pop_back();
  138.         tower[b].push_back(disk);
  139.         /*for (int k = 0; k < 3; k++){
  140.            for (int i = 0; i < tower[k].size(); i++){
  141.                printf("%d ", tower[k][i]);
  142.            }
  143.            printf("\n");
  144.         }*/
  145.         movementsRemaining--;
  146.         if (movementsRemaining < 1) {
  147.             exit(0);
  148.         }
  149.     }
  150.     void solveNormalHanoi(int numberOfDisks, int origin, int dest) {
  151.         if (numberOfDisks == 1) {
  152.             moveDiskFromTowerToTower(origin, dest);
  153.         } else {
  154.             int other = otherTowerIndex(origin, dest);
  155.             solveNormalHanoi(numberOfDisks - 1, origin, other);
  156.             moveDiskFromTowerToTower(origin, dest);
  157.             solveNormalHanoi(numberOfDisks - 1, other, dest);
  158.         }
  159.     }
  160.     void moveAllEqualOrSmallerDisksToTower(int disk, int destTower) {
  161.         int originTower = findDisk(disk);
  162.         if (disk == 0) {
  163.             if(originTower != destTower) {
  164.                 moveDiskFromTowerToTower(originTower, destTower);
  165.             }
  166.             return;
  167.         }
  168.         if (originTower == destTower) {
  169.             return moveAllEqualOrSmallerDisksToTower(disk - 1, destTower);
  170.         }
  171.         int otherTower = otherTowerIndex(originTower, destTower);
  172.         moveAllEqualOrSmallerDisksToTower(disk - 1, otherTower);
  173.         moveDiskFromTowerToTower(originTower, destTower);
  174.         solveNormalHanoi(disk, otherTower, destTower);
  175.     }
  176. public:
  177.     void solveHanoi(const vector<int>& a, const vector<int>& b, const vector<int>& c, int dest) {
  178.         movementsRemaining = 200;
  179.         tower[0] = a;
  180.         tower[1] = b;
  181.         tower[2] = c;
  182.         for (int i = 0; i < 3; i++) {
  183.             sort(tower[i].begin(), tower[i].end());
  184.             reverse(tower[i].begin(), tower[i].end());
  185.         }
  186.         moveAllEqualOrSmallerDisksToTower(a.size() + b.size() + c.size() - 1, dest);
  187.         assert(tower[dest].size() == a.size() + b.size() + c.size());
  188.     }
  189.  
  190. };
  191.  
  192. HanoiSolver solver;
  193.  
  194. void testSolver(int n) {
  195.  vector<int> tower[3];
  196.  for (int i = n - 1; i >= 0; i--) {
  197.     int towerId = rand() % 3;
  198.     tower[towerId].push_back(i);
  199.  }
  200.  for (int k = 0; k < 3; k++){
  201.     for (int i = 0; i < tower[k].size(); i++){
  202.         printf("%d ", tower[k][i]);
  203.     }
  204.     printf("\n");
  205.  }
  206.  solver.solveHanoi(tower[0], tower[1], tower[2], 0);
  207. }
  208.  
  209. void solveBigCase() {
  210.     vector<int> towers[3];
  211.     int index = 0;
  212.     for (int i = 0; i < 50; i++) {
  213.         if (disks[i] < 0) {
  214.             index++;
  215.         } else {
  216.             towers[index].push_back(disks[i]);
  217.         }
  218.     }
  219.     solver.solveHanoi(towers[0], towers[1], towers[2], 1);
  220. }
  221.  
  222. int main( int argc, char* argv[] )
  223. {
  224.     initColors();
  225.  cout << endl
  226.       << "Using EasyBMP Version " << _EasyBMP_Version_ << endl << endl
  227.       << "Copyright (c) by the EasyBMP Project 2005-6" << endl
  228.       << "WWW: http://easybmp.sourceforge.net" << endl << endl;
  229.  
  230.  BMP Output;
  231.  Output.SetSize( 800 , 550 );
  232.  Output.SetBitDepth( 24 );
  233.  clearBmp(Output);
  234.  fillInputData();
  235.  drawHanoiTowers(Output);
  236.  
  237.  cout << "writing 24bpp ... " << endl;
  238.  Output.WriteToFile( "output.bmp" );
  239.  solveBigCase();
  240. // testSolver(5);
  241.  return 0;
  242. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement