How to solve 8-puzzle problem using Breadth-First search in C++ - c++

I want to build a c++ program that would solve 8-puzzle problem using BFS.
I want to show every generated state.
But the problem is, I don't know how to generate state.
I just want some clean function which will efficiently generate states and there will be a Explored array which will assure that there is no redundant state.
I've explored GitHub but there is too much complex solutions
I've written the following code till now
#include<iostream>
#include<conio.h>
using namespace std;
class puzzle{
private:
int initial[3][3],goal[3][3] = {{1,2,3},{4,5,6},{7,8,0}};
int queue[1000];
string data;
public:
void genratePuzzle();
void showState();
bool check_goal(int initial);
};
void puzzle::genratePuzzle(){
cout<<"\n***Create initial state 0-8***\n";
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
cout<<"Insert at ["<<i<<"]["<<j<<"] : ";
cin>>initial[i][j];
}
}
}
void puzzle::showState(){
cout<<"\n***State***\n";
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
cout<<initial[i][j]<<" ";
}
cout<<endl;
}
}
bool puzzle::check_goal(int initial){
bool check = true;
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
if(initial[i][j] != goal[i][j]){
check = false;
}
}
}
return check;
}
int main(){
puzzle p1;
p1.genratePuzzle();
p1.showState();
getch();
}
Goal state
1 2 3
4 5 6
7 8 0

Put your state into
struct state {
int data[3][3];
bool operator < (const state & other) {
for (int y=0; y<3; ++y) {
for (int x=0; x<3; ++x) {
if (data[y][x] < other.data[y][x]) {
return true;
}
if (data[y][x] > other.data[y][x]) {
return false;
}
}
}
return false; // all were equal
}
}
Now you can use values of type state as keys in a std::map e.g. make a std::map<state, bool> explored if you want. It behaves like an array indexed by states, so:
state a;
// do something to the state...
// and you can do this
explored[a] = true;
How do you generate new states? You start with an existing state and try all valid moves on it. Repeat until done.

Related

Code Blocks gives me following error upon execution of code(even parity hamming code)

error message
This is what it shows in the build log:
Checking for existence: C:\CodeBlocks\hammingcodeven.exe
Executing: '"C:\CodeBlocks/cb_console_runner.exe" "C:\CodeBlocks\hammingcodeven.exe"' (in 'C:\CodeBlocks')
Set variable: PATH=C:\MinGW\bin;C:\MinGW;C:\Windows\System32;C:\Windows;C:\Windows\System32\wbem;C:\Windows\System32\WindowsPowerShell\v1.0;C:\Windows\System32\OpenSSH;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Users\mahek\AppData\Local\Microsoft\WindowsApps
Process terminated with status -1073741510 (0 minute(s), 54 second(s))
This is the code to find binary value of m bit code after using an even parity hamming code
#include<iostream>
#include<math.h>
using namespace std;
class data
{
int A[50],m,r,ps[6],B[6][56],final[56];
public:
void show();
void input();
void findr();
void findps();
void binary();
void findfinal();
};
void data::input()
{
cout<<"Enter length of frame:";
cin>>m;
cout<<"Enter frame:";
for(int i=1;i<=m;i++)
{
cin>>A[i];
}
findr();
}
void data::findr()
{
r=0;
for(int i=1;i<=m;i++)
{
int x=pow(2,i);
if(x>(m+i+1))
{
r=i;
break;
}
}
if(r==0)
cout<<"Error";
binary();
}
void data::binary()
{
for(int i=1;i<=m+r;i++)
{
int h=i;
for(int j=r;j>=1;j--)
{
B[i][j]=h%2;
h=h/2;
}
}
findps();
}
void data::findps()
{
for(int i=1;i<=r;i++)
ps[i]=0;
for(int i=1;i<=m+r;i++)
{
for(int j=1;j<=r;j++)
{
ps[j]=ps[j]^B[i][j];
}
}
findfinal();
}
void data::findfinal()
{
for(int i=1,j=1;i<=m+r,j<=r;i++,j*=2)
{
if(i==j)
{
final[i]=ps[j];
}
else
final[i]=A[i];
}
}
void data::show()
{
cout<<"Input:";
for(int i=1;i<=m;i++)
cout<<A[i]<<" ";
cout<<endl;
cout<<"Output:";
for(int i=1;i<=m+r;i++)
cout<<final[i]<<" ";
}
int main()
{
data obj;
obj.input();
obj.show();
}
In the first loop of the function binary(), the variable i can go as high as m + r. In your example, m is 8, so m + r is at least 9. However, i is used to index the first dimension of B, which has a sizr of six. Accessing B outside of its defined size results in reading/writing other memory on the stack, resulting in undefined behavior. To help with this, you could dynamically allocate your fields with the needed size. I also strongly recommend giving your fields meaningful names to help people understand what your code is trying to do.
Furthermore, you are indexing arrays incorrectly. In C++ and many other languages, arrays are zero indexed, meaning that the first value of an array A of size n is at A[0] and the last value is at A[n-1].

