//
// main.cpp
// path_finder
//
// Created by Jack Kim on 2023/06/01.
//
#include <iostream>
#include <vector>
#include <iomanip>
#include <queue>
#include <string>
#include <ostream>
#include <stack>
using namespace std;
class location{
public:
int x;
int y;
shared_ptr<location> prev;
public:
location(int x, int y, shared_ptr<location> prev)
: x(x), y(y), prev(prev) {}
};
void print_map(const string & title, vector<vector<int>> & map){
int width = (int)map[0].size();
int height = (int)map.size();
cout << "[" << title << "]" << endl;
for(int x=0;x<width*2+1;x++)cout << "─"; cout << endl;
for(int y=0;y<height;y++){
cout << "│";
for(int x=0;x<width;x++){
string ch = " ";
switch(map[y][x]) {
case 1: ch = "▒"; break;
case 0: ch = " "; break;
case 9: ch = "+"; break;
}
if(x == 0 && y == 0) ch = "S";
else if(x == width-1 && y == height-1) ch = "E";
cout << ch ;
if(x != width-1)
cout << " ";
}
cout << "│" << endl;
}
for(int x=0;x<width*2+1;x++)cout << "─"; cout << endl;
}
void print_visited(const string & title, vector<vector<int>> & map, vector<vector<int>> & visited){
vector<vector<int>> visited_map = map;
for(auto y=0;y<map.size();y++){
for(auto x=0;x<map[0].size();x++){
if(visited[y][x] == 1)
visited_map[y][x] = 9;
}
}
print_map(title, visited_map);
cout << endl;
}
void print_result(vector<vector<int>> & map, vector<vector<int>> & visited, shared_ptr<location> & p, bool show_visited = true){
vector<vector<int>> found_path = map;
auto temp = p;
while(temp != nullptr){
found_path[temp->y][temp->x] = 9;
temp = temp->prev;
}
print_map("PATH", found_path);
if(show_visited) print_visited("VISITED", map, visited);
}
bool moveable(vector<vector<int>> & map, vector<vector<int>> & visited, int x, int y){
if(x < 0 || x > map[0].size()-1) return false;
if(y < 0 || y > map.size()-1) return false;
if(map[y][x] != 0) return false;
if(visited[y][x] != 0) return false;
return true;
}
void bfs(vector<vector<int>> & map, vector<vector<int>> & visited, queue<shared_ptr<struct location>> & q){
int width = (int)map[0].size();
int height = (int)map.size();
q.push(shared_ptr<location>(new location(0, 0, nullptr)));
while(!q.empty()){
auto p = q.front(); q.pop();
int x = p->x, y = p->y;
visited[y][x] = 1;
if(x == width - 1 && y == height - 1){
print_result(map, visited, p);
return;
}
if(moveable(map, visited, x, y-1)) q.push(shared_ptr<location>(new location(x, y-1, p))); // up
if(moveable(map, visited, x, y+1)) q.push(shared_ptr<location>(new location(x, y+1, p))); // down
if(moveable(map, visited, x-1, y)) q.push(shared_ptr<location>(new location(x-1, y, p))); // left
if(moveable(map, visited, x+1, y)) q.push(shared_ptr<location>(new location(x+1, y, p))); // right
}
}
void dfs(vector<vector<int>> & map, vector<vector<int>> & visited, stack<shared_ptr<location>> & s){
int width = (int)map[0].size();
int height = (int)map.size();
s.push(shared_ptr<location>(new location(0, 0, nullptr)));
while(!s.empty()){
auto p = s.top(); s.pop();
int x = p->x, y = p->y;
visited[y][x] = 1;
if(x == width - 1 && y == height - 1){
print_result(map, visited, p);
return;
}
if(moveable(map, visited, x-1, y)) s.push(shared_ptr<location>(new location(x-1, y, p))); // left
if(moveable(map, visited, x+1, y)) s.push(shared_ptr<location>(new location(x+1, y, p))); // right
if(moveable(map, visited, x, y-1)) s.push(shared_ptr<location>(new location(x, y-1, p))); // up
if(moveable(map, visited, x, y+1)) s.push(shared_ptr<location>(new location(x, y+1, p))); // down
}
}
void dfs_recursive(vector<vector<int>> & map, vector<vector<int>> & visited, shared_ptr<location> p){
int width = (int)map[0].size();
int height = (int)map.size();
int x = p->x, y = p->y;
visited[y][x] = 1;
if(x == width - 1 && y == height - 1){
print_result(map, visited, p);
return;
}
if(moveable(map, visited, x-1, y))
dfs_recursive(map, visited, shared_ptr<location>(new location(x-1, y, p))); // left
if(moveable(map, visited, x+1, y))
dfs_recursive(map, visited, shared_ptr<location>(new location(x+1, y, p))); // right
if(moveable(map, visited, x, y-1))
dfs_recursive(map, visited, shared_ptr<location>(new location(x, y-1, p))); // up
if(moveable(map, visited, x, y+1))
dfs_recursive(map, visited, shared_ptr<location>(new location(x, y+1, p))); // down
}
int dfs_recursive_all(vector<vector<int>> & map, vector<vector<int>> & visited, vector<vector<int>> & record, shared_ptr<location> p){
int width = (int)map[0].size();
int height = (int)map.size();
int x = p->x, y = p->y;
visited[y][x] = 1;
record[y][x] = 1;
int theWays = 0;
if(x == width - 1 && y == height - 1){
print_result(map, visited, p, false);
theWays += 1;
}
if(moveable(map, visited, x-1, y))
theWays += dfs_recursive_all(map, visited, record, shared_ptr<location>(new location(x-1, y, p))); // left
if(moveable(map, visited, x+1, y))
theWays += dfs_recursive_all(map, visited, record, shared_ptr<location>(new location(x+1, y, p))); // right
if(moveable(map, visited, x, y-1))
theWays += dfs_recursive_all(map, visited, record, shared_ptr<location>(new location(x, y-1, p))); // up
if(moveable(map, visited, x, y+1))
theWays += dfs_recursive_all(map, visited, record, shared_ptr<location>(new location(x, y+1, p))); // down
visited[y][x] = 0;
return theWays;
}
int main(int argc, const char * argv[]) {
vector<vector<int>> map = {
{0, 1, 0, 0, 0, 0, 0},
{0, 1, 0, 1, 0, 1, 0},
{0, 0, 0, 0, 0, 1, 0},
{1, 1, 1, 1, 0, 1, 0},
{1, 1, 1, 1, 0, 0, 0},
};
print_map("MAP", map);
cout << endl;
{
cout << "<BFS BY QUEUE>" << endl << endl;
vector<vector<int>> visited(map.size(), vector<int>(map[0].size()));
queue<shared_ptr<struct location>> q; bfs(map, visited, q);
}
cout << endl;
{
cout << "<DFS BY STACK> " << endl;
stack<shared_ptr<struct location>> s;
vector<vector<int>> visited(map.size(), vector<int>(map[0].size()));
dfs(map, visited, s);
}
cout << endl;
{
cout << "<DFS BY RECURSIVE>" << endl;
vector<vector<int>> visited(map.size(), vector<int>(map[0].size()));
dfs_recursive(map, visited, shared_ptr<location>(new location(0, 0, nullptr)));
}
cout << endl;
{
cout << "<DFS ALL BY RECURSIVE>" << endl;
vector<vector<int>> visited(map.size(), vector<int>(map[0].size()));
vector<vector<int>> record(map.size(), vector<int>(map[0].size()));
auto count = dfs_recursive_all(map, visited, record, shared_ptr<location>(new location(0, 0, nullptr)));
cout << "total path : " << count << endl << endl;
print_visited("[VISITED]", map, record);
}
cout << endl;
return 0;
}