Professional Documents
Culture Documents
Practical – 2
Analysis:
Given a 3×3 board with 8 tiles (every tile has one number from 1 to 8) and one empty space. The
objective is to place the numbers on tiles to match the final configuration using the empty space.
We can slide four adjacent (left, right, above, and below) tiles into the empty space.
Here, a pair of tiles form an inversion if the values on tiles are in reverse order of their
appearance in goal state.
i. BFS:
This approach will find the goal state after sliding the empty space maximum 4 times in
whichever direction possible.
The steps to solve the problem using BFS:
#include<bits/stdc++.h>
using namespace std;
int main(){
1
IT375 - Artificial Intelligence 20IT116
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
vector<vector<char>> initState = {
{'1', '2', '3'},
{'4', '6', ' '},
{'5', '8', '7'}
};
vector<vector<char>> goalState = {
{'1', '2', '3'},
{'5', '6', '7'},
{'4', '8', ' '}
};
queue<vector<vector<char>>> states;
states.push(initState);
set<vector<vector<char>>> visited;
while(!states.empty()){
vector<vector<char>> curr = states.front();
states.pop();
visited.insert(curr);
bool flag = true;
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
if(curr[i][j] != goalState[i][j]){
flag = false;
break;
}
}
}
if(flag) cout << "Found!\n"; break;
int x, y;
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
if(curr[i][j] == ' '){
x = i; y = j;
break;
}
}
}
if(x - 1 >= 0){
swap(curr[x - 1][y], curr[x][y]);
if(visited.find(curr) == visited.end()){
states.push(curr);
2
IT375 - Artificial Intelligence 20IT116
}
swap(curr[x - 1][y], curr[x][y]);
}
if(x + 1 < 3){
swap(curr[x + 1][y], curr[x][y]);
if(visited.find(curr) == visited.end()){
states.push(curr);
}
swap(curr[x + 1][y], curr[x][y]);
}
if(y - 1 >= 0){
swap(curr[x][y - 1], curr[x][y]);
if(visited.find(curr) == visited.end()){
states.push(curr);
}
swap(curr[x][y - 1], curr[x][y]);
}
if(y + 1 < 3){
swap(curr[x][y + 1], curr[x][y]);
if(visited.find(curr) == visited.end()){
states.push(curr);
}
swap(curr[x][y + 1], curr[x][y]);
}
}
cout << "Not Found!\n";
}
ii. DFS:
1. First find out the empty space in the given initial matrix.
2. Then try to slide that space in any of the directions
3. After a slide is performed, start exploring that state till it’s depth(Here till it’s depth
means either we have reached the goal state or an already explored state)
4. Keep exploring the states till we either reach the goal state or run out of states to explore.’
5. Like BFS, here also we need to keep track of all the states that were explored.
#include <bits/stdc++.h>
using namespace std;
3
IT375 - Artificial Intelligence 20IT116
4
IT375 - Artificial Intelligence 20IT116
5
IT375 - Artificial Intelligence 20IT116
Analysis:
You are given two jugs, one of m litre and another of n litre capacity. Both the jugs are initially
empty. The jugs do not have any intermediate markings and labelling for measuring smaller
quantities. You can be asked to measure d litres of water, such that d is less than n.
First, fill the n litre jug and empty all its contents in the “m” litre jug. As soon as the n litre jug
becomes vacant, refill it. As soon as the “m” litre jug becomes full, empty it. Repeat the first
three steps until either the n litre jug or the m litre jug, has exactly d litres of water in it.
The solution written using Breadth-First Search is considered to be one of the most optimum
solutions.
1. Define a state space that contains all possible configurations of the water jugs and
even some of the unreachable ones.
2. Specify one or multiple states within that space that describe all the possible
situations from which we can initiate the problem-solving process. These states are
referred to as the initial states.
3. Specify one or more states which are regarded as the acceptable solutions to the
problem. These states are known as goal states.
4. Specify a set of rules also known as predictions that describe the actions (operators)
allowed and a well-defined control strategy for aligning the order of application of
these predictions.
Implementation:
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
void printpath(map<pii, pii> mp, pii u)
{
6
IT375 - Artificial Intelligence 20IT116
queue<pii> q;
q.push({0, 0});
while (!q.empty()) {
auto u = q.front();
q.pop();
if(m[u] == 1)
continue;
if((u.first > a || u.second > b || u.first < 0 || u.second < 0))
continue;
m[{u.first, u.second}] = 1;
if(u.first == target || u.second == target){
isSolvable = true;
printpath(mp, u);
if(u.first == target){
if(u.second != 0)
cout << u.first << " " << 0 << endl;
}
else{
if(u.first != 0)
cout << 0 << " " << u.second << endl;
}
return;
}
if(m[{u.first, b}] != 1){
q.push({u.first, b});
mp[{u.first, b}] = u;
}
if(m[{a, u.second}] != 1){
q.push({a, u.second});
mp[{a, u.second}] = u;
7
IT375 - Artificial Intelligence 20IT116
}
int d = b - u.second;
if(u.first >= d){
int c = u.first - d;
if(m[{c, b}] != 1){
q.push({c, b});
mp[{c, b}] = u;
}
}
else{
int c = u.first + u.second;
if(m[{0, c}] != 1){
q.push({0, c});
mp[{0, c}] = u;
}
}
d = a - u.first;
if(u.second >= d){
int c = u.second - d;
if(m[{a, c}] != 1){
q.push({a, c});
mp[{a, c}] = u;
}
}
else{
int c = u.first + u.second;
if(m[{c, 0}] != 1){
q.push({c, 0});
mp[{c, 0}] = u;
}
}
if(m[{u.first, 0}] != 1){
q.push({u.first, 0});
mp[{u.first, 0}] = u;
}
if(m[{0, u.second}] != 1){
q.push({0, u.second});
mp[{0, u.second}] = u;
}
}
if(!isSolvable)
cout << "No solution";
}
8
IT375 - Artificial Intelligence 20IT116
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
int jug1, jug2, target;
cin >> jug1;
cin >> jug2;
cin >> target;
cout << "Path from initial state to solution state ::\n";
BFS(jug1, jug2, target);
return 0;
}
9
IT375 - Artificial Intelligence 20IT116
Analysis:
Given an N x N chessboard and N queens. We need to determine all the possible states of the
chessboard which has N queens and no queens are attacking each other.
Backtracking/DFS Approach:
1. Put the queens column by column, to place a queen on a cell first check if that cell is
being attacked by another queen. If not, place the queen on that cell and then explore all
the possibilities.
2. After all the possibilities with the queen on that cell is explored, remove the queen from
that cell and try putting it on another cell of the same column and then repeat the same
process.
3. After the whole traversal is over, we will have our all possible states.
Implementation:
#include<bits/stdc++.h>
using namespace std;
class Solution {
public:
bool safe(int row, int col, vector<string> board, int n){
int duprow = row;
int dupcol = col;
while(row >= 0 && col >= 0){
if(board[row][col] == 'Q') return false;
row--;
col--;
}
row = duprow;
col = dupcol;
while(col >= 0){
if(board[row][col] == 'Q') return false;
col--;
}
col = dupcol;
while(row < n && col >= 0){
if(board[row][col] == 'Q') return false;
row++;
col--;
}
10
IT375 - Artificial Intelligence 20IT116
return true;
}
void solve(int col,vector<string> board, vector<vector<string>>& ans, int n){
if(col == n){
ans.push_back(board);
return;
}
for(int row = 0; row < n; row++){
if(safe(row, col, board, n)){
board[row][col] = 'Q';
solve(col + 1, board, ans, n);
board[row][col] = '.';
}
}
}
vector<vector<string>> solveNQueens(int n) {
vector<vector<string>> ans;
vector<string> board(n);
string s(n, '.');
for(int i = 0; i < n; i++){
board[i] = s;
}
solve(0, board, ans, n);
return ans;
}
};
int main(){
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
int n;
cin >> n;
Solution obj;
vector<vector<string>> ans = obj.solveNQueens(n);
for(auto& j:ans){
for(auto i:j){
cout << i << "\n";
}
cout << "\n";
}
}
11