Getting wrong answer in a DP problem although implementation looks correct

I was trying to solve Reduce String on codechef which says
Give a string s of length l, and a set S of n sample string(s). We do reduce the string s using the set S by this way:
Wherever Si appears as a consecutive substring of the string s, you can delete (or not) it.
After each deletion, you will get a new string s by joining the part to the left and to the right of the deleted substring.
I wrote a recursive function as follows:-
Basically what i am doing in my code is either don't delete the character or delete it if it is part of any substring but it is giving wrong answer.
#include <bits/stdc++.h>
using namespace std;
#define mx 255
int dp[mx];
unordered_map<string,int> sol;
void init(int n)
{
for(int i=0;i<n;i++)
{
dp[i]=-1;
}
}
int solve(string str,int low,int high,vector<string> smp)
{
if(low>high)
{
return 0;
}
if(dp[low]!=-1)
{
return dp[low];
}
int ans=1+solve(str,low+1,high,smp);
for(int i=low;i<high;i++)
{
string tem=str.substr(low,i-low+1);
for(int j=0;j<smp.size();j++)
{
cout<<"low i high str"<<low<<" "<<i<<" "<<high<<" "<<smp[j]<<" "<<tem<<endl;
if(tem.compare(smp[j])==0)
{
ans=min(ans,solve(str,i+1,high,smp));
}
}
}
return dp[low]=ans;
}
signed main()
{
sol.clear();
string str;
vector<string> smp;
int n;
cin>>str;
cin>>n;
for(int i=0;i<n;i++)
{
string tem;
cin>>tem;
smp.push_back(tem);
}
int len=str.length();
init(len+1);
cout<<solve(str,0,len-1,smp)<<endl;
return 0;
}
PS:
link to the question
This question is toughest(seen so far) and most beautiful(again seen so far) question based on DP ON INTERVALS.
The initial code would definitely not work since it only considers single pass on the string and would not consider remaining string after deleting the patterns again and again.
There are 3 cases:-
Case 1 Either character is not deleted.
Case 2It is deleted as a part of contiguous substring.
Case 3It is deleted as a part of subsequence that matches any word given in the set of patterns and everything that is not part of that subsequence is deleted first as a substring(which again belongs to set of words).
The third part is the most tricky and requires enough thinking and is even tougher to implement too.
So for every substring we need to check whether this substring can be completely destroyed or not.
The function compute_full_recur() is the function that ensures that whether substring can be deleted either in Case 2 or Case 3.
The function compute_full takes care of Case 1.And finally this code will not run on codechef link since all the function are recursive with memoization but to verify the code is working i Have run it on Problem Reducto of Hackerrank which is exact similar with lower constraints.Download test cases and then run on test cases on your PC for verifying.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
#define mx 252
#define nx 40
bool full[mx][mx],vis[mx][mx],full_recur[mx][mx][nx][nx];
int ans[mx];
void init()
{
for(int i=0;i<mx;i++)
{
for(int j=0;j<mx;j++)
{
full[i][j]=false,vis[i][j]=false;
}
}
for(int i=0;i<mx;i++)
{
ans[i]=-1;
}
for(int i=0;i<mx;i++)
{
for(int j=0;j<mx;j++)
{
for(int k=0;k<nx;k++)
{
for(int l=0;l<nx;l++)
{
full_recur[i][j][k][l]=false;
}
}
}
}
}
bool compute_full_recur(string str,int low,int high,vector<string> pat,int idx,int len)
{
if(low>high&&len==pat[idx].length())
{
return true;
}
if(low>high&&len<pat[idx].length())
{
full_recur[low][high][idx][len]=false;
return false;
}
if(str[low]==pat[idx][len]&&compute_full_recur(str,low+1,high,pat,idx,len+1))
{
return full_recur[low][high][idx][len]=true;
}
for(int i=low+1;i<=high;i++)
{
if(str[low]==pat[idx][len]&&full[low+1][i]&&compute_full_recur(str,i+1,high,pat,idx,len+1))
{
return full_recur[low][high][idx][len]=true;
}
}
full_recur[low][high][idx][len]=false;
return false;
}
void compute_full(string str,int low,int high,vector<string> pats)
{
if(low>high)
{
return;
}
if(vis[low][high])
{
return;
}
vis[low][high]=true;
compute_full(str,low+1,high,pats);
compute_full(str,low,high-1,pats);
for(int i=0;i<pats.size();i++)
{
if(!full[low][high])
full[low][high]=compute_full_recur(str,low,high,pats,i,0);
}
}
int compute_ans(string str,int low,int high)
{
if(low>high)
{
return 0;
}
if(ans[low]!=-1)
{
return ans[low];
}
int sol=1+compute_ans(str,low+1,high);
for(int i=low+1;i<=high;i++)
{
if(full[low][i]==true)
{
sol=min(sol,compute_ans(str,i+1,high));
}
}
return ans[low]=sol;
}
signed main()
{
int t;
cin>>t;
while(t--)
{
string str;
int n;
vector<string> pats;
cin>>n>>str;
for(int i=0;i<n;i++)
{
string tem;
cin>>tem;
pats.push_back(tem);
}
init();
compute_full(str,0,str.length()-1,pats);
cout<<compute_ans(str,0,str.length()-1)<<endl;
}
return 0;
}

I'am trying to implement BFS and count all the visited node through the edges. But my code giving me 0 count except the 1st one

In this code I just want to visit the node and count the edges. For the 1st time it seems good but when I pass new nodes and edges it is giving 0 count. I find out that it's condition is not true for the next nodes and edges. It's my first implementation of BFS.
#include<bits/stdc++.h>
using namespace std;
vector<int>v[1000];
int level[1000];
bool vis[1000];
void bfs(int s,int E)
{
int count=0;
queue<int>q;
q.push(s);
level[s]=0;
vis[s]=true;
while(!q.empty())
{
int p=q.front();
q.pop();
for(int i=0;i<v[p].size();i++)
{
if(vis[v[p][i]] == false)
{
level[v[p][i]] = level[p]+1;
q.push(v[p][i]);
vis[v[p][i]] = true;
count++;
}
}
}
cout<<count<<endl;
}
int main()
{
int N,E,x,y,size;
while(scanf("%d %d",&N,&E)==2)
{
for(int i=1;i<=E;i++)
{
scanf("%d %d",&x,&y);
v[x].push_back(y);
v[y].push_back(x);
}
int s=0;
bfs(s);
}
return 0;
}
You are not resetting whatever variables you have used like your adjacency list v,level and vis.
You have to reset them to some default value before working on a different graph, as values of previous graphs are unwanted.
You can simply run a loop, before each input:
for(int i=0;i<N;i++)
{
v[i].clear();
vis[i]=0;
level[i]=-1;
}

How to swap elements in 2d array c++

I'm trying to make a 15 puzzle game by swapping an element with the position of a blank element. I've made this code, but it only swaps when the tile is to the right or below for some reason.
void moveTile(int gameBoard[][SIZE], int nextMove, int &blanki, int &blankj)
{
int temp=nextMove;
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
if(gameBoard[i][j]==nextMove)
{
gameBoard[i][j]=gameBoard[blanki][blankj];
gameBoard[blanki][blankj]=temp;
blanki=i;
blankj=j;
}
}
}
}
Walk thru it in a debugger. You'll see that after a swap is made, you keep going and searching. In the case where the tile is above or left, you'll swap a second time.
You need to stop searching once you've made a swap.
I have updated it to include a stop, now the code does not iterate.
void moveTile(int gameBoard[][SIZE], int nextMove, int &blanki, int &blankj)
{ bool stop=false;
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
while(!stop)
{if(gameBoard[i][j]==nextMove)
{
int temp=gameBoard[i][j];
gameBoard[i][j]=gameBoard[blanki][blankj];
gameBoard[blanki][blankj]=temp;
blanki=i;
blankj=j;
stop=true;
}
}
}
}
}

Different output when set different breakpoints

I just wrote a code to build a Huffman Tree using MinHeap. When testing I want to output its traversal result.
The algorithm is simple, but my code can't get the right answer. It's strange that the output was different when I set different breakpoints. For instance, it depends on if I set a break point in the loop, such as line 165 input_list.insert(*parent);.
The test input was
4 //number of nodes.
1 1 3 5 //weight of each node.
and the output when debugging it with a breakpoint in the loop is
5
10
1
2
1
5
3
that is correct. But when I just run it without debug, it even didn't have any output. Does anyone know how to explain it?
#include <iostream>
#include <vector>
using namespace std;
#define max_size 100
int sum=0;
class huffman_node
{
public:
int weight;
huffman_node* left_child;
huffman_node* right_child;
huffman_node(){}
huffman_node(int w, huffman_node* l, huffman_node* r):
weight(w),left_child(l),right_child(r) {}
};
vector <huffman_node> node_list;
class minheap
{
public:
minheap()
{
heap=new huffman_node [max_size];
current_size=0;
}
~minheap()
{
delete []heap;
}
void siftdown(int start, int m)
{
int i=start;
int j=2*i+1;
huffman_node temp=heap[i];
while(j<=m)
{
if(j<m && heap[j+1].weight<heap[j].weight)
{
++j;
}
if(temp.weight<=heap[j].weight)
{
break;
}
else
{
heap[i]=heap[j];
i=j;
j=2*i+1;
}
}
heap[i]=temp;
}
void siftup(int start)
{
int j=start;
int i=(j-1)/2;
huffman_node temp=heap[j];
while(j>0)
{
if(heap[i].weight<=temp.weight)
{
break;
}
else
{
heap[j]=heap[i];
j=i;
i=(j-1)/2;
}
heap[j]=temp;
}
}
bool insert(const huffman_node& input)
{
if(current_size==max_size)
{
cout<<"minheap full"<<endl;
return false;
}
heap[current_size]=input;
siftup(current_size);
++current_size;
return true;
}
bool remove_min(huffman_node& output)
{
if(!current_size)
{
cout<<"minheap empty"<<endl;
return false;
}
output=heap[0];
heap[0]=heap[current_size-1];
--current_size;
siftdown(0,current_size-1);
return true;
}
private:
huffman_node* heap;
int current_size;
};
void route_length(huffman_node* &root,int depth)
{
if(root!=NULL)
{
// if(root->left_child==NULL&&root->right_child==NULL)
// {
// sum+=depth*root->weight;
// }
route_length(root->left_child,depth+1);
cout<<root->weight<<endl;
route_length(root->right_child,depth+1);
}
else
{
return;
}
}
int main()
{
minheap input_list;
int n;
cin>>n;
for(int i=0;i<n;++i)
{
int key;
cin>>key;
huffman_node input(key,NULL,NULL);
input_list.insert(input);
cin.get();
}
huffman_node* root;
for(int i=0;i<n-1;++i)
{
huffman_node* parent;
huffman_node out1;
huffman_node out2;
input_list.remove_min(out1);
input_list.remove_min(out2);
node_list.push_back(out1);
node_list.push_back(out2);
parent=new huffman_node(out1.weight+out2.weight,&node_list[node_list.size()-2],&node_list[node_list.size()-1]);
input_list.insert(*parent);
root=parent;
}
route_length(root,0);
// cout<<sum<<endl;
return 0;
}
The problem is that you are using pointers to elements of a vector<huffman_node> and storing these in your data structure (i.e. left and right members of the huffman_node object).
The thing that is randomly killing your program is that std::vector moves values around in memory when you append to it. The contents of the elements of the vectors are preserved, but the location is not. Once it moves the elements, the memory where the vector used to be can be overwritten by whatever (i.e. gdb needs heap memory too) and now the pointers are pointing to garbage.
As a quick sanity check, you can make your code not crash by reserving space in your node_list by calling
node_list.reserve(max_size*2);
in the beginning of main. This is not the right way of developing this piece of code further, but should illustrate the problem.
It would be better if your node_list was a vector<huffman_node*> instead. Or if you changed the left/right members to be vector indices instead of pointers.