Last active
February 26, 2017 16:30
-
-
Save abdalimran/3e40fe043541d98bf0e00bca36149f0c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <vector> | |
#include <set> | |
#include <cstring> | |
#include <string> | |
#include <map> | |
#include <queue> | |
#include <algorithm> | |
using namespace std; | |
struct Node { | |
int puzzle[5][5]; | |
int value; | |
int state; | |
}; | |
int goalState[5][5]; | |
int randomPuzzle[5][5]; | |
int temppuzzle[5][5]; | |
int temppuzzle1D[15]; | |
map <string, string> parent; | |
map <string, int> level; | |
map <string, int > state; | |
int stateCnt = 0; | |
vector <pair <int, int>> getMove; | |
int dir[2] = {1,-1}; | |
vector <int> visited[5000010]; | |
int visitCnt = 0; | |
set <string> stVisited; | |
pair <int, int> goalStateLocation[10]; | |
int eI,eJ; | |
vector <Node> tempNodepuzzle; | |
bool compare(Node x1, Node x2) { | |
if (x1.value == x2.value) | |
return x1.state < x2.state; | |
return x1.value < x2.value; | |
} | |
bool checkGoalState() { | |
for (int i = 1; i <= 3; i++) { | |
for (int j = 1; j <= 3; j++) { | |
if (goalState[i][j] != temppuzzle[i][j]) { | |
return false; | |
} | |
} | |
} | |
return true; | |
} | |
void temppuzzleTo1D() { | |
int cnt = 0; | |
for (int i = 1; i <= 3; i++) { | |
for (int j = 1; j <= 3; j++) | |
temppuzzle1D[cnt++] = temppuzzle[i][j]; | |
} | |
} | |
void findEmp() { | |
for (int i = 1; i <= 3; i++) { | |
for (int j = 1; j <= 3; j++) { | |
if (temppuzzle[i][j] == 0) { | |
eI = i; | |
eJ = j; | |
return; | |
} | |
} | |
} | |
} | |
void genMove() { | |
getMove.clear(); | |
findEmp(); | |
int empI = eI; | |
int empJ = eJ; | |
for (int i = 0; i < 2; i++) { | |
if (temppuzzle[empI + dir[i]][empJ] != -1) | |
getMove.push_back(make_pair(empI + dir[i], empJ)); | |
} | |
for (int i = 0; i < 2; i++) { | |
if (temppuzzle[empI][empJ + dir[i]] != -1) | |
getMove.push_back(make_pair(empI, empJ + dir[i])); | |
} | |
} | |
void makeVisit() { | |
string s = ""; | |
for (int i = 1; i <= 3; i++) { | |
for (int j = 1; j <= 3; j++) { | |
char c = temppuzzle[i][j] + 48; | |
s += c; | |
} | |
} | |
stVisited.insert(s); | |
} | |
bool chkVisited() { | |
string s = ""; | |
for (int i = 1; i <= 3; i++) { | |
for (int j = 1; j <= 3; j++) { | |
char c = temppuzzle[i][j] + 48; | |
s += c; | |
} | |
} | |
if (stVisited.find(s) == stVisited.end()) | |
return false; | |
else | |
return true; | |
} | |
void makeTemppuzzle(Node xx) { | |
memset(temppuzzle, -1, sizeof(temppuzzle)); | |
for (int i = 1; i <= 3; i++) { | |
for (int j = 1; j <= 3; j++) | |
temppuzzle[i][j] = xx.puzzle[i][j]; | |
} | |
} | |
void initGoalStates() { | |
for (int i = 1; i <= 3; i++) { | |
for (int j = 1; j <= 3; j++) { | |
goalStateLocation[goalState[i][j]] = make_pair(i, j); | |
} | |
} | |
} | |
int calculateManhattanDistance(Node x) { | |
int cntTotDist = 0; | |
for (int i = 1; i <= 3; i++) { | |
for (int j = 1; j <= 3; j++) { | |
int xVal = x.puzzle[i][j]; | |
if (xVal > 0) { | |
int igoalState = goalStateLocation[xVal].first; | |
int jgoalState = goalStateLocation[xVal].second; | |
cntTotDist += abs(i - igoalState); | |
cntTotDist += abs(j - jgoalState); | |
} | |
} | |
} | |
for (int i = 1; i <= 3; i++) { | |
for (int j = 1; j <= 3; j++) { | |
int xgoalState = goalState[i][j]; | |
int nextgoalState; | |
int xVal = x.puzzle[i][j]; | |
int nextVal; | |
if (j + 1 <= 3) { | |
nextVal = x.puzzle[i][j + 1]; | |
nextgoalState = goalState[i][j + 1]; | |
if (xVal == nextgoalState && xgoalState == nextVal) | |
cntTotDist++; | |
} | |
if (i + 1 <= 3) { | |
nextVal = x.puzzle[i + 1][j]; | |
nextgoalState = goalState[i + 1][j]; | |
if (xVal == nextgoalState && xgoalState == nextVal) | |
cntTotDist++; | |
} | |
} | |
} | |
return cntTotDist; | |
} | |
string NodeToString(Node xx) { | |
string s = ""; | |
for (int i = 1; i <= 3; i++) { | |
for (int j = 1; j <= 3; j++) { | |
char c = xx.puzzle[i][j] + 48; | |
s += c; | |
} | |
} | |
return s; | |
} | |
void printPath(string SS) { | |
if (parent[SS] == SS) { | |
cout << "Step: " << level[SS] << endl; | |
for (int i = 0; i < SS.size(); i++) { | |
cout << SS[i] << " "; | |
if ((i + 1) % 3 == 0) | |
cout << endl; | |
} | |
cout << endl; | |
return; | |
} | |
printPath(parent[SS]); | |
cout << "Step: " << level[SS] << endl; | |
for (int i = 0; i < SS.size(); i++) { | |
cout << SS[i] << " "; | |
if ((i + 1) % 3 == 0) | |
cout << endl; | |
} | |
cout << endl; | |
return; | |
} | |
void Solve() { | |
int cnt = 0; | |
queue < Node > que; | |
Node xx; | |
for (int i = 1; i <= 3; i++) { | |
for (int j = 1; j <= 3; j++) { | |
xx.puzzle[i][j] = randomPuzzle[i][j]; | |
temppuzzle[i][j] = randomPuzzle[i][j]; | |
} | |
} | |
makeVisit(); | |
que.push(xx); | |
string s = NodeToString(xx); | |
parent[s] = s; | |
level[s] = 0; | |
state[s] = stateCnt++; | |
bool solved = false; | |
while (!que.empty() && !solved) { | |
Node u = que.front(); | |
makeTemppuzzle(u); | |
string sU = NodeToString(u); | |
genMove(); | |
int empUI = eI; | |
int empUJ = eJ; | |
tempNodepuzzle.clear(); | |
for (int i = 0; i < getMove.size(); i++) { | |
int empVI = getMove[i].first; | |
int empVJ = getMove[i].second; | |
makeTemppuzzle(u); | |
swap(temppuzzle[empUI][empUJ], temppuzzle[empVI][empVJ]); | |
if (!chkVisited()) { | |
Node v; | |
for (int ii = 1; ii <= 3; ii++) { | |
for (int jj = 1; jj <= 3; jj++) { | |
v.puzzle[ii][jj] = temppuzzle[ii][jj]; | |
} | |
} | |
string sV = NodeToString(v); | |
level[sV] = level[sU] + 1; | |
parent[sV] = sU; | |
state[sV] = stateCnt; | |
v.value = calculateManhattanDistance(v) + level[sV]; | |
v.state = stateCnt; | |
tempNodepuzzle.push_back(v); | |
stateCnt++; | |
} | |
} | |
sort(tempNodepuzzle.begin(), tempNodepuzzle.end(), compare); | |
for (int i = 0; i < tempNodepuzzle.size(); i++) { | |
Node v = tempNodepuzzle[i]; | |
makeTemppuzzle(v); | |
makeVisit(); | |
que.push(v); | |
string sV = NodeToString(v); | |
if (checkGoalState()) { | |
printPath(sV); | |
solved = true; | |
cout << "Solved!!" << endl; | |
break; | |
} | |
break; | |
} | |
que.pop(); | |
} | |
if (!solved) | |
cout << "It can not be solved." << endl; | |
} | |
int main() { | |
randomPuzzle[1][1] = 0; | |
randomPuzzle[1][2] = 3; | |
randomPuzzle[1][3] = 2; | |
randomPuzzle[2][1] = 1; | |
randomPuzzle[2][2] = 4; | |
randomPuzzle[2][3] = 6; | |
randomPuzzle[3][1] = 8; | |
randomPuzzle[3][2] = 7; | |
randomPuzzle[3][3] = 5; | |
goalState[1][1] = 1; | |
goalState[1][2] = 2; | |
goalState[1][3] = 3; | |
goalState[2][1] = 8; | |
goalState[2][2] = 0; | |
goalState[2][3] = 4; | |
goalState[3][1] = 7; | |
goalState[3][2] = 6; | |
goalState[3][3] = 5; | |
initGoalStates(); | |
cout << "Random puzzle:" << endl << endl; | |
for (int i = 1; i <= 3; i++) { | |
for (int j = 1; j <= 3; j++) | |
cout << randomPuzzle[i][j] << " "; | |
cout << endl; | |
} | |
cout << endl << endl; | |
cout << "Solution: " << endl << endl; | |
Solve(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment