Advertisement
Guest User

Tantrix

a guest
Feb 4th, 2021
130
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.26 KB | None | 0 0
  1. #include <iostream>
  2. #include <list>
  3. #include <vector>
  4. #include <string>
  5. #include <sstream>
  6.  
  7. enum colorState {r, g, b, y};
  8.  
  9. enum rot {I,II,III,IIII,IIIII,IIIIII};
  10.  
  11. const int dirs[6][2] = { {0,1},
  12.                          {1,1},
  13.                          {1,0},
  14.                          {0,-1},
  15.                          {-1,-1},
  16.                          {-1,0} };
  17.  
  18. int totalBoards = 0;
  19. int perm = 0;
  20.  
  21. class coords {
  22.     public:int x;
  23.     public:int y;
  24.    
  25.     public:coords() = default;
  26.  
  27.     friend bool operator==(const coords& c1, const coords& c2) {
  28.         return c1.x == c2.x && c1.y == c2.y;
  29.     }
  30.  
  31.     public:coords(int nx, int ny) {
  32.         x = nx;
  33.         y = ny;
  34.     }
  35. };
  36.  
  37. class tile {
  38.     public:colorState states[6];
  39.     public:int identifier;
  40.     public:coords coordinates;
  41.  
  42.     public:tile() = default;
  43.  
  44.     friend bool operator==(const tile& t1, const tile& t2) {
  45.         return t1.identifier == t2.identifier;
  46.     }
  47.  
  48.     public:tile(colorState s[6], int i, coords c) {
  49.         *states = *s;
  50.         identifier = i;
  51.         coordinates = c;
  52.     }
  53.  
  54.     public:void rotateC() {
  55.         colorState tmpA,tmpB;
  56.         tmpA = states[1];
  57.         states[1] = states[0];
  58.         tmpB = states[2];
  59.         states[2] = tmpA;
  60.         tmpA = states[3];
  61.         states[3] = tmpB;
  62.         tmpB = states[4];
  63.         states[4] = tmpA;
  64.         tmpA = states[5];
  65.         states[5] = tmpB;
  66.         states[0] = tmpA;
  67.     }
  68.  
  69.     public:void rotateAC() {
  70.         colorState tmpA, tmpB;
  71.         tmpA = states[0];
  72.         states[0] = states[1];
  73.         tmpB = states[5];
  74.         states[5] = tmpA;
  75.         tmpA = states[4];
  76.         states[4] = tmpB;
  77.         tmpB = states[3];
  78.         states[3] = tmpA;
  79.         tmpA = states[2];
  80.         states[2] = tmpB;
  81.         states[1] = tmpA;
  82.     }
  83.  
  84.     public:void alterX(int altX) {
  85.         coordinates.x += altX;
  86.     }
  87.  
  88.     public:void alterY(int altY) {
  89.         coordinates.y += altY;
  90.     }
  91.  
  92.     public:void setX(int altX) {
  93.         coordinates.x = altX;
  94.     }
  95.  
  96.     public:void setY(int altY) {
  97.         coordinates.y = altY;
  98.     }
  99. };
  100.  
  101. class tileRot {
  102.     public: tile t;
  103.     public: rot r;
  104.    
  105.     public:tileRot(tile nt, rot nr) {
  106.         t = nt;
  107.         r = nr;
  108.     }
  109. };
  110.  
  111. bool compareTiles(const tile& a, const tile& b) {
  112.     if (a.coordinates.x < b.coordinates.x) return true;
  113.     if (b.coordinates.x < a.coordinates.x) return false;
  114.  
  115.     if (a.coordinates.y < b.coordinates.y) return true;
  116.     if (b.coordinates.y < a.coordinates.y) return false;
  117. }
  118.  
  119. class board {
  120.     public:std::list<tile> boardtiles;
  121.    
  122.     public:board(){
  123.         boardtiles = std::list<tile>();
  124.     }
  125.  
  126.     public:void addToBoard(tile toadd) {
  127.         boardtiles.push_back(toadd);
  128.     }
  129.  
  130.     public:void removeFromBoard(tile toadd) {
  131.         boardtiles.remove(toadd);
  132.     }
  133.  
  134.     public:std::list<tile> getBoard() {
  135.         return boardtiles;
  136.     }
  137.  
  138.     public:std::list<coords> getAdjecentCoords() {
  139.         std::list<coords> result = std::list<coords>();
  140.         for (tile t : boardtiles) {
  141.             for (int i = 0; i < 6; i++) {
  142.                 int x = t.coordinates.x + dirs[i][0];
  143.                 int y = t.coordinates.y + dirs[i][1];
  144.                 if (std::find(result.begin(), result.end(), coords{ x,y }) != result.end())
  145.                     break;
  146.                 else for (tile tTMP : boardtiles)
  147.                     if (tTMP.coordinates.x == x && tTMP.coordinates.y == y)
  148.                         result.push_back(coords{ x,y });
  149.             }
  150.         }
  151.         return result;
  152.     }
  153.  
  154.     public:std::list<coords> getValidCoords(std::list<coords> adjCoords) {
  155.         std::list<coords> result = std::list<coords>();
  156.         for (coords c : adjCoords) {
  157.             int tileCount = 0;
  158.             for (int i = 0; i < 6; i++) {
  159.                 int x = c.x + dirs[i][0];
  160.                 int y = c.y + dirs[i][1];
  161.                 for (tile t : boardtiles) {
  162.                     if (t.coordinates.x == x, t.coordinates.y == y)
  163.                         tileCount++;
  164.                 }
  165.             }
  166.             if (tileCount > 1)
  167.                 result.push_back(c);
  168.         }
  169.         return result;
  170.     }
  171.  
  172.  
  173.     public:void printBoard() {
  174.         std::list<tile> tmp = boardtiles;
  175.         tmp.sort(compareTiles);
  176.         for (tile t : tmp)
  177.             printf("%s",generateTile(t).c_str());
  178.     }
  179.  
  180.     private:std::string generateTile(tile t) {
  181.         std::ostringstream stream;
  182.         stream << "  == ++\n";
  183.         stream << " =%c    %c+\n", enumToChar(t.states[4]), enumToChar(t.states[5]);
  184.         stream << "| %c %2d %c |\n", enumToChar(t.states[3]),t.identifier, enumToChar(t.states[0]);
  185.         stream << " =%c    %c+\n", enumToChar(t.states[2]), enumToChar(t.states[1]);
  186.         stream << "  == ++\n";
  187.         return stream.str();
  188.     }
  189.  
  190.     private:char enumToChar(colorState state) {
  191.         if (state == r)
  192.             return 'r';
  193.         if (state == g)
  194.             return 'g';
  195.         if (state == b)
  196.             return 'b';
  197.         if (state == y)
  198.             return 'y';
  199.     }
  200. };
  201.  
  202. void calcboard(std::vector<tile> permVec, board b);
  203. std::list<std::list<tile>> findPermutations(std::list<tile> original);
  204. std::list<tileRot> getValidSpacesForTile(tile t, bool secondToAdd, board b);
  205. bool checkLineContinuous(colorState state, board b);
  206. tile* findTile(int x, int y, board b);
  207. bool checkValidPosition(tile pos, board b);
  208.  
  209. int main()
  210. {
  211.     tile Tc[14] = { tile(new colorState[6]{r,g,g,b,b,r},1 ,{INT16_MIN,INT16_MIN}),
  212.                     tile(new colorState[6]{g,r,r,b,b,g},2 ,{INT16_MIN,INT16_MIN}),
  213.                     tile(new colorState[6]{r,b,b,r,g,g},3 ,{INT16_MIN,INT16_MIN}),
  214.                     tile(new colorState[6]{g,r,r,g,b,b},4 ,{INT16_MIN,INT16_MIN}),
  215.                     tile(new colorState[6]{b,r,r,b,g,g},5 ,{INT16_MIN,INT16_MIN}),
  216.                     tile(new colorState[6]{r,g,g,b,b,r},6 ,{INT16_MIN,INT16_MIN}),
  217.                     tile(new colorState[6]{g,r,b,g,b,r},7 ,{INT16_MIN,INT16_MIN}),
  218.                     tile(new colorState[6]{b,r,g,b,g,r},8 ,{INT16_MIN,INT16_MIN}),
  219.                     tile(new colorState[6]{g,r,r,b,g,b},9 ,{INT16_MIN,INT16_MIN}),
  220.                     tile(new colorState[6]{r,g,g,b,r,b},10,{INT16_MIN,INT16_MIN}),
  221.                     tile(new colorState[6]{r,b,b,g,r,g},11,{INT16_MIN,INT16_MIN}),
  222.                     tile(new colorState[6]{b,r,r,g,b,g},12,{INT16_MIN,INT16_MIN}),
  223.                     tile(new colorState[6]{b,g,g,r,b,r},13,{INT16_MIN,INT16_MIN}),
  224.                     tile(new colorState[6]{g,b,b,r,g,r},14,{INT16_MIN,INT16_MIN}),
  225.                   };
  226.  
  227.     printf("starting...\n");
  228.  
  229.     for (int iFirst = 0; iFirst < 14; iFirst++) {
  230.         board b = board();
  231.  
  232.         std::list<tile> toAdd = std::list<tile>();
  233.        
  234.  
  235.         Tc[iFirst].coordinates.x = 0;
  236.         Tc[iFirst].coordinates.y = 0;
  237.  
  238.         b.addToBoard(Tc[iFirst]);
  239.         for (int iNext = 0; iNext < 14; iNext++) {
  240.             if (iNext != iFirst)
  241.                 toAdd.push_back(Tc[iNext]);
  242.         }
  243.         //we have to add 13 more tiles.
  244.         for (std::list<tile> perm : findPermutations(toAdd)) {
  245.             printf("Permutations found");
  246.             std::vector<tile> permVec(perm.begin(), perm.end());
  247.             calcboard(permVec, b);
  248.         }
  249.     }
  250.     printf("finished \n");
  251. }
  252.  
  253. //provide a board with tiles layed on them and premVec an list of tiles to still place on the board.
  254. void calcboard(std::vector<tile> permVec, board b) {
  255.     bool secondToAdd;
  256.     std::list<tileRot> valid = std::list<tileRot>();
  257.     secondToAdd = true;
  258.     //iterate through all tiles in the list
  259.     for (int iTile = 0; iTile < 13; iTile++) {
  260.         //obtain the list of valid tiles and rotation for the iTileth tile of the list
  261.         valid = getValidSpacesForTile(permVec.at(iTile), secondToAdd, b);
  262.         //we now have a list of all valid positions for all rotations for the tile to insert next given the previous board.
  263.         for (tileRot tileValid : valid) {
  264.             //add the tile to the board so we can recursively see how the next tile fits the board.
  265.             b.addToBoard(tileValid.t);
  266.             //check if there are still tiles to place
  267.             if (permVec.size() > 0) {
  268.                 //create a copy of the list
  269.                 std::vector<tile> cpy = permVec;
  270.                 //remove the placed element from the copy
  271.                 cpy.erase(cpy.begin() + iTile);
  272.                 //calculate all board options for the remaining tiles.
  273.                 calcboard(cpy, b);
  274.             } else {
  275.                 totalBoards++;
  276.                 //check if the board contains a single line for state "r" (currently potentially broken)
  277.                 if (checkLineContinuous(r, b))
  278.                 {
  279.                     //we've found a line that works, print the board.
  280.                     printf("Board %d is valid!\n", totalBoards);
  281.                     b.printBoard();
  282.                 }
  283.                 else
  284.                 {
  285.                     //we've found an invalid board.
  286.                     printf("Board %d is invalid!\n", totalBoards);
  287.                 }
  288.             }
  289.             //remove the tile from the board so it can be added somewhere else.
  290.             b.removeFromBoard(tileValid.t);
  291.         }
  292.         secondToAdd = false;
  293.     }
  294. }
  295.  
  296. bool checkLineContinuous(colorState state, board b) {
  297.     int outs = 0;
  298.     for (tile t : b.boardtiles) {
  299.         //enumerate through each position
  300.         for (int i = 0; i < 6; i++) {
  301.             if (t.states[i] = state) {
  302.                 // find the neighbour in the list
  303.                 tile* neighbour = findTile(t.coordinates.x + dirs[i][0],
  304.                                            t.coordinates.y + dirs[i][1],
  305.                                            b);
  306.                 if (neighbour == nullptr) {
  307.                     outs++;
  308.                 }
  309.             }
  310.         }
  311.     }
  312.     return outs == 2;
  313. }
  314.  
  315. std::list<tileRot> getValidSpacesForTile(tile t,bool secondToAdd, board b) {
  316.     std::list<tileRot> valid = std::list<tileRot>();
  317.     for (int iRot = 0; iRot < 6; iRot++) {
  318.         std::list<coords> toCheck = b.getAdjecentCoords();
  319.         if (!secondToAdd)
  320.             toCheck = b.getValidCoords(toCheck);
  321.         for (coords c : toCheck) {
  322.             t.setX(c.x);
  323.             t.setX(c.y);
  324.             if (checkValidPosition(t, b)) {
  325.                 valid.push_back(tileRot(t, (rot)iRot));
  326.             }
  327.         }
  328.         t.rotateC();
  329.     }
  330.     return valid;
  331. }
  332.  
  333. std::list<std::list<tile>> findPermutations(std::list<tile> original)
  334. {
  335.     perm++;
  336.     if (perm % 1000000000 == 0)
  337.     {
  338.         printf("perm reached %1.000.000.000\n");
  339.     }
  340.     std::list<std::list<tile>> result = std::list<std::list<tile>>();
  341.     if (original.size() == 2)
  342.     {
  343.         // these are permutations of array of size 2
  344.         result.push_back(std::list<tile>(original));
  345.         result.push_back(std::list<tile>{original.end(),original.begin()});
  346.         return result;
  347.     }
  348.     else
  349.     {
  350.         // going through array
  351.         for(tile t : original)
  352.         {
  353.             // creating subarray = array
  354.             std::list<tile> rlist = std::list<tile>(original);
  355.             // removing element
  356.             rlist.remove(t);
  357.             for(std::list<tile> retlist : findPermutations(rlist))
  358.             {
  359.                 retlist.push_front(t); // inserting the element at pos 0
  360.                 result.push_back(retlist);
  361.             }
  362.         }
  363.     }
  364.     return result;
  365. }
  366.  
  367. bool checkValidPosition(tile pos, board b) {
  368.     //the directions from pos to each neighbour
  369.  
  370.     //enumerate through each position
  371.     for (int i = 0; i < 6; i++) {
  372.         // find the neighbour in the list
  373.         tile* neighbour = findTile(pos.coordinates.x + dirs[i][0],
  374.                                    pos.coordinates.y + dirs[i][1],
  375.                                    b);
  376.         //check if neighbour exists
  377.         if(neighbour != nullptr)
  378.             //check if the 2 states next to each other don't match
  379.             if (neighbour->states[(i + 3) % 6] != pos.states[i])
  380.                 //if there is no match, the position is invalid
  381.                 return false;
  382.     }
  383.     //all existing neoghbours have matching states
  384.     return true;
  385. }
  386.  
  387. tile* findTile(int x, int y, board b) {
  388.     for (tile b : b.boardtiles)
  389.         if (x == b.coordinates.x && y == b.coordinates.y)
  390.             return &b;
  391.     return nullptr;
  392. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement