DFS on undirected graph - c++

I have an exercise for university where I have to write a DFS algorithm to run on an undirected graph. I also have to make the program sum the values of all nodes show the order in which the nodes were visited.
Here is the given structure:
#include <iostream>
#include <cassert>
using namespace std;
struct node {
// DATA STRUCTURE NODES
};
int dfs_sum(/* FUNCTION ARGUMENTS */) {
// DEPTH FIRST SEARCH ALGORITHM
}
void node_init(/* FUNCTION ARGUMENTS */) {
// INITIALIZATION OF NODE WITH LABEL "value" AND NEIGHBOR "num_adjacent"
}
void edge_init(/* FUNCTION ARGUMENTS */) {
// INITIALIZATION OF EDGE BETWEEN TWO NODES
}
void node_delete(/* FUNCTION ARGUMENTS */) {
// DE-ALLOCATE MEMORY THAT WAS ALLOCATED IN "node_init"
}
void init_nodes(node *nodes) {
node_init(&nodes[0], 1, 1);
node_init(&nodes[1], 2, 4);
node_init(&nodes[2], 3, 1);
node_init(&nodes[3], 4, 4);
node_init(&nodes[4], 5, 4);
node_init(&nodes[5], 6, 2);
node_init(&nodes[6], 7, 5);
node_init(&nodes[7], 8, 3);
node_init(&nodes[8], 9, 2);
node_init(&nodes[9], 10, 2);
node_init(&nodes[10], 11, 4);
node_init(&nodes[11], 12, 2);
edge_init(&nodes[0], &nodes[1]);
edge_init(&nodes[1], &nodes[4]);
edge_init(&nodes[1], &nodes[6]);
edge_init(&nodes[1], &nodes[7]);
edge_init(&nodes[2], &nodes[3]);
edge_init(&nodes[3], &nodes[6]);
edge_init(&nodes[3], &nodes[7]);
edge_init(&nodes[3], &nodes[11]);
edge_init(&nodes[4], &nodes[5]);
edge_init(&nodes[4], &nodes[8]);
edge_init(&nodes[4], &nodes[9]);
edge_init(&nodes[5], &nodes[6]);
edge_init(&nodes[6], &nodes[9]);
edge_init(&nodes[6], &nodes[10]);
edge_init(&nodes[7], &nodes[10]);
edge_init(&nodes[8], &nodes[10]);
edge_init(&nodes[10], &nodes[11]);
}
void delete_nodes(node *nodes) {
for (int i = 0; i < 12; ++i) {
node_delete(&nodes[i]);
}
}
int main() {
node *nodes= new node[12];
init_nodes(nodes);
int sum_dfs = dfs_sum(&nodes[0]);
cout << endl;
int sum_loop = 0;
for (int i = 0; i < 12; ++i) {
sum_loop += nodes[i].value;
}
cout << "sum_dfs = " << sum_dfs << " sum_loop = " << sum_loop << endl;
delete_nodes(nodes);
delete [] nodes;
return 0;
}
I do not know how to begin this exercise

