I am working on the knight moves problem and managed to print the number of moves but still need to print the path e.g. "3 moves: path is: [3,3] [4,5] [2,4] [4,3]". I tried to print the Queue but got instead all visited paths. I tried also to work backward to the previous points (function minStepToReachTarget) but i think my novice skill did not help.
i already got the number of moves but is there a function or piece of code that help me print the path?
Best,
James.
#include <bits/stdc++.h>
#include <iostream>
#include <queue>
using namespace std;
// structure for storing a cell's data
class cell {
public:
int x, y;
int dis;
cell() {}
cell(int x, int y, int dis) : x(x), y(y), dis(dis) { }
};
// Utility method returns true if (x, y) lies
// inside Board
bool isInside(int x, int y, int N)
{
if (x >= 1 && x <= N && y >= 1 && y <= N)
return true;
return false;
}
// Method returns minimum step
// to reach target position
int minStepToReachTarget( int knightPos[], int targetPos[], int N)
{
// x and y direction, where a knight can move
int dx[] = { -2, -1, 1, 2, -2, -1, 1, 2 };
int dy[] = { -1, -2, -2, -1, 1, 2, 2, 1 };
// queue for storing states of knight in board
queue<cell> q;
// push starting position of knight with 0 distance
q.push(cell(knightPos[0], knightPos[1], 0));
cell t;
int x, y;
bool visit[N + 1][N + 1];
// make all cell unvisited
for (int i = 1; i <= N; i++)
for (int j = 1; j <= N; j++)
visit[i][j] = false;
// visit starting state
visit[knightPos[0]][knightPos[1]] = true;
// loop until we have one element in queue
while (!q.empty()) {
t = q.front();
q.pop();
// cout << "[" << t.x << " "<< t.y<<"]\n";
// if current cell is equal to target cell,
// return its distance
if (t.x == targetPos[0] && t.y == targetPos[1]) {
// cout << "[" << targetPos[0] << " " << targetPos[1] << "]\n";
return t.dis;
}
// loop for all reachable states
for (int i = 0; i < 8; i++) {
x = t.x + dx[i];
y = t.y + dy[i];
// If reachable state is not yet visited and
// inside board, push that state into queue
if (isInside(x, y, N) && !visit[x][y]) {
visit[x][y] = true;
//** cout << "[" << x << " " << y << "]\n";
q.push(cell(x, y, t.dis + 1));
}
}
}
return t.dis;
}
int main(){
int N = 8, knightPos[2], targetPos[2];
cout <<"=> Enter the current Knight’s location: ";
for (int i = 0; i < 2; i++) std::cin>> knightPos[i];
cout <<"=> Enter the destination location: ";
for (int i = 0; i < 2; i++) std::cin>> targetPos[i];
cout <<"=> You made it in " << minStepToReachTarget(knightPos, targetPos, N) <<
" moves from [" << knightPos[0] <<"," << knightPos[1] << "] "
"to [" << targetPos[0] <<"," << targetPos[1] <<"]! Here is your path: ";
return 0;
/*
=> Enter the current Knight’s location: 3 3
=> Enter the destination location: 4 3
=> You made it in 3 moves from [3,3] to [4,3]! Here is your path:
[3,3] [4,5] [2,4] [4,3]
*/
}
You're doing a breadth-first search on your board. Once your reach your destination, the function minStepToReachTarget has no idea how it got there. What you can do is, for each cell in the queue, keep track of its 'parent', i.e. from which cell it was visited first. Once you've found the target, instead of returning t.dis, you could trace the parents of t and return an array representing the path. t.dis would then be equal to the length of the array minus one, since you include both the starting point and target point in the path.
Related
I have a class that I'm trying to use, but in main function ёstartё doesn't execute with following error expression preceeding of apparent call must have pointer-to func type
#include <queue>
#include <limits>
#include <cmath>
#include <iostream>
// represents a single pixel
class Node {
public:
int idx; // index in the flattened grid
float cost; // cost of traversing this pixel
Node(int i, float c) : idx(i), cost(c) {}
};
bool operator<(const Node &n1, const Node &n2) {
return n1.cost > n2.cost;
}
bool operator==(const Node &n1, const Node &n2) {
return n1.idx == n2.idx;
}
// various grid heuristics:
// http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html#S7
float linf_norm(int i0, int j0, int i1, int j1) {
return std::max(std::abs(i0 - i1), std::abs(j0 - j1));
}
// manhattan distance
float l1_norm(int i0, int j0, int i1, int j1) {
return std::abs(i0 - i1) + std::abs(j0 - j1);
}
// weights: flattened h x w grid of costs
// h, w: height and width of grid
// start, goal: index of start/goal in flattened grid
// diag_ok: if true, allows diagonal moves (8-conn.)
// paths (output): for each node, stores previous node in path
class Astar {
public:
float* weights = nullptr;
int h;
int w;
int start;
int goal;
bool diag_ok;
int* paths = nullptr;
void setVariables(float* weightsInput, int hInput, int wInput, int startInput, int goalInput, bool diag_okInput, int* pathsInput) {
weights = weightsInput;
h = hInput;
w = wInput;
start = startInput;
goal = goalInput;
diag_ok = diag_okInput;
paths = pathsInput;
}
void start() {
const float INF = std::numeric_limits<float>::infinity();
std::cout << "width : " << w << " " << "height : " << h << std::endl;
std::cout << "start : " << start << " goal : " << goal << std::endl;
Node start_node(start, 0.);
Node goal_node(goal, 0.);
float* costs = new float[h * w];
for (int i = 0; i < h * w; ++i)
costs[i] = INF;
costs[start] = 0.;
std::priority_queue<Node> nodes_to_visit;
nodes_to_visit.push(start_node);
int* nbrs = new int[3];
bool solution_found = false;
while (!nodes_to_visit.empty()) {
// .top() doesn't actually remove the node
Node cur = nodes_to_visit.top();
if (cur == goal_node) {
solution_found = true;
break;
}
nodes_to_visit.pop();
int row = cur.idx / w;
int col = cur.idx % w;
bool allowDiag;
// check bounds and find up to eight neighbors: top to bottom, left to right
// can move only right\down\down - right so we can max have 3 neighbours
nbrs[0] = (col + 1 < w) ? cur.idx + 1 : -1; // right
nbrs[1] = (row + 1 < h) ? cur.idx + w : -1; // down
allowDiag = (weights[cur.idx + w + 1] == 14) ? true : false;
nbrs[2] = (allowDiag) ? cur.idx + w + 1 : -1; // down-right
std::cout << "right-bottom node : " << weights[cur.idx + w + 1] << std::endl;
float heuristic_cost;
for (int i = 0; i < 3; ++i) {
std::cout << "neighbours : " << nbrs[i] << " ";
if (nbrs[i] >= 0) {
// the sum of the cost so far and the cost of this move
float new_cost = costs[cur.idx] + weights[nbrs[i]];
if (new_cost < costs[nbrs[i]]) {
// estimate the cost to the goal based on legal moves
if (allowDiag) {
heuristic_cost = linf_norm(nbrs[i] / w, nbrs[i] % w,
goal / w, goal % w);
}
else {
heuristic_cost = l1_norm(nbrs[i] / w, nbrs[i] % w,
goal / w, goal % w);
}
// paths with lower expected cost are explored first
float priority = new_cost + heuristic_cost;
nodes_to_visit.push(Node(nbrs[i], priority));
costs[nbrs[i]] = new_cost;
paths[nbrs[i]] = cur.idx;
}
}
}
std::cout << "\n";
}
delete[] costs;
delete[] nbrs;
//return solution_found;
}
};
int main() {
Astar astarPathfinding;
float* weights;
int h;
int w;
int start;
int goal;
bool diag_ok;
int* paths;
astarPathfinding.setVariables(weights, h, w, start, goal, diag_ok, paths);
astarPathfinding.start(); // error
return 0;
}
You have "start" as member and "start" as function.
Rename one of them will fix your error.
I tried to implement this algorithm but there's some logical error. The algorithm is given below.
DFS(G)
1. for each vertex u ∈ G.V
2. u.color = WHITE
3. u.pi = NIL
4. time = 0
5. for each vertex u ∈ G.V
6. if u.color == WHITE
7. DFS-VISIT(G,u)
DFS-VISIT(G,u)
1. time = time + 1
2. u.d = time
3. u.color = GRAY
4. for each v ∈ G.Adj[u]
5. if v.color == WHITE
6. v.pi = u
7. DFS-VISIT(G,v)
8. u.color = BLACK
9. time = time + 1
10. u.f = time
Code:
#include <bits/stdc++.h>
using namespace std;
#define WHITE 0
#define GRAY 1
#define BLACK 2
#define SIZE 100
int Time;
int adj[SIZE][SIZE];
int color[SIZE];
int parent[SIZE];
int d[SIZE];
void dfs_Visit(int G, int u)
{
Time++;
d[u] = Time;
color[u] = GRAY;
for(int i = 0; i < G; i++)
{
if(color[i] == WHITE)
{
parent[i] = u;
dfs_Visit(G, i);
}
}
color[u] = BLACK;
Time++;
cout << u << " ";
}
void dfs(int G)
{
for(int i = 0; i < G; i++)
{
color[i] = WHITE;
parent[i]=NULL;
}
Time=0;
cout << "DFS is ";
for(int i = 0; i < G; i++)
{
if(color[i] == WHITE)
{
dfs_Visit(G, i);
}
}
}
int main()
{
int vertex;
int edge;
cout << "VERTEX & Edge : ";
cin >> vertex >> edge;
cout << "Vertex is : " << vertex <<endl;
cout << "Edge is : " << edge <<endl;
int node1, node2;
for(int i = 0; i < edge; i++)
{
cout << "EDGE " << i << ": ";
cin >> node1 >> node2;
adj[node1][node2] = 1;
adj[node2][node1] = 1;
}
dfs(vertex);
}
Output picture
Inputs:
VERTEX & Edge : 4 5
Vertex is : 4
Edge is : 5
EDGE 0: 0 1
EDGE 1: 1 2
EDGE 2: 2 0
EDGE 3: 0 3
EDGE 4: 2 4
Output:
DFS is 3 2 1 0
And the accepted result is 2 1 3 0
The problem is that you haven't coded DFS-VISIT step 4 correctly
Step 4 says for each v ∈ G.Adj[u] but your code says for(int i=0; i<G; i++). Those aren't the same thing at all. You should only visit the adjacent vertexes.
In fact if you look at your code you never use adj at all. That can't be right.
I have a graph with N vertices and M edges (N is between 1 and 15 and M is between 1 and N^2). The graph is directed and weighted (with a probability for that excact edge). You are given a start vertex and a number of edges. The program is then going to calculate the probability for each vertex being the end vertex.
Examle input:
3 3 //Number of vertices and number of edges
1 2 0.4 //Edge nr.1 from vertex 1 to 2 with a probability of 0.4
1 3 0.5 //Edge nr.2 from vertex 1 to 3 with a probability of 0.5
2 1 0.8 //Edge nr.3...
3 //Number of questions
2 1 //Start vertex, number of edges to visit
1 1
1 2
Output:
0.8 0.2 0.0 //The probability for vertex 1 beign the last vertex is 0.8 for vertex 2 it is 0.2 and for vertex 3 it is 0.0
0.1 0.4 0.5
0.33 0.12 0.55
I have used a DFS in my solution, but when number of edges to visit can be up to 1 billion, this is way too slow... I have been looking at DP but I am not sure about how to implement it for this particular problem (if it is even the right way to solve it). So I was hoping that some of you could suggest an alternative to DFS and/or perhaps a way of using/implementing DP.
(I know it might be a bit messy, I have only been programming in C++ for a month)
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
struct bird {
int colour;
float probability;
};
struct path {
int from;
int to;
};
vector <vector <bird>> birdChanges;
vector <int> layer;
vector <double> savedAnswers;
stack <path> nextBirds;
int fromBird;
//Self loop
void selfLoop(){
float totalOut = 0;
for (int i = 0; i < birdChanges.size(); i++) {
for (int j = 0; j < birdChanges[i].size(); j++) {
totalOut += birdChanges[i][j].probability;
}
if (totalOut < 1) {
bird a;
a.colour = i;
a.probability = 1 - totalOut;
birdChanges[i].push_back(a);
}
totalOut = 0;
}
}
double fillingUp(double momentarilyProbability, long long int numberOfBerries){
int layernumber=0;
while (layer[numberOfBerries - (1+layernumber)] == 0) {
layernumber++;
if (numberOfBerries == layernumber) {
break;
}
}
layernumber = layer.size() - layernumber;
path direction;
int b;
if (layernumber != 0) {
b= birdChanges[nextBirds.top().from][nextBirds.top().to].colour;//Usikker
}
else {
b = fromBird;
}
while (layer[numberOfBerries - 1] == 0) {
//int a = birdChanges[nextBirds.top().from][nextBirds.top().to].colour;
if (layernumber != 0) {
momentarilyProbability *= birdChanges[nextBirds.top().from][nextBirds.top().to].probability;
//b = birdChanges[nextBirds.top().from][nextBirds.top().to].colour;
}
for (int i = 0; i < birdChanges[b].size(); i++) {
direction.from = b;
direction.to = i;
//cout << endl << "Stacking " << b << " " << birdChanges[b][i].colour;
nextBirds.push(direction);
layer[layernumber]++;
}
layernumber++;
b = birdChanges[nextBirds.top().from][nextBirds.top().to].colour;
}
//cout << "Returning" << endl;
return momentarilyProbability *= birdChanges[nextBirds.top().from][nextBirds.top().to].probability;;
}
//DFS
void depthFirstSearch(int fromBird, long long int numberOfBerries) {
//Stack for next birds (stack)
path a;
double momentarilyProbability = 1;//Momentarily probability (float)
momentarilyProbability=fillingUp(1, numberOfBerries);
//cout << "Back " << momentarilyProbability << endl;
//Previous probabilities (stack)
while (layer[0] != 0) {
//cout << "Entering" << endl;
while (layer[numberOfBerries - 1] != 0) {
savedAnswers[birdChanges[nextBirds.top().from][nextBirds.top().to].colour] += momentarilyProbability;
//cout << "Probability for " << birdChanges[nextBirds.top().from][nextBirds.top().to].colour << " is " << momentarilyProbability << endl;
momentarilyProbability = momentarilyProbability / birdChanges[nextBirds.top().from][nextBirds.top().to].probability;
nextBirds.pop();
layer[numberOfBerries - 1]--;
if (layer[numberOfBerries - 1] != 0) {
momentarilyProbability *= birdChanges[nextBirds.top().from][nextBirds.top().to].probability;
}
}
if (layer[0] != 0) {
int k = 1;
while (layer[layer.size() - k]==0&&k+1<=layer.size()) {
//cout << "start" << endl;
momentarilyProbability = momentarilyProbability / birdChanges[nextBirds.top().from][nextBirds.top().to].probability;
//cout << "Popping " << nextBirds.top().from << birdChanges[nextBirds.top().from][nextBirds.top().to].colour << endl;
nextBirds.pop();
//cout << "k " << k << endl;
layer[numberOfBerries - 1 - k]--;
k++;
//cout << "end" << endl;
}
}
if (layer[0] != 0) {
//cout << 1 << endl;
//cout << "Filling up from " << nextBirds.top().from << birdChanges[nextBirds.top().from][nextBirds.top().to].colour << endl;
momentarilyProbability = fillingUp(momentarilyProbability, numberOfBerries);
}
}
//Printing out
for (int i = 1; i < savedAnswers.size(); i++) {
cout << savedAnswers[i] << " ";
}
cout << endl;
}
int main() {
int numberOfColours;
int possibleColourchanges;
cin >> numberOfColours >> possibleColourchanges;
birdChanges.resize(numberOfColours+1);
int from, to;
float probability;
for (int i = 0; i < possibleColourchanges; i++) {
cin >> from >> to >> probability;
bird a;
a.colour = to;
a.probability = probability;
birdChanges[from].push_back(a);
}
selfLoop();
int numberOfQuestions;
cin >> numberOfQuestions;
long long int numberOfBerries;
for (int i = 0; i < numberOfQuestions; i++) {
cin >> fromBird >> numberOfBerries;
savedAnswers.assign(numberOfColours + 1, 0);
layer.resize(numberOfBerries, 0);
//DFS
depthFirstSearch(fromBird, numberOfBerries);
}
system("pause");
}
Fast explanation of how to do this with the concept of a Markov Chain:
Basic algorithm:
Input: starting configuration vector b of probabilities of
being in a vertex after 0 steps,
Matrix A that stores the probability weights,
in the scheme of an adjacency matrix
precision threshold epsilon
Output:
an ending configuration b_inf of probabilities after infinite steps
Pseudocode:
b_old = b
b_new = A*b
while(difference(b_old, b_new) > epsilon){
b_old = b_new
b_new = A*b_old
}
return b_new
In this algorithm, we essentially compute potencies of the probability matrix and look for when those become stable.
b are the probabilities to be at a vertex after no steps where taken
(so, in your case, every entry being zero except for the start vertex, which is one)
A*b are those after one step was taken
A^2 * b are those after two steps were taken, A^n * b after n steps.
When A^n * b is nearly the same as A^n-1 * b, we assume that nothing big will happen to it any more, that it is basically the same as A^infinity * b
One can mock this algorithm with some examples, like an edge that leads in a subgraph with a very small probability that will result one being in the subgraph with probability 1 after infinite steps, but for example from reality, it will work.
For the difference, the euclidean distance should work well, but essentially any norm does, you could also go with maximum or manhattan.
Note that I present a pragmatic point of view, a mathematician would go far more into detail about under which properties of A it will converge how fast for which values of epsilon.
You might want to use a good library for matrices for that, like Eigen.
EDIT:
Reading the comment of Jarod42, I realize that your amount of steps are given. In that case, simply go with A^steps * b for the exact solution. Use a good library for a fast computation of the potency.
I'm trying to write a maze solver using backtracking. It should see whether it's possible to solve a given puzzle from the starting point S to the end point E. The pseudo code can be seen in this link here. My implementation looks like this:
const int N = 8; // global var
bool exploreMaze(char maze[][N], int x, int y)
{
if(y >= 8 || y < 0 || x >= 7 || x < 0) // null char at end of each 1d array
return false;
if(maze[x][y] == '*')
return false;
if(maze[x][y] == 'E')
return true;
maze[x][y] = '*'; // set grid to '*' as to not loop infinitely
if(exploreMaze(maze, x + 1, y))
{
cout << "up" << ", ";
return true;
}
if(exploreMaze(maze, x - 1, y))
{
cout << "down" << ", ";
return true;
}
if(exploreMaze(maze, x, y - 1))
{
cout << "left" << ", ";
return true;
}
if(exploreMaze(maze, x, y + 1))
{
cout << "right" << ", ";
return true;
}
return false;
}
bool isMazeSolvable(char maze[][N])
{
int startX = -1, startY = -1;
for(int i = 0; i < N; i++)
{
for(int j = 0; j < N; j++)
{
if(maze[i][j] == 'S')
startX = i;
startY = j;
}
}
if(startX == -1)
return false;
return exploreMaze(maze, startX, startY);
}
int main()
{
char maze[N][N] = {"*******", " S ", "*******", " E ", "*******",
"*******", "*******", "*******"};
cout << isMazeSolvable(maze);
return 0;
}
The array that I'm testing in main should definitely have no solution, but somehow I'm getting 1(true) as the output. Any ideas?
Your maze '*' is only initialized out in the Y direction by 7 characters, but your maze walker checks out to 8 character. This allows it to walk around the end of your walls.
I added a quick maze print function and changed the exploreMaze to put '.' where it walks. Giving the following output:
Initial maze:
*******
S
*******
E
*******
*******
*******
*******
left, left, left, left, left, up, up, right, right, right, right, right, right,
1
After explore:
*******
.......
*******.
E.....
*******
*******
*******
*******
Soluton: Either change the initializer to use 8 character walls, or change the exploreMaze function to only look 7 characters in the Y direction.
Also note: You are not doing the "backtracking" part of the maze solver, because you mark where you have been but don't clean off your path on your way out of the recursion. Add
maze[x][y] = ' '; // Clear the grid so we can try this spot again in another recursion
to the end of your exploreMaze function
I wrote a C++ routine to find nearest double element in sorted array. Is there a way to speed up?
There are two branches based on the value of boolean reversed, if reversed it is sorted in the decreasing order.
void findNearestNeighbourIndex_new(real_T value, real_T* x, int_T x_size, int_T& l_idx)
{
l_idx = -1;
bool reversed= (x[1] - x[0] < 0);
if ((!reversed&& value <= x[0])
|| (reversed&& value >= x[0])){
// Value is before first position in x
l_idx = 0;
}
else if ((!reversed&& value >= x[x_size - 1])
|| (reversed&& value <= x[x_size - 1])){
// Value is after last position in x
l_idx = x_size - 2;
}
else // All other cases
{
if (reversed)
{
for (int i = 0; i < x_size - 1; ++i)
{
if (value <= x[i] && value > x[i + 1])
{
l_idx = i;
break;
}
}
}
else{
for (int i = 0; i < x_size - 1; ++i)
{
if (value >= x[i] && value < x[i + 1])
{
l_idx = i;
break;
}
}
}
}
}
In this very case where array is sorted, I do not see a way to do better. So, with profiling i see that the comparison in if (value <= x[i] && value > x[i + 1]) is expensive.
EDIT
tried with lower_bound()
std::vector<real_T> x_vec(x, x + x_size);
l_idx = std::upper_bound(x_vec.begin(), x_vec.end(), value) - x_vec.begin() - 1;
You can use std::lower_bound to find a element equal or greater than requested, and then move iterator backwards and check preceding value too. This will use binary search and will cost O(log n), also this enables standard STL comparators and so on.
If you don't actually have an vector to use with upper_bound() you don't need to construct one as that is going to be an O(n) operation. upper_bound() will work with the array that you have. You can use:
l_idx = std::upper_bound(x, x + size, value) - x - 1;
Test case:
#include <iostream>
#include <functional>
#include <algorithm>
int main()
{
const int size = 9;
int x[9] = {1,2,3,4,5,6,7,8,9};
auto pos = std::upper_bound(x, x + size, 5) - x;
std::cout << "position: " << pos;
return 0;
}
Output:
5
As the result of upper_bound() points us to 6(live example).
The way is to substract 1 to size (to make work over higest value) and 0.5 to target value to make it accurate:
#include <iostream>
#include <functional>
#include <algorithm>
using namespace std;
int main()
{
float x[10] = { 2,3,4,5,6,7,8,9,10,11 },y;
int size = sizeof(x) / sizeof(x[0]),pos;
y = 4.1; pos = std::upper_bound(x, x + size - 1, y - 0.5) - x;
std::cout << "position: " << pos << " target value=" << y << " upper_bound=" << x[pos] << endl;
y = 4.9; pos = std::upper_bound(x, x + size - 1, y - 0.5) - x;
std::cout << "position: " << pos << " target value=" << y << " upper_bound=" << x[pos] << endl;
y = -0.5; pos = std::upper_bound(x, x + size - 1, y - 0.5) - x;
std::cout << "position: " << pos << " target value=" << y << " upper_bound=" << x[pos] << endl;
y = 100; pos = std::upper_bound(x, x + size - 1, y - 0.5) - x;
std::cout << "position: " << pos << " target value=" << y << " upper_bound=" << x[pos] << endl;
getchar();
return 0;
}
Implemented this helper routine
void findNearestNeighbourIndex_bin_search_new(real_T value, real_T* x,
int_T start, int_T stop, int_T& l_idx)
{
int_T mid = ( stop - start ) / 2;
if (value >= x[mid+1])
{
findNearestNeighbourIndex_bin_search_new(value, x, mid + 1, stop, l_idx);
}
else if (value < x[mid])
{
findNearestNeighbourIndex_bin_search_new(value, x, start, mid, l_idx);
}
else
{
l_idx = mid;
return;
}
}