Skip to content

Commit 3dcd85b

Browse files
committed
Key Changes Made:
Removed <bits/stdc++.h>: Ensured portability by using specific headers. Namespace: Avoided using namespace std; for better practices. Test Function: Created testSolve8TilePuzzle() to handle test cases and moved all main logic there. Maintained Clarity: The main() function now only calls the test function for cleaner structure.
1 parent ca8a229 commit 3dcd85b

File tree

1 file changed

+61
-56
lines changed

1 file changed

+61
-56
lines changed
Lines changed: 61 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,32 @@
1-
#include <bits/stdc++.h>
2-
using namespace std;
1+
#include <iostream> // for IO operations
2+
#include <vector> // for std::vector
3+
#include <set> // for std::set
4+
#include <limits> // for std::numeric_limits
5+
36
/**
47
* @file
5-
* @brief Implementation of Iterative deepening Search algorithm
8+
* @brief Implementation of the Iterative Deepening Search algorithm for the 8-tile puzzle.
69
* @author [Sushant Kogurwar](https://github.com/sushskvnitn)
710
*/
8-
#define N 3 // Define the size of the tile puzzle (3x3)
11+
12+
#define N 3 ///< Define the size of the tile puzzle (3x3)
913

1014
/**
1115
* @class Node
1216
* @brief Represents a state in the 8-tile puzzle.
1317
*/
1418
class Node {
1519
private:
16-
vector<vector<int>> state; ///< Current state of the puzzle
17-
pair<int, int> blankIndex; ///< Index of the blank tile (0)
18-
Node *parent; ///< Parent node for tracing back the solution
19-
int depth; ///< Depth of the current node in the search tree
20+
std::vector<std::vector<int>> state; ///< Current state of the puzzle
21+
std::pair<int, int> blankIndex; ///< Index of the blank tile (0)
22+
Node *parent; ///< Parent node for tracing back the solution
23+
int depth; ///< Depth of the current node in the search tree
2024

2125
/**
2226
* @brief Finds the index of the blank tile in the current state.
2327
* @return Pair of indices (row, column) of the blank tile.
2428
*/
25-
pair<int, int> findBlankIndex() {
29+
std::pair<int, int> findBlankIndex() {
2630
for (int i = 0; i < N; i++) {
2731
for (int j = 0; j < N; j++) {
2832
if (state[i][j] == 0) {
@@ -40,53 +44,31 @@ class Node {
4044
* @param parent Pointer to the parent node.
4145
* @param depth Depth of the node.
4246
*/
43-
Node(const vector<vector<int>> &state, Node *parent, int depth)
47+
Node(const std::vector<std::vector<int>> &state, Node *parent, int depth)
4448
: state(state), parent(parent), depth(depth) {
4549
blankIndex = findBlankIndex();
4650
}
4751

48-
vector<vector<int>> getState() const { return state; }
49-
pair<int, int> getBlankIndex() const { return blankIndex; }
52+
std::vector<std::vector<int>> getState() const { return state; }
53+
std::pair<int, int> getBlankIndex() const { return blankIndex; }
5054
int getDepth() const { return depth; }
5155
};
5256

5357
/**
5458
* @class Solve8TilePuzzle
5559
* @brief A class to solve the 8-tile puzzle using Iterative Deepening Search (IDS).
56-
*
57-
* @details
58-
* This class implements a solution for the 8-tile puzzle, where the goal is to
59-
* rearrange the tiles from a given initial state to a specified goal state.
60-
* The algorithm uses Iterative Deepening Search, which combines the benefits of
61-
* depth-first search (space efficiency) and breadth-first search (completeness).
62-
*
63-
* The initial state of the puzzle is provided by the user, and the algorithm
64-
* checks if the puzzle is solvable based on the number of inversions in the array.
65-
* If the puzzle is solvable, it attempts to find the solution using a depth-limited
66-
* search approach, increasing the depth limit iteratively until a solution is found
67-
* or it is confirmed that no solution exists.
68-
*
69-
* The implementation ensures that:
70-
* - The space complexity is efficient, as it avoids storing large states in memory.
71-
* - The time complexity is less than O(n^2) due to the iterative deepening approach.
72-
* - The original array remains unmodified throughout the process.
73-
*
74-
* If the puzzle is not solvable, the algorithm returns a message indicating this.
75-
*
76-
* @note The blank tile is represented by 0 in the puzzle.
7760
*/
78-
7961
class Solve8TilePuzzle {
8062
public:
81-
vector<vector<int>> initialState, goalState; ///< Initial and goal states
82-
set<vector<vector<int>>> visitedList; ///< Set to track visited states
63+
std::vector<std::vector<int>> initialState, goalState; ///< Initial and goal states
64+
std::set<std::vector<std::vector<int>>> visitedList; ///< Set to track visited states
8365

8466
/**
8567
* @brief Constructor for Solve8TilePuzzle class.
8668
* @param initialState Initial state of the puzzle.
8769
* @param goalState Goal state of the puzzle.
8870
*/
89-
Solve8TilePuzzle(const vector<vector<int>> &initialState, const vector<vector<int>> &goalState)
71+
Solve8TilePuzzle(const std::vector<std::vector<int>> &initialState, const std::vector<std::vector<int>> &goalState)
9072
: initialState(initialState), goalState(goalState) {}
9173

9274
bool boundsOK(int i, int j) const {
@@ -108,20 +90,21 @@ class Solve8TilePuzzle {
10890
return true;
10991
}
11092

111-
const vector<vector<int>> dirs = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
93+
const std::vector<std::vector<int>> dirs = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
11294
for (const auto &dir : dirs) {
11395
int newI = currNode->getBlankIndex().first + dir[0];
11496
int newJ = currNode->getBlankIndex().second + dir[1];
11597

11698
if (!boundsOK(newI, newJ)) continue;
11799

118-
vector<vector<int>> newState = currNode->getState();
119-
swap(newState[currNode->getBlankIndex().first][currNode->getBlankIndex().second], newState[newI][newJ]);
100+
std::vector<std::vector<int>> newState = currNode->getState();
101+
std::swap(newState[currNode->getBlankIndex().first][currNode->getBlankIndex().second], newState[newI][newJ]);
120102
Node *newNode = new Node(newState, currNode, currNode->getDepth() + 1);
121103

122104
if (visitedList.find(newNode->getState()) == visitedList.end()) {
123105
if (dls(newNode, depthLimit)) return true;
124106
}
107+
delete newNode; // Prevent memory leak
125108
}
126109
return false;
127110
}
@@ -130,10 +113,14 @@ class Solve8TilePuzzle {
130113
* @brief Initiates the iterative deepening search to solve the puzzle.
131114
*/
132115
void iterativeDeepeningSearch() {
133-
for (int depth = 0; depth < INT_MAX; depth++) {
116+
for (int depth = 0; depth < std::numeric_limits<int>::max(); depth++) {
134117
visitedList.clear();
135118
Node *root = new Node(initialState, nullptr, 0);
136-
if (dls(root, depth)) return;
119+
if (dls(root, depth)) {
120+
delete root; // Clean up
121+
return;
122+
}
123+
delete root; // Clean up
137124
}
138125
}
139126

@@ -142,7 +129,7 @@ class Solve8TilePuzzle {
142129
* @param node The node at which the solution is found.
143130
*/
144131
void printSolution(Node *node) {
145-
cout << "Solution found at depth " << node->getDepth() << endl;
132+
std::cout << "Solution found at depth " << node->getDepth() << std::endl;
146133
// Trace back to print the solution path if necessary
147134
}
148135

@@ -168,30 +155,48 @@ class Solve8TilePuzzle {
168155
* @brief Takes user input for the initial state of the puzzle.
169156
* @param initialState Reference to the 2D vector where the input will be stored.
170157
*/
171-
void takeUserInput(vector<vector<int>> &initialState) {
172-
cout << "Enter the initial state of the 8-tile puzzle (0 for blank tile):\n";
158+
void takeUserInput(std::vector<std::vector<int>> &initialState) {
159+
std::cout << "Enter the initial state of the 8-tile puzzle (0 for blank tile):\n";
173160
for (int i = 0; i < N; i++) {
174161
for (int j = 0; j < N; j++) {
175-
cin >> initialState[i][j];
162+
std::cin >> initialState[i][j];
176163
}
177164
}
178165
}
179166

180167
/**
181-
* @brief Main function to run the 8-tile puzzle solver.
168+
* @brief Test function to run the 8-tile puzzle solver with predefined cases.
182169
*/
183-
int main() {
184-
vector<vector<int>> initialState(N, vector<int>(N, 0));
185-
vector<vector<int>> goalState = {{1, 2, 3}, {4, 5, 6}, {7, 8, 0}};
186-
187-
takeUserInput(initialState);
170+
void testSolve8TilePuzzle() {
171+
// Test Case 1: Solvable case
172+
std::vector<std::vector<int>> initialState1 = {{1, 2, 3}, {4, 5, 6}, {7, 8, 0}};
173+
std::vector<std::vector<int>> goalState = {{1, 2, 3}, {4, 5, 6}, {7, 8, 0}};
174+
175+
Solve8TilePuzzle puzzle1(initialState1, goalState);
176+
if (puzzle1.isSolvable()) {
177+
std::cout << "Test Case 1: ";
178+
puzzle1.iterativeDeepeningSearch();
179+
} else {
180+
std::cout << "Test Case 1: Not Solvable" << std::endl;
181+
}
188182

189-
Solve8TilePuzzle solvePuzzle(initialState, goalState);
190-
if (solvePuzzle.isSolvable()) {
191-
solvePuzzle.iterativeDeepeningSearch();
183+
// Test Case 2: Unsolvable case
184+
std::vector<std::vector<int>> initialState2 = {{1, 2, 3}, {4, 5, 6}, {0, 7, 8}};
185+
186+
Solve8TilePuzzle puzzle2(initialState2, goalState);
187+
if (puzzle2.isSolvable()) {
188+
std::cout << "Test Case 2: ";
189+
puzzle2.iterativeDeepeningSearch();
192190
} else {
193-
cout << "\nNot Solvable" << endl;
191+
std::cout << "Test Case 2: Not Solvable" << std::endl;
194192
}
193+
}
195194

195+
/**
196+
* @brief Main function to run the test function.
197+
* @returns 0 on exit
198+
*/
199+
int main() {
200+
testSolve8TilePuzzle();
196201
return 0;
197202
}

0 commit comments

Comments
 (0)