I am not familiar with c++ (I think that's what you used) but the implementation is the same anyway so I can give you a pseudo-code of what the algorithm should look like.
create a stack where object will be stored
all nodes are not visited when we begin
push source in the stack and mark it as visited
while the stack is not empty;
go to the first adjacent node to source and if it has not been visited
mark as visited and move to its next unvisited node and so on
if at any point you reach a node that cannot visited any other unvisited node
pop the stack until you can visited an unvisited node.
Do this until the stack is empty
Below is a simple implementation using an adjacency matrix
void dfs(int adjacency_matrix[][], int source){
Stack<Integer> stack = new Stack<>();
int numNodes = adjacency_matrix[source].length -1;
boolean [] visited = new boolean[numNodes +1];
visited[source] = true;
stack.add(source);
while(!stack.isEmpty()){
int current = stack.peek(); // don't remove the element but get it
System.out.println("Current node being visited is "+current);
for(int x = 0; x <= numNodes; x++){
if(adjacency_matrix[current][x] == 1 && visited[x] == false){
visited[x] = true;
stack.push(x);
break;
}else if(x == numNodes){
stack.pop();
}
}
}
}
You can test with a graph like this
0 --- 1-------5----6--8
| \ \ | / /
| \ \ | / /
| \ \ | / /
2 3----4---7---9
0 1 2 3 4 5 6 7 8 9
---------------------
0 | 0 1 1 1 0 0 0 0 0 0
1 | 1 0 0 0 1 1 0 0 0 0
2 | 1 0 0 0 0 0 0 0 0 0
3 | 1 0 0 0 1 0 0 0 0 0
4 | 0 1 0 1 0 0 0 1 0 0
5 | 0 1 0 0 0 0 1 1 0 0
6 | 0 0 0 0 0 1 0 1 1 0
7 | 0 0 0 0 1 1 1 0 0 1
8 | 0 0 0 0 0 0 1 0 0 1
9 | 0 0 0 0 0 0 0 1 1 0
---------------------

Related

How to implement a recursive function to save the elements of the N-th Cartesian Power of (0,1,...,N) in C++?

If the question is not clear, I want to have for example if N=4 a result like this:
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 2 2 2 2 3 3 3 3 . . . .
0 1 2 3 4 0 1 2 3 4 1 2 3 4 1 2 3 4 . . . .
This is my function:
int Combinazioni(int i, int N, vector<vector<int>> & combs){
if(i<N) {
for (int k=0; k<=N; k++){
combs[i].push_back(k);
return(Combinazioni(i+1,N, combs));
}
for(int j=0; j<N-1;j++){
while(combs[j].size()<combs[N-1].size()){
combs[j].push_back(combs[j].back());
}
}
}
return 1;
}
where combs is a vector of vectors that I have initialized with N rows, and then I'll transpose it for better accessibility...
When I compile it gives me this:
warning: control reaches end of non-void function [-Wreturn-type]
and when I execute it prints
0
0 0
0 0 0
0 0 0 0
There must definitely be some bug in the logic of my recursion but I'm not very good at visualizing it so if there's an easy and elegant way to do this or to solve the bug I'd be grateful, thank you.
P.S. I think it doesn't really need to be super-efficient, and in fact if there's a better alternative to recursion, or some effective library, it would be equally fine for my purpose
Hard coded solution would look like:
std::vector<int> values{0, 1, 2, 3, 4}
for (int a1 : values) {
for (int a2 : values) {
for (int a3 : values) {
for (int a4 : values) {
for (int a5 : values) {
do_job({a1, a2, a3, a4, a5});
}
}
}
}
}
More generic solution might be:
bool increase(std::size_t max_size, std::vector<std::size_t>& it)
{
for (std::size_t i = 0, size = it.size(); i != size; ++i) {
const std::size_t index = size - 1 - i;
++it[index];
if (it[index] > max_size) {
it[index] = 0;
} else {
return true;
}
}
return false;
}
void iterate(std::size_t max_size, std::size_t len)
{
std::vector<std::size_t> it(len, 0);
do {
do_job(it);
} while (increase(max_size, it));
}
Demo

Breadth First Search fails to find destination that does exist

So I have been working on a Breadth First Search to get a path given a starting and ending node. However in some cases it seems to fail and not get the path, which I know is possible since a Depth First Search and visual inspection shows that it should exist.
I have an Adjacency Matrix:
1 2 3 4 5 6 7 8
1 0 20 25 20 0 0 0 0
2 20 0 5 0 30 0 0 0
3 25 5 0 13 8 21 0 0
4 20 0 13 0 0 17 0 0
5 0 30 8 0 0 33 0 0
6 0 0 21 17 33 0 0 0
7 0 0 0 0 0 0 0 10
8 0 0 0 0 0 0 10 0
Which has a graph as follows:
This is my function:
void Network::BFS(int src, int dest, vector<bool>& visited, vector<int>& path) {
// The Queue is the core for the BFS.
queue<int> Queue;
// Mark current node as visited.
visited[src] = true;
Queue.push(src);
// While queue is not empty.
while (!Queue.empty()) {
// Add node to path.
// Check if we have found the destination yet or not, if we have we do one last push to path and we're done!
if (Queue.front() == dest) {
return;
}
int top = Queue.front();
path.push_back(Queue.front());
// Pop off front.
Queue.pop();
// Iterate and process all none visited nodes.
for (int node = 0; node < amountOfNodes; node++) {
// Check if it is not visited already.
if (visited[node] == false && (adjMatrix[node * amountOfNodes + src] != 0)) {
Queue.push(node); // Add to end.
visited[node] = true;
}
}
}
}
Sample input and output:
(6, 3) -> Path is: 6
(1, 5) -> Path is: 1 2 3 4
As you can see, it does not compute the path properly at all. Where is my algorithm going wrong here, and how do I fix it?
BFS involves visiting adjacent nodes in a FIFO fashion. Once you reach a node, you put into the queue all its neighbours, unless they were already visited.
First off, there's a typo where you iterate over adjacent nodes. You want to traverse the top column, not the src one:
adjMatrix[node * amountOfNodes + top] != 0
// ~~^
Secondly, your current path implementation stores the visit order of nodes, not a path from the source to its destination. For the latter, you need to store the parent of each node, so that the final path can be restored by going from a child (destination) to its parent, grandparent, great-grandparent, ..., etc.
std::vector<int> parent(amountOfNodes, -1);
//...
if (visited[node] == false && (adjMatrix[node * amountOfNodes + top] != 0))
{
Queue.push(node); // Add to end.
visited[node] = true;
parent[node] = top;
}
Restoring the path is straightforward:
int u = dest;
do
{
std::cout << u << " ";
u = parent[u];
}
while (u != -1);
DEMO

Turning a 2D array of different color into a single color optimally

I am trying to find a solution of the puzzle game 'Flood It'. The main idea is to turn a whole N*M game board of k different colors into a single color. I have to start from the top left corner of the board and turn the same colored block into one of the colors of neighboring nodes and thus moving ahead and flooding the whole board into a single color at last. For example:
Initial Board:
1 1 1 2 2 3
1 1 2 3 4 5
1 1 1 1 3 4
1 4 3 2 1 5
2 3 4 5 1 2
Final Board:
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
where 1,2,3,4,5 represents different colors. I have prepared a C++ code for finding out the area of same colored block at any position of the board . This can be applied at the top left cell at first and then at the neighboring nodes of it to flood the color. My code is as follows:
#include <cstdint>
#include <vector>
#include <queue>
#include <string>
#include <iostream>
typedef std::vector<int32_t> vec_1d;
typedef std::vector<vec_1d> vec_2d;
// Print the 2d vector with a label
void dump(std::string const& label, vec_2d const& v)
{
std::cout << label << "\n";
for (std::size_t y(0); y < v.size(); ++y) {
for (std::size_t x(0); x < v[0].size(); ++x) {
std::cout << v[y][x] << " ";
}
std::cout << "\n";
}
std::cout << "\n";
}
// Recursive implementation of the search
void find_connected_r(int32_t target_color
, std::size_t x
, std::size_t y
, vec_2d const& colors
, vec_2d& result)
{
if ((result[y][x] == 1) || (colors[y][x] != target_color)) {
return;
}
result[y][x] = 1;
std::size_t width(colors[0].size());
std::size_t height(colors.size());
if (x > 0) {
find_connected_r(target_color, x - 1, y, colors, result);
}
if (y > 0) {
find_connected_r(target_color, x, y - 1, colors, result);
}
if (x < (width - 1)) {
find_connected_r(target_color, x + 1, y, colors, result);
}
if (y < (height - 1)) {
find_connected_r(target_color, x, y + 1, colors, result);
}
}
// Entry point to the search, select the implementation with last param
vec_2d find_connected(std::size_t x, std::size_t y, vec_2d const& colors, bool recursive)
{
if (colors.empty() || colors[0].empty()) {
throw std::runtime_error("Invalid input array size");
}
int32_t target_color(colors[y][x]);
vec_2d result(colors.size(), vec_1d(colors[0].size(), 0));
if (recursive) {
find_connected_r(target_color, x, y, colors, result);
}
else {
find_connected(target_color, x, y, colors, result);
}
return result;
}
void dump_coordinates(std::string const& label, vec_2d const& v)
{
std::cout << label << "\n";
for (std::size_t y(0); y < v.size(); ++y) {
for (std::size_t x(0); x < v[0].size(); ++x) {
if (v[y][x]) {
std::cout << "(" << x << ", " << y << ") ";
}
}
}
std::cout << "\n";
}
int main()
{
vec_2d colors{
{ 1, 1, 1, 1, 1, 1 }
, { 2, 2, 2, 3, 3, 1 }
, { 1, 1, 1, 1, 3, 1 }
, { 1, 3, 3, 3, 3, 1 }
, { 1, 1, 1, 1, 1, 1 }
};
}
How will I turn the whole board/matrix into a single color by examining the neighboring nodes?
A possible top-level algorithm to solve this puzzle is to repeat the following until there is only one color on the whole board:
Find all contiguous color regions. Treat the region at (0,0) as primary, all others as secondary.
Pick the largest (by count of tiles) secondary region with a color that is different to the primary region's color. Let's name the color of this secondary region the new_color.
Recolor the primary region to new_color.
Finding all the regions
We should keep a cumulative_mask to track of all the tiles that are already identified as part of some region.
First we find the primary region, starting search at (0,0), and update our cumulative_mask with the result.
Then repeat until no more regions can be found:
Find the position of the first zero tile in the cumulative_mask, which has at least one non-zero tile in the primary region mask.
Find the region starting at this position.
Update the cumulative_mask with the mask of this region.
Selecting the color
Simply iterate through secondary regions, and find the region with largest count, which has a different color than the primary region.
Code
(also on coliru)
Note: Intentionally written in a way to make it possible to understand the algorithm. This could definitely be refactored, and it's missing a lot of error checking.
#include <cstdint>
#include <vector>
#include <queue>
#include <string>
#include <iostream>
typedef std::vector<int32_t> vec_1d;
typedef std::vector<vec_1d> vec_2d;
typedef std::pair<std::size_t, std::size_t> position;
position const INVALID_POSITION(-1, -1);
int32_t const INVALID_COLOR(0);
// ============================================================================
struct region_info
{
int32_t color;
vec_2d mask;
std::size_t count() const
{
std::size_t result(0);
for (std::size_t y(0); y < mask.size(); ++y) {
for (std::size_t x(0); x < mask[0].size(); ++x) {
if (mask[y][x]) {
++result;
}
}
}
return result;
}
};
struct region_set
{
// The region that contains (0, 0)
region_info primary;
// All other regions
std::vector<region_info> secondary;
};
// ============================================================================
// Print the 2D vector with a label
void dump(std::string const& label, vec_2d const& v)
{
std::cout << label << "\n";
for (std::size_t y(0); y < v.size(); ++y) {
for (std::size_t x(0); x < v[0].size(); ++x) {
std::cout << v[y][x] << " ";
}
std::cout << "\n";
}
std::cout << "\n";
}
// Print the coordinates of non-zero elements of 2D vector with a label
void dump_coordinates(std::string const& label, vec_2d const& v)
{
std::cout << label << "\n";
for (std::size_t y(0); y < v.size(); ++y) {
for (std::size_t x(0); x < v[0].size(); ++x) {
if (v[y][x]) {
std::cout << "(" << x << ", " << y << ") ";
}
}
}
std::cout << "\n";
}
void dump(region_info const& ri)
{
std::cout << "Region color: " << ri.color << "\n";
std::cout << "Region count: " << ri.count() << "\n";
dump("Region mask:", ri.mask);
}
void dump(region_set const& rs)
{
std::cout << "Primary Region\n" << "\n";
dump(rs.primary);
for (std::size_t i(0); i < rs.secondary.size(); ++i) {
std::cout << "Secondary Region #" << i << "\n";
dump(rs.secondary[i]);
}
}
// ============================================================================
// Find connected tiles - implementation
void find_connected(int32_t target_color
, std::size_t x
, std::size_t y
, vec_2d const& colors
, vec_2d& result)
{
std::size_t width(colors[0].size());
std::size_t height(colors.size());
std::queue<position> s;
s.push(position(x, y));
while (!s.empty()) {
position pos(s.front());
s.pop();
if (result[pos.second][pos.first] == 1) {
continue;
}
if (colors[pos.second][pos.first] != target_color) {
continue;
}
result[pos.second][pos.first] = 1;
if (pos.first > 0) {
s.push(position(pos.first - 1, pos.second));
}
if (pos.second > 0) {
s.push(position(pos.first, pos.second - 1));
}
if (pos.first < (width - 1)) {
s.push(position(pos.first + 1, pos.second));
}
if (pos.second < (height - 1)) {
s.push(position(pos.first, pos.second + 1));
}
}
}
// Find connected tiles - convenience wrapper
vec_2d find_connected(std::size_t x, std::size_t y, vec_2d const& colors)
{
if (colors.empty() || colors[0].empty()) {
throw std::runtime_error("Invalid input array size");
}
int32_t target_color(colors[y][x]);
vec_2d result(colors.size(), vec_1d(colors[0].size(), 0));
find_connected(target_color, x, y, colors, result);
return result;
}
// ============================================================================
// Change color of elements at positions with non-zero mask value to new color
vec_2d& change_masked(int32_t new_color
, vec_2d& colors
, vec_2d const& mask)
{
for (std::size_t y(0); y < mask.size(); ++y) {
for (std::size_t x(0); x < mask[0].size(); ++x) {
if (mask[y][x]) {
colors[y][x] = new_color;
}
}
}
return colors;
}
// Combine two masks
vec_2d combine(vec_2d const& v1, vec_2d const& v2)
{
vec_2d result(v1);
for (std::size_t y(0); y < v2.size(); ++y) {
for (std::size_t x(0); x < v2[0].size(); ++x) {
if (v2[y][x]) {
result[y][x] = v2[y][x];
}
}
}
return result;
}
// Find position of first zero element in mask
position find_first_zero(vec_2d const& mask)
{
for (std::size_t y(0); y < mask.size(); ++y) {
for (std::size_t x(0); x < mask[0].size(); ++x) {
if (!mask[y][x]) {
return position(x, y);
}
}
}
return INVALID_POSITION;
}
bool has_nonzero_neighbor(std::size_t x, std::size_t y, vec_2d const& mask)
{
bool result(false);
if (x > 0) {
result |= (mask[y][x - 1] != 0);
}
if (y > 0) {
result |= (mask[y - 1][x] != 0);
}
if (x < (mask[0].size() - 1)) {
result |= (mask[y][x + 1] != 0);
}
if (y < (mask.size() - 1)) {
result |= (mask[y + 1][x] != 0);
}
return result;
}
// Find position of first zero element in mask
// which neighbors at least one non-zero element in primary mask
position find_first_zero_neighbor(vec_2d const& mask, vec_2d const& primary_mask)
{
for (std::size_t y(0); y < mask.size(); ++y) {
for (std::size_t x(0); x < mask[0].size(); ++x) {
if (!mask[y][x]) {
if (has_nonzero_neighbor(x, y, primary_mask)) {
return position(x, y);
}
}
}
}
return INVALID_POSITION;
}
// ============================================================================
// Find all contiguous color regions in the image
// The region starting at (0,0) is considered the primary region
// All other regions are secondary
// If parameter 'only_neighbors' is true, search only for regions
// adjacent to primary region, otherwise search the entire board
region_set find_all_regions(vec_2d const& colors, bool only_neighbors = false)
{
region_set result;
result.primary.color = colors[0][0];
result.primary.mask = find_connected(0, 0, colors);
vec_2d cumulative_mask = result.primary.mask;
for (;;) {
position pos;
if (only_neighbors) {
pos = find_first_zero_neighbor(cumulative_mask, result.primary.mask);
} else {
pos = find_first_zero(cumulative_mask);
}
if (pos == INVALID_POSITION) {
break; // No unsearched tiles left
}
region_info reg;
reg.color = colors[pos.second][pos.first];
reg.mask = find_connected(pos.first, pos.second, colors);
cumulative_mask = combine(cumulative_mask, reg.mask);
result.secondary.push_back(reg);
}
return result;
}
// ============================================================================
// Select the color to recolor the primary region with
// based on the color of the largest secondary region of non-primary color
int32_t select_color(region_set const& rs)
{
int32_t selected_color(INVALID_COLOR);
std::size_t selected_count(0);
for (auto const& ri : rs.secondary) {
if (ri.color != rs.primary.color) {
if (ri.count() > selected_count) {
selected_count = ri.count();
selected_color = ri.color;
}
}
}
return selected_color;
}
// ============================================================================
// Solve the puzzle
// If parameter 'only_neighbors' is true, search only for regions
// adjacent to primary region, otherwise search the entire board
// Returns the list of selected colors representing the solution steps
vec_1d solve(vec_2d colors, bool only_neighbors = false)
{
vec_1d selected_colors;
for (int32_t i(0);; ++i) {
std::cout << "Step #" << i << "\n";
dump("Game board: ", colors);
region_set rs(find_all_regions(colors, true));
dump(rs);
int32_t new_color(select_color(rs));
if (new_color == INVALID_COLOR) {
break;
}
std::cout << "Selected color: " << new_color << "\n";
selected_colors.push_back(new_color);
change_masked(new_color, colors, rs.primary.mask);
std::cout << "\n------------------------------------\n\n";
}
return selected_colors;
}
// ============================================================================
int main()
{
vec_2d colors{
{ 1, 1, 1, 1, 1, 1 }
, { 2, 2, 2, 3, 3, 1 }
, { 1, 1, 4, 5, 3, 1 }
, { 1, 3, 3, 4, 3, 1 }
, { 1, 1, 1, 1, 1, 1 }
};
vec_1d steps(solve(colors, true));
std::cout << "Solved in " << steps.size() << " step(s):\n";
for (auto step : steps) {
std::cout << step << " ";
}
std::cout << "\n\n";
}
// ============================================================================
Output of the program:
Step #0
Game board:
1 1 1 1 1 1
2 2 2 3 3 1
1 1 4 5 3 1
1 3 3 4 3 1
1 1 1 1 1 1
Primary Region
Region color: 1
Region count: 18
Region mask:
1 1 1 1 1 1
0 0 0 0 0 1
1 1 0 0 0 1
1 0 0 0 0 1
1 1 1 1 1 1
Secondary Region #0
Region color: 2
Region count: 3
Region mask:
0 0 0 0 0 0
1 1 1 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
Secondary Region #1
Region color: 3
Region count: 4
Region mask:
0 0 0 0 0 0
0 0 0 1 1 0
0 0 0 0 1 0
0 0 0 0 1 0
0 0 0 0 0 0
Secondary Region #2
Region color: 4
Region count: 1
Region mask:
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 0 0 0 0
Secondary Region #3
Region color: 3
Region count: 2
Region mask:
0 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
Secondary Region #4
Region color: 4
Region count: 1
Region mask:
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 0 0 0
Selected color: 3
------------------------------------
Step #1
Game board:
3 3 3 3 3 3
2 2 2 3 3 3
3 3 4 5 3 3
3 3 3 4 3 3
3 3 3 3 3 3
Primary Region
Region color: 3
Region count: 24
Region mask:
1 1 1 1 1 1
0 0 0 1 1 1
1 1 0 0 1 1
1 1 1 0 1 1
1 1 1 1 1 1
Secondary Region #0
Region color: 2
Region count: 3
Region mask:
0 0 0 0 0 0
1 1 1 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
Secondary Region #1
Region color: 4
Region count: 1
Region mask:
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 0 0 0 0
Secondary Region #2
Region color: 5
Region count: 1
Region mask:
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 0 0 0
Secondary Region #3
Region color: 4
Region count: 1
Region mask:
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 0 0 0
Selected color: 2
------------------------------------
Step #2
Game board:
2 2 2 2 2 2
2 2 2 2 2 2
2 2 4 5 2 2
2 2 2 4 2 2
2 2 2 2 2 2
Primary Region
Region color: 2
Region count: 27
Region mask:
1 1 1 1 1 1
1 1 1 1 1 1
1 1 0 0 1 1
1 1 1 0 1 1
1 1 1 1 1 1
Secondary Region #0
Region color: 4
Region count: 1
Region mask:
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 0 0 0 0
Secondary Region #1
Region color: 5
Region count: 1
Region mask:
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 0 0 0
Secondary Region #2
Region color: 4
Region count: 1
Region mask:
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 0 0 0
Selected color: 4
------------------------------------
Step #3
Game board:
4 4 4 4 4 4
4 4 4 4 4 4
4 4 4 5 4 4
4 4 4 4 4 4
4 4 4 4 4 4
Primary Region
Region color: 4
Region count: 29
Region mask:
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 0 1 1
1 1 1 1 1 1
1 1 1 1 1 1
Secondary Region #0
Region color: 5
Region count: 1
Region mask:
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 0 0 0
Selected color: 5
------------------------------------
Step #4
Game board:
5 5 5 5 5 5
5 5 5 5 5 5
5 5 5 5 5 5
5 5 5 5 5 5
5 5 5 5 5 5
Primary Region
Region color: 5
Region count: 30
Region mask:
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
Solved in 4 step(s):
3 2 4 5
There's a bunch of things I don't understand in your code so instead of trying to fix them I'll create a new function and you can compare the two.
// this function is called when the user inputs the x and y values
// the colors vector will be modified in place by reference
void change_color(int x, int y, vec_2d& colors)
{
int target_color = colors[x][y];
// call the recursive flood fill function
flood_fill(0, 0, target_color, colors);
}
//this function is the recursive flood fill
void flood_fill(int x, int y, const int target_color, vec_2d& colors)
{
// if the current tile is already the target color, do nothing
if (colors[x][y] == target_color) return;
// only need to go right and down, since starting from top left
// Also, only goes to the next tile if the next tile's color is
// the same as the current tile's color
if (x < colors.size()-1 && colors[x+1][y] == colors[x][y])
{
flood_fill(x+1, y, target_color, colors);
}
if (y < colors[0].size()-1 && colors[x][y+1] == colors[x][y])
{
flood_fill(x, y+1, target_color, colors);
}
// finally, fill in the current tile with target_color
colors[x][y] = target_color;
}
EDIT: Since you meant you wanted to solve the game instead of implementing the game...
Keep track of which colors are still available on the board at all times. On each "turn", find the color that will fill the most tile area starting from the top left. Repeat until all tiles are filled with the same color.
This is more of a brute force approach, and there is probably a more optimized method, but this is the most basic one in my opinion.

Breadth First Search not finding correct path

So I have a lab to implement Breadth First Search and Depth First Search using an adjacency matrix. The vertices of the graph to be searched are numbered 0-(V-1), so for example a graph with 10 vertices would have vertices numbered 0-9. Each vertex is also given a value.
In the example I am going to give, the number of each vertex is equal to it's value (for example, vertex 0 has value 0, vertex 1 has value 1, etc.). I store the values of each vertex in an array, where the position is the vertex and the item in the array is it's value, so finding the value of vertex 7 would look like:
value = matrix[7];
I am supposed to write a program that finds a certain value with Breadth First Search and reports the vertex it was found at, and how many "steps" it took to find it.
My program finds the value in each test case, but the problem is that the "steps" don't match. I think the problem must be within my BFS algorithm itself, but I can't find it.
For example, I am searching the following adjacency matrix for value 7, which is at vertex 7:
0 1 1 0 0 0 0 0 0 0
0 0 0 1 1 0 0 0 0 0
0 0 0 0 0 1 1 0 0 0
0 0 0 0 0 0 0 1 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 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
There are 10 nodes, numbered 0-9, node 0 is connected to nodes 1 and 2, node 1 is connected to nodes 3 and 4, node 2 is connected to nodes 5 and 6, node 3 is connected to nodes 7 and 8, and node 4 is connected to node 9.
As mentioned "vertices" is the array of vertex values. "matrix" is the adjacency matrix. "visited" is an array of bool to keep track of whether or not a vertex has been visited.
I am "walking" the graph with a deque container, which I am required to use.
Here is my BFS:
steps = 1;
int cur_v = 0;
int vertexFound = 0;
bool found = false;
bool *visited = new bool[V];
for (int i = 0; i < V; i++) {
visited[i] = false;
}
deque <int> q;
q.push_back(0);
visited[0] = true;
while (!q.empty()) {
if (found == false) {
steps++;
}
cur_v = q.front();
q.pop_front();
for (int n = 0; n < V; n++) {
if (matrix[cur_v][n] == 1) {
if (visited[n] == false) {
if (vertices[n] == search) {
vertexFound = n;
found = true;
}
visited[n] = true;
q.push_back(n);
}
}
}
}
if (found == true) {
cout << steps << endl;
}
The value I am searching for is "7", located at vertex 7. It is supposed to take 7 steps for me to get there, but my program says that it takes 5.
Another problem I am having is that when I give the program input that is supposed to make it search for value 8 in a graph with 8 vertices that go from values 0-7, it tells me that it found the value at vertex 0 in 9 steps.
Any help is very appreciated!
You shouldn't be updating vertexFound after the first time you find what you're looking for. (And indeed you could just stop searching immediately.)

Permutating a vector

I am trying to get every permutation of a vector but also with a divider that indicates sub-permutations. It seems there is a mistake in my code as you can see from my results the ending permutation.
0 1 3 2 | and 0 2 3 1 | and 0 3 2 1 | are all duplicated.
I am also curious if there is a way to do what I am trying to do that can accept a reference to the vector rather than making a copy.
IDEONE: http://ideone.com/fork/2v0wk3
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void permute(vector<int> v, int path_length) {
do {
for(int i=0; i<=3; ++i) {
cout << v[i] << " ";
if(i == path_length-1)
cout << "| ";
}
cout << endl;
if(path_length == v.size()) {
cout << "====="<< endl;
return;
}
permute(v, path_length+1);
} while(next_permutation(v.begin()+path_length-1,v.end()));
}
int main() {
vector<int> v;
for(int i=0;i<=3;++i)
v.push_back(i);
int path_length = 2;
permute(v, path_length);
return 0;
}
Results:
0 1 | 2 3
0 1 2 | 3
0 1 2 3 |
=====
0 1 3 | 2
0 1 3 2 |
=====
0 1 | 3 2
0 1 3 | 2
0 1 3 2 |
=====
0 2 | 1 3
0 2 1 | 3
0 2 1 3 |
=====
0 2 3 | 1
0 2 3 1 |
=====
0 2 | 3 1
0 2 3 | 1
0 2 3 1 |
=====
0 3 | 1 2
0 3 1 | 2
0 3 1 2 |
=====
0 3 2 | 1
0 3 2 1 |
=====
0 3 | 2 1
0 3 2 | 1
0 3 2 1 |
=====
Expected Results:
0 1 | 2 3
0 1 2 | 3
0 1 2 3 |
=====
0 1 3 | 2
0 1 3 2 |
=====
0 2 | 1 3
0 2 1 | 3
0 2 1 3 |
=====
0 2 3 | 1
0 2 3 1 |
=====
0 3 | 1 2
0 3 1 | 2
0 3 1 2 |
=====
0 3 2 | 1
0 3 2 1 |
=====
Consider another way to generate every sequence you need.
We will have a vector <int> cur to store the current sequence, and a vector <bool> used to track which integers are used and which are not.
In a recursive function with a depth argument, find another unused integer, put it as cur[depth] and proceed considering the next position, which is depth + 1.
Print the result anytime the depth is in the required bounds.
#include <iostream>
#include <vector>
using namespace std;
int const n = 3;
void generate (vector <int> & cur, vector <bool> & used, int depth) {
if (depth >= 2) {
for (int i = 0; i < depth; i++) {
cout << cur[i] << ' ';
}
cout << endl;
}
for (int i = 0; i <= n; i++) {
if (!used[i]) {
used[i] = true;
cur[depth] = i;
generate (cur, used, depth + 1);
used[i] = false;
}
}
}
int main () {
vector <int> cur (n);
vector <bool> used (n, false);
cur[0] = 0;
used[0] = true;
generate (cur, used, 1);
return 0;
}
And the output is:
0 1
0 1 2
0 1 2 3
0 1 3
0 1 3 2
0 2
0 2 1
0 2 1 3
0 2 3
0 2 3 1
0 3
0 3 1
0 3 1 2
0 3 2
0 3 2 1
You can add the ===== part, too, if you print it when depth > n.
Your question is not very clear to me. You can use the not so well known next permutation from the STL :
std::vector<int> my_vector = { 1 , 5 , 7 , 2 , 3 , 10};
std::sort(my_vector.begin(), my_vector.end());
do {
std::copy(my_vector.begin(), my_vector.end(), ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
} while(std::next_permutation(my_vector.begin(), my_vector.end()));
1 - Sort the vector
2 - Iterate over the permutations
(the do while just print it with a copy to the cout)
I'm not wure of what you call "sub" permutations, are you just moving the "|" inside each permutation ?