aimon1337

Untitled

Jan 10th, 2022
217
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.78 KB | None | 0 0
  1. #include <algorithm>
  2. #include <cmath>
  3. #include <cstdlib>
  4. #include <fstream>
  5. #include <iostream>
  6. #include <vector>
  7. using namespace std;
  8.  
  9. struct Node
  10. {
  11.     vector<vector<int>> curState;
  12.     int H, G, N;
  13.     string action;
  14.     Node* parent;
  15.     Node(vector<vector<int>> X, string Action, int g, int h, int n, Node* Parent)
  16.     {
  17.         this->curState = X;
  18.         this->action = Action;
  19.         this->G = g;
  20.         this->N = n;
  21.         this->H = h;
  22.         this->parent = Parent;
  23.     }
  24. };
  25.  
  26. int getInversion(vector<int> arr)
  27. {
  28.     int inv_count = 0;
  29.     for (unsigned int i = 0; i < arr.size() - 1; ++i)
  30.     {
  31.         for (unsigned int j = i + 1; j < arr.size(); ++j)
  32.         {
  33.             inv_count += ((arr[i] > arr[j]) ? 1 : 0);
  34.         }
  35.     }
  36.     return inv_count;
  37. }
  38.  
  39. bool isSolvable(vector<vector<int>> curState, int N)
  40. {
  41.     int empty_row = -1;
  42.     vector<int> arr;
  43.     for (int i = 0; i < N; ++i)
  44.     {
  45.         for (int j = 0; j < N; ++j)
  46.         {
  47.             if (curState[i][j])
  48.                 arr.push_back(curState[i][j]);
  49.             else empty_row = i;
  50.         }
  51.     }
  52.     int inversions = getInversion(arr);
  53.     if (N % 2 == 0 && (empty_row % 2 == !(inversions % 2)))
  54.         return true;
  55.     if (N % 2 == 1 && inversions % 2 == 0)
  56.         return true;
  57.     return false;
  58. }
  59.  
  60. void printData(vector<vector<int>> curState, string outputFilePath)
  61. {
  62.     int N = curState.size();
  63.     ofstream fout(outputFilePath, ios::out | ios::app);
  64.     for (int i = 0; i < N; ++i)
  65.     {
  66.         for (int j = 0; j < N; ++j)
  67.         {
  68.             fout << curState[i][j] << " ";
  69.         }
  70.         fout << endl;
  71.     }
  72.     fout << endl;
  73.     fout.close();
  74. }
  75.  
  76. void getEmptyPosition(vector<vector<int>> curState, int& xPoz, int& yPoz)
  77. {
  78.     for (unsigned int i = 0; i < curState.size(); ++i)
  79.     {
  80.         for (unsigned int j = 0; j < curState.size(); ++j)
  81.         {
  82.             if (curState[i][j] == 0)
  83.             {
  84.                 xPoz = i, yPoz = j;
  85.                 return;
  86.             }
  87.         }
  88.     }
  89. }
  90.  
  91. bool canMoveUp(vector<vector<int>> curState, int N, int xPoz, int yPoz)
  92. {
  93.     for (int i = 0; i < N; ++i)
  94.     {
  95.         if (curState[xPoz][yPoz] == curState[0][i])
  96.             return false;
  97.     }
  98.     return true;
  99. }
  100.  
  101.  
  102. bool canMoveDown(vector<vector<int>> curState, int N, int xPoz, int yPoz)
  103. {
  104.     for (int i = 0; i < N; ++i)
  105.     {
  106.         if (curState[xPoz][yPoz] == curState[N - 1][i])
  107.             return false;
  108.     }
  109.     return true;
  110. }
  111.  
  112.  
  113. bool canMoveLeft(vector<vector<int>> curState, int N, int xPoz, int yPoz)
  114. {
  115.     for (int i = 0; i < N; ++i)
  116.     {
  117.         if (curState[xPoz][yPoz] == curState[i][0])
  118.             return false;
  119.     }
  120.     return true;
  121. }
  122.  
  123.  
  124. bool canMoveRight(vector<vector<int>> curState, int N, int xPoz, int yPoz)
  125. {
  126.     for (int i = 0; i < N; ++i)
  127.     {
  128.         if (curState[xPoz][yPoz] == curState[i][N - 1])
  129.             return false;
  130.     }
  131.     return true;
  132. }
  133.  
  134. void expandState(vector<vector<int>> curState, int N, vector<vector<int>>& child1, vector<vector<int>>& child2, vector<vector<int>>& child3, vector<vector<int>>& child4)
  135. {
  136.     int xPoz, yPoz;
  137.     getEmptyPosition(curState, xPoz, yPoz);
  138.     if (canMoveUp(curState, N, xPoz, yPoz))
  139.     {
  140.         child1 = curState;
  141.         swap(child1[xPoz - 1][yPoz], child1[xPoz][yPoz]);
  142.  
  143.     }
  144.     if (canMoveDown(curState, N, xPoz, yPoz))
  145.     {
  146.         child2 = curState;
  147.         swap(child2[xPoz + 1][yPoz], child2[xPoz][yPoz]);
  148.     }
  149.     if (canMoveLeft(curState, N, xPoz, yPoz))
  150.     {
  151.         child3 = curState;
  152.         swap(child3[xPoz][yPoz - 1], child3[xPoz][yPoz]);
  153.     }
  154.     if (canMoveRight(curState, N, xPoz, yPoz))
  155.     {
  156.         child4 = curState;
  157.         swap(child4[xPoz][yPoz + 1], child4[xPoz][yPoz]);
  158.     }
  159. }
  160.  
  161. int getManhattanDistance(vector<vector<int>>curState, vector<vector<int>> goalState, int N)
  162. {
  163.     int manhattan = 0;
  164.     for (int i = 0; i < N; ++i)
  165.     {
  166.         for (int j = 0; j < N; ++j)
  167.         {
  168.             if (i == N - 1 && j == N - 1)
  169.             {
  170.                 break;
  171.             }
  172.             for (int x = 0; x < N; ++x)
  173.             {
  174.                 for (int y = 0; y < N; ++y)
  175.                 {
  176.                     if (goalState[i][j] == curState[x][y])
  177.                         manhattan = manhattan + abs(i - x) + abs(j - y);
  178.                 }
  179.             }
  180.         }
  181.     }
  182.     return manhattan;
  183. }
  184.  
  185. void getChilds(Node curState, int N, vector<Node>& Tree, string outputFilePath, vector<vector<int>> goalState)
  186. {
  187.     vector<vector<int>> child1, child2, child3, child4;
  188.     expandState(curState.curState, N, child1, child2, child3, child4);
  189.     int H;
  190.     if (!child1.empty())
  191.     {
  192.         H = getManhattanDistance(child1, goalState, N);
  193.         Tree.push_back(Node(child1, "UP", curState.G + 1, H, N, &curState));
  194.     }
  195.     if (!child2.empty())
  196.     {
  197.         H = getManhattanDistance(child2, goalState, N);
  198.         Tree.push_back(Node(child2, "DOWN", curState.G + 1, H, N, &curState));
  199.     }
  200.     if (!child3.empty())
  201.     {
  202.         H = getManhattanDistance(child3, goalState, N);
  203.         Tree.push_back(Node(child3, "LEFT", curState.G + 1, H, N, &curState));
  204.     }
  205.     if (!child4.empty())
  206.     {
  207.         H = getManhattanDistance(child4, goalState, N);
  208.         Tree.push_back(Node(child4, "RIGHT", curState.G + 1, H, N, &curState));
  209.     }
  210. }
  211.  
  212. bool checkForDuplicate(Node node, vector<Node> List)
  213. {
  214.     for (auto itr = List.begin(); itr < List.end(); ++itr)
  215.     {
  216.         if (node.curState == itr->curState)
  217.             return true;
  218.     }
  219.     return false;
  220. }
  221.  
  222. bool operator <(Node A, Node B)
  223. {
  224.     return A.H + A.G < B.H + B.G;
  225. }
  226.  
  227. void aStar(Node input, vector<vector<int>> goalState, int N, string outputFilePath)
  228. {
  229.     vector<Node> openList, closedList;
  230.     openList.push_back(input);
  231.     while (!openList.empty())
  232.     {
  233.         auto min = min_element(openList.begin(), openList.end());
  234.         Node curNode = *min;
  235.         if (curNode.curState == goalState || curNode.H == 0)
  236.         {
  237.             cout << curNode.G << endl;
  238.             printData(curNode.curState, outputFilePath);
  239.             // while (curNode.parent != nullptr)
  240.             // {
  241.             //  printData(curNode.parent->curState, outputFilePath);
  242.             //  curNode = *(curNode.parent);
  243.             // }
  244.             /*
  245.                 ^
  246.                 |
  247.                 asta nu functioneaza, n-am stiut cum sa revin la parinti
  248.             */
  249.             return;
  250.         }
  251.         openList.erase(min);
  252.         closedList.push_back(curNode);
  253.         vector<Node> Tree;
  254.         getChilds(curNode, N, Tree, outputFilePath, goalState);
  255.         for (unsigned int i = 0; i < Tree.size(); ++i)
  256.         {
  257.             if (checkForDuplicate(Tree[i], closedList))
  258.                 continue;
  259.             if (!checkForDuplicate(Tree[i], openList))
  260.             {
  261.                 openList.push_back(Tree[i]);
  262.             }
  263.         }
  264.     }
  265. }
  266.  
  267. bool checkCorrectData(vector<vector<int>> mat)
  268. {
  269.     vector<int> freq(mat.size() * mat.size(), 0);
  270.     for (unsigned int i = 0; i < mat.size(); ++i)
  271.     {
  272.         for (unsigned int j = 0; j < mat.size(); ++j)
  273.         {
  274.             freq[mat[i][j]]++;
  275.         }
  276.     }
  277.     for (unsigned int i = 0; i < mat.size() * mat.size(); ++i)
  278.     {
  279.         if (freq[i] != 1)
  280.             return true;
  281.     }
  282.     return false;
  283. }
  284.  
  285. Node readData(string filePath, int& N, vector<vector<int>>& goalState)
  286. {
  287.     vector<vector<int>> givenState;
  288.     cout << "Care este calea fisierului de intrare: ";
  289.     cin >> filePath;
  290.     ifstream fin;
  291.     fin.open(filePath, ios::in);
  292.     if (!fin)
  293.     {
  294.         cerr << "Eroare la deschiderea fisierului " << filePath;
  295.         exit(EXIT_FAILURE);
  296.     }
  297.     fin >> N;
  298.     if (N <= 1)
  299.     {
  300.         cerr << "Dimensiunea puzzle-ului trebuie sa fie minim 2!";
  301.         exit(EXIT_FAILURE);
  302.     }
  303.     vector<vector<int>> X(N, vector<int>(N));
  304.     goalState.resize(N, vector<int>(N));
  305.     for (int i = 0; i < N; ++i)
  306.     {
  307.         for (int j = 0; j < N; ++j)
  308.         {
  309.             fin >> X[i][j];
  310.             if (X[i][j] < 0 || X[i][j] >= (N * N))
  311.             {
  312.                 cerr << "Elementele introduse au fost invalide. Introduceti doar valori intre 0 si " << N * N - 1;
  313.                 exit(EXIT_FAILURE);
  314.             }
  315.             goalState[i][j] = (N * i + j + 1) % (N * N);
  316.         }
  317.     }
  318.     if (checkCorrectData(X))
  319.     {
  320.         cerr << "Elementele introduse au fost invalide. Introduceti doar valori intre 0 si " << N * N - 1;
  321.         exit(EXIT_FAILURE);
  322.     }
  323.     Node input(X, "None", 0, 0, N, nullptr);
  324.     int H = getManhattanDistance(input.curState, goalState, N);
  325.     input.H = H;
  326.     fin.close();
  327.     return input;
  328. }
  329.  
  330.  
  331. int main()
  332. {
  333.     int N;
  334.     string inputFilePath, outputFilePath;
  335.     vector<vector<int>> goalState;
  336.     Node input = readData(inputFilePath, N, goalState);
  337.     cout << "Care este calea fisierului de iesire: "; cin >> outputFilePath;
  338.     if (isSolvable(input.curState, N))
  339.     {
  340.         aStar(input, goalState, N, outputFilePath);
  341.         return 0;
  342.     }
  343.     else
  344.     {
  345.         cerr << "Puzzle-ul introdus nu este rezolvabil!";
  346.         exit(EXIT_FAILURE);
  347.     }
  348. }
  349.  
  350.  
Add Comment
Please, Sign In to add comment