I am using Lee's algorithm to find the shortest path inside a maze.
The maze consists of 0s and 1s. A cell with value 1 represents an empty space one can go to, a cell with value 0 is an obstacle one cannot pass.
However, by doing the q.pop() part inside the while(!q.isEmpty()) loop, I am loosing my "nodes"(I have implemented a strucutre pozitie_plan that stores the index of the row, the index of the column and the distance between an arbitrary-chosen point in a matrix and itself). These "nodes" could be part of the path that I want to output in the end. Yet, I think I should not be altering that part.
I am restricted to use the Queue on DLLA (Dynamic Linked List on Array). I have implemented my own. If needed, I will add its implementation, too.
The way I am finding the path is by determining the shortest length using Lee's algorithm and leaving a trace on an auxiliary matrix, the value in an (i, j) cell representing the distance from the source to that cell.
Finally, I am tracing back a path(there could be more than one, I believe) starting from the exit of the maze (provided the exit has been found) to the starting position, by searching for those cells that have the value equal to: the value in the current cell - 1.
I am keeping these pozitie_plan nodes in a queue, then reverting the queue in the end and outputing the final result.
I feel this could be done better. But how ?
Here is my code. If asked for, I could edit the post and change the code I posted to a version that has some couts and more commentaries and / or the implementation for the Queue.
main.cpp
#include <iostream>
#include <vector>
#include "Queue.h"
#include "ShortTest.h"
#include "ExtendedTest.h"
#define Nmax 25
using std::cin;
using std::cout;
using std::vector;
using std::swap;
#include <fstream>
using std::ifstream;
using std::ofstream;
template<typename T>
void citeste_mat(ifstream &input_stream, T mat[][Nmax], int &n, int &m)
{
input_stream >> n >> m;
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
input_stream >> mat[i][j];
}
void citeste_poz_start(ifstream &input_stream, pozitie_plan &p)
{
input_stream >> p.i >> p.j;
p.dist = 0;
p.i--; p.j--; // utilizatorul vede in indexare de la 1, dar eu am implementat in indexare de la 0!
}
template<typename V>
void citeste_date(ifstream &input_file, V mat[][Nmax], int &n, int &m, pozitie_plan &p)
{
citeste_mat<V>(input_file, mat, n, m);
citeste_poz_start(input_file, p);
}
template<typename U> // ar fi fost problema daca puneam aici tot "T" in loc de "U" ?
void afis_mat(U mat[][Nmax], int n, int m)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
cout << mat[i][j] << " ";
cout << '\n';
}
cout << '\n';
}
bool valid_pozitie( int i, int j, int n, int m)
{
return 0 <= i && i < n && 0 <= j && j < m;
}
template<typename T>
bool obstacol(T mat[][Nmax], pozitie_plan p)
{
return mat[p.i][p.j] == 0;
}
template<typename T>
bool valid_nevizitat(T aux[][Nmax], pozitie_plan p)
{
return aux[p.i][p.j] == false;
}
template<typename T, typename U>
bool valid(T mat[][Nmax], U aux[][Nmax], pozitie_plan p, int n, int m)
{
return valid_pozitie(p.i, p.j, n, m) && !obstacol<T>(mat, p) && valid_nevizitat<U>(aux, p);
}
// e un pic "overhead" sa am toate functiile astea de valid, stiu; dar parca imi place sa am totul cat se poate de fragmentat
bool pe_contur(pozitie_plan p, int n, int m)
{
// return p.i == 0 || p.j == 0 || p.i == n - 1 || p.j == m - 1;
return p.i * p.j == 0 || p.i == n-1 || p.j == m-1;
}
template<typename T>
bool solution(T mat[][Nmax], pozitie_plan p , int n, int m)
{
return !obstacol(mat, p) && pe_contur(p, n, m);
}
template<typename T>
pozitie_plan gaseste_cale(T mat[][Nmax], int n, int m, pozitie_plan ps)
{
// voi pastra integritatea matricii ( mat nu va fi modificata )
const int dx[] = { -1, 0, 1, 0 };
const int dy[] = { 0, 1, 0, -1};
bool visited[Nmax][Nmax] = { false };
visited[ps.i][ps.j] = true; // marchez pozitia de start ca vizitata
Queue q;
q.push(ps); // bag in coada pozitia de start
pozitie_plan current_pos;
int row, column, distance;
while (!q.isEmpty())
// cat timp exista in coada pozitii pentru care trebuie verificati vecinii (daca vecinii sunt iesire sau nu)
{
current_pos = q.top();
if (solution<int>(mat, current_pos, n, m))
{
return current_pos; // voi returna prima solutie gasita, care garantat va fi cea mai scurta (BFS)
}
q.pop(); // stocand head ul in `current_pos` pot spune ca am tratat ce aveam in head, asa cu fac pop
for (int k = 0; k < 4; k++)
{
row = current_pos.i + dx[k];
column = current_pos.j + dy[k];
distance = current_pos.dist + 1;
pozitie_plan vecin{ row, column, distance };
if (valid<int,bool>(mat, visited, vecin, n, m))
{
mat[row][column] = distance;
visited[row][column] = true;
q.push(vecin);
}
}
}
return NULL_POZITIE_PLAN;
}
void reconstruct_path(int mat[][Nmax], int n, int m, pozitie_plan end, pozitie_plan begin, Queue& q)
{
const int dx[] = { -1, 0, 1, 0 };
const int dy[] = { 0, 1, 0, -1 };
q.push(end);
pozitie_plan current_pos = end;
int row, column, distance;
int len = current_pos.dist;
while(len != 1)
{
for (int k = 0; k < 4; k++)
{
row = current_pos.i + dx[k];
column = current_pos.j + dy[k];
distance = mat[row][column];
if (valid_pozitie(row, column, n, m)
&& distance == len - 1)
{
pozitie_plan new_pos = pozitie_plan{ row, column, distance };
q.push(new_pos);
current_pos = new_pos;
break;
}
}
len--;
}
q.push(begin);
}
void reverse_queue(Queue& q, const int len)
{
pozitie_plan *aux = new pozitie_plan[len];
for (int i = 0; i < len; i++)
aux[i] = q.pop();
for (int i = 0; i < len / 2; i++)
swap(aux[i], aux[len - 1 - i]);
for (int i = 0; i <len ; i++)
q.push(aux[i]);
}
int main()
{
int mat[Nmax][Nmax] = { 0 };
int n, m;
pozitie_plan pozitie_start;
ifstream input_file;
input_file.open("input.txt", ios::in);
citeste_date<int>(input_file, mat, n, m, pozitie_start);
input_file.close();
afis_mat<int>(mat, n, m);
// pana aici citesc datele de intrare
pozitie_plan end = gaseste_cale<int>(mat, n, m, pozitie_start); // presupun ca utilizatorul numara liniile & coloanele de la 1
if (end == NULL_POZITIE_PLAN)
{
cout << "NO SOLUTION FOUND!\n";
}
else
{
// Queue cale = reconstruct_path(mat, n, m, end);
Queue cale;
reconstruct_path(mat, n, m, end, pozitie_start, cale);
reverse_queue(cale, end.dist + 1);
cout << "The shortest path (length = " << end.dist << " not including the starting position) to be followed in the given matrix (above) is:\n";
cale.toString();
}
return 0;
}
Example
input.txt
18 20
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 1
0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
17 3
console output
The shortest path...// everything is ok, the path is ok
I am trying to implement a binary image matching algorithm. And I need to generate the C matrix given below.
Given a small pattern image A, I need to match it to large image row-by-row and column-by-column, to find the location where that pattern matches the most.
Given M x M sized pattern A:
0 0 1
0 1 1
1 1 1
and N x N sized input image B:
0 0 0 0 0 1 0 0
0 0 0 0 1 1 0 0
0 0 0 1 1 1 0 0
0 0 0 0 0 0 0 0
1 1 1 0 0 0 1 0
0 0 0 0 0 0 1 0
0 0 0 1 1 1 1 0
0 0 0 0 0 0 0 0
the N x N sized output image C is the similarity of A with B at each row and column of B. Therefore C:
0 0 0 0 0 0 0 0
0 3 4 6 9 4 2 0
0 3 4 6 4 1 1 0
0 6 6 4 2 2 3 0
0 4 3 2 3 5 5 0
0 2 2 4 6 8 5 0
0 3 4 5 4 5 2 0
0 0 0 0 0 0 0 0
I am at stuck at the point where I need to compare the matrix A with B. I have made them as 2D arrays.
This is what I have done so far
for (int i = 0; i <3 ; i++)
{
for (int j = 0; j<3; j++)
{
for (int k = 0; k < 8; i++)
{
for (int s = 0; s < 8; j++)
{
if (A[i][j] == B[k][s])
{
count++;
}
}
}
}
whats your code or algorithm? You've 9 in the matrix, so
0 0 1
0 1 1
1 1 1
matches exactly. There's the coordinate pair you must be searching for.
typedef int** matrix;
struct position
{
int x;
int y;
position(int _x,int _y){ x = _x ; y= _y; }
}
// M <= N
//checks all MxM submatrices in NxN matrix B
//and compares them with NxN matrix A
position f(matrix A, int M , matrix B , int N)
{
int best_match_first_row = -1;
int best_match_first_column = -1;
int best_match_counted = -1;
for(int i=0; i <= N-M ; ++i)// iterate through the first elements of every
for(int j=0; j <= N-M ; ++j)// MxM submatrix
{
int match_count = 0;
for(int k=0 ; k < M ; ++k)//iterate through the submatrix
for(int l=0 ; l < M ; ++l)//and compare elements with matrix A
if( A[k][l] == B[i+k][j+l] ) ++match_count; //count if it matches
if(match_count > best_match_counted) //if we have a better match than before
{
best_match_counted = match_count; //store the new count as best.
best_match_first_row = i; //store the position of the
best_match_first_column = j; //first element in the submatrix
}
}
//returns the position of the first element of the most matching submatrix
return position( best_match_first_row , best_match_first_column )
}
Does int myarray[7][7] not create a box with 8x8 locations of 0-7 rows and columns in C++?
When I run:
int board[7][7] = {0};
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
cout << board[i][j] << " ";
}
cout << endl;
}
I get output:
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 146858616 1 0 0 146858832 1 1978920048
So the 8 columns seem to work, but not the 8 rows.
If I change it to int board[8][7] = {0}; it works on mac CodeRunner IDE, but on linux Codeblocks I get:
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 1503452472
Not sure what's going on here.
Two dimensional arrays are not different to the one dimensional ones in this regard: Just as
int a[7];
can be indexed from 0 to 6,
int a2[7][7];
can be indexed from 0 to 6 in both dimensions, index 7 is out of bounds. In particular: a2 has 7 columns and rows, not 8.
int board[7][7]; will only allocate 7x7, not 8x8. When it's allocated, you specify how many, but indexes start at 0 and run to the size - 1.
So based on your source, I would say you really want int board[8][8].
int board[7][7] = {0}; creates a 7x7 array. You are going out of bounds in your loop. Change it to int board[8][8] = {0};
int board[8][7] = {0};
When you do as above, you created only 8 rows and 7 columns.
So your loop condition should be as follows:
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 7; j++)
{
If you try as follows system will print garbage values from 8th columns
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
Araay starts from zero means that it will have n-1 elements not n+1 elements
try
int a[8][8] = {}
i = 0
j = 0
for(i=0;i<8;i++)
{
for(j=0;j<8;j++)
{
a[i][j] = 0;
}
}
I have made a 'Map' array and I am attempting to populate it from a 'map' file. On creation I assign the value '0' to each element of the array but the 'Map' file contains the following:
MAP:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
I load the map using 'loadMap()'
loadMap():
void room::loadMap()
{
int x=0;
int y=0;
string line;
ifstream mapFile(NAME + "_MAP.txt");
while(!mapFile.eof())
{
for(int i=0; i<cellsY; i++)
{
getline(mapFile,line,'\n');
for(int j=0; j<cellsX; j++)
{
getline(mapFile,line,' ');
map[(cellsX*j) + cellsY] = atoi(line.c_str());
};
};
}
y = 10;
x = 15;
for(int i=0; i<y; i++)
{
cout << endl;
for(int j=0; j<x; j++)
{
cout << map[(x*j) + y];
};
};
}
In this example the elements are still assigned to '0', but I am trying to mimic the Map files layout.
For starters, you never test that any of the input works, nor
that the open succeeded. Then, in the outer loop, you read
a line from the file, and throw it away, before reading further
in the inner loop. And your calcule of the index is wrong.
What you're probably looking for is something like:
std::ifstream mapFile(...);
if ( !mapFile.is_open() ) {
// Error handling...
}
for ( int i = 0; mapFile && i != cellsY; ++ i ) {
std::string line;
if ( std::getline( mapFile, line ) ) {
std::istringstream text( line );
for ( int j = 0; j != cellsX && text >> map[cells X * i + j]; ++ j ) {
}
if ( j != cellsX ) {
// Error: missing elements in line
}
text >> std::ws;
if ( text && text.get() != EOF ) {
// Error: garbage at end of line
}
}
}
For the error handling, the simplest is just to output an
appropriate error message and continue, noting the error so you
can return some sort of error code at the end.
I think this is what you are looking for.
void room::loadMap()
{
int x=0;
int y=0;
ifstream mapFile(NAME + "_MAP.txt");
for(int i=0; i<cellsY; i++)
{
for(int j=0; j<cellsX; j++)
{
int v;
mapFile >> v;
if ( mapFile.eof() )
{
break;
}
map[(cellsX*j) + cellsY] = v;
}
}
y = 10;
x = 15;
for(int i=0; i<y; i++)
{
cout << endl;
for(int j=0; j<x; j++)
{
cout << map[(x*j) + y];
};
};
}
I should open with the fact that I am very new to c++.
I am attempting to display a constantly updating 20x20 matrix of chars. Currently, I am displaying the the matrix using for loops as cout's (code below) but that is incredibly flickery- I'm looking for something smoother.
Is there a way to convert this char matrix into an image and display that?
This is my first question here, so I apologize if I did something wrong!
Code so far:
#include <iostream>
#include <cstdlib>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
using namespace std;
int main()
{
int randInt;
//Initialize matrix and location
int matrix[20][20];
int location[2] = {0,0};
for (int i=0; i<20; i++)
{
for (int j=0; j<20; j++)
{
matrix[i][j] = 1;
}
}
//move the X around
for (int i=0; i<100; i++)
{
cout << string(50, '\n');
//Change the X's location
randInt = rand() % 4;
switch (randInt)
{
case 0:
if(location[1] > 0)
location[1] = location[1]-1;
break;
case 1:
if(location[0] < 20)
location[0] = location[0]+1;
break;
case 2:
if(location[1] < 20)
location[1] = location[1]+1;
break;
case 3:
if(location[0] > 0)
location[0] = location[0]-1;
break;
default:
cout << "Switch statement problem";
}
//Display the matrix
for (int x=0; x<20; x++)
{
for (int y=0; y<20; y++)
{
if(x==location[0] && y==location[1])
cout << "X";
else
cout << matrix[x][y];
}
cout << endl;
}
Sleep(100);
}
system ("pause");
return 0;
}
You should rename the location[2] to something like `struct { int x,y; } location for readability.
Then you can build an array of characters in RAM and put out it at once.
int _tmain(int argc, _TCHAR* argv[])
{
char matrix[20][20];
char image[21][21];
struct { int x, y; } location;
int x = 0;
int y = 0;
location.x = 7;
location.y = 3;
// fill the matrix
for (x = 0; x < 20; ++x)
{
for (y = 0; y < 20; ++y)
{
matrix[y][x] = 'a' + x + y;
}
}
// prepare the image
y = 0;
while (y < 20)
{
memcpy(image[y], matrix[y], 20);
image[y][20] = '\n';
++y;
}
// add the cross
image[location.y][location.x] = 'X';
image[20][0] = '\0';
// use the image
puts((char*)image);
}
Please add you random functionality as needed.
If you want to convert the char to a image and see the color means, write the char value as pixel in simple pgm format.
Write a file in this sample format
P2
# feep.pgm
24 7
15
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 3 3 3 3 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 15 15 15 0
0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 15 0
0 3 3 3 0 0 0 7 7 7 0 0 0 11 11 11 0 0 0 15 15 15 15 0
0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 0 0
0 3 0 0 0 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
check this link http://netpbm.sourceforge.net/doc/pgm.html for pgm format