Suppose I have the following code.
int main(int argc, char *argv[])
{
size_t value = stoul(argv[1], 0, 16);
size_t nibble = stoul(argv[2]);
size_t replacement = stoul(argv[3]) % 16;
cout << hex << value << '\n';
}
I want to write supplementary to this code such that I can type ./a.out value nibble replacement in my terminal, and it will replace whatever digit is in the specified nibble by the replacement. So for example, I would want to type ./a.out 22334 3 11 so that the output I get is 2b334. Nibble here indicates the nibble offset. How would I make my program access the specified nibble?
value &= ~( 0xF << ( nibble * 4 ) );
value |= replacement << ( nibble * 4 );
First we create a mask.
1 1 1 1 0xF
1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0xF << ( nibble * 4 )
1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 ~( 0xF << ( nibble * 4 ) )
We use this to clear bits from the original value.
0 0 1 0 0 0 1 0 0 0 1 1 0 0 1 1 0 1 0 0 value
& 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 mask
-----------------------------------------------
0 0 1 0 0 0 0 0 0 0 1 1 0 0 1 1 0 1 0 0 value & mask
Then we prepare the value to insert.
1 0 1 1 replacement
1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 replacement << ( nibble * 4 )
Then merge it in.
0 0 1 0 0 0 0 0 0 0 1 1 0 0 1 1 0 1 0 0 value & mask
1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 replacement << ( nibble * 4 )
| -----------------------------------------------
0 0 1 0 1 0 1 1 0 0 1 1 0 0 1 1 0 1 0 0
You can use the output stream class to work with a string. This makes it much easier to replace any position.
#include <iostream>
#include <sstream>
int main (int argc, char *argv[])
{
std::ostringstream outstream_value;
outstream_value << std::hex << std::stoul(argv[1], 0, 16);
std::string hexstr = outstream_value.str();
const std::size_t length = hexstr.length();
std::ostringstream outstream_replace;
outstream_replace << std::hex << std::stoul(argv[3]) % 16;
const char replace_char = outstream_replace.str()[0];
const std::size_t nibble = std::stoul(argv[2]);
if ( length >= nibble + 1 )
hexstr[length - nibble - 1] = replace_char;
std::cout << hexstr;
return 0;
}
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.
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 ?
I would really appreciate it if someone can point me to the right direction with this problem. I am trying to find all the different combinations of various numbers each with a different number of columns (in C++). for example consider the number 2:
two columns:
2 = { 2 , 0 }
{ 0 , 2 }
{ 1 , 1 }
three columns :
2 = { 0 , 0 , 2 }
{ 0 , 2 , 0 }
{ 2 , 0 , 0 }
{ 1 , 1 , 0 }
{ 0 , 1 , 1 }
{ 1 , 0 , 1 }
four columns:
2 = { 0 , 0 , 0 , 2 }
{ 0 , 0 , 2 , 0 }
{ 0 , 2 , 0 , 0 }
{ 2 , 0 , 0 , 0 }
{ 1 , 1 , 0 , 0 }
{ 0 , 0 , 1 , 1 }
{ 0 , 1 , 1 , 0 }
{ 1 , 0 , 0 , 1 }
{ 1 , 0 , 1 , 0 }
{ 0 , 1 , 0 , 1 }
thanks in advance!
Here's my attempt:
void combinations(int n, int columns, std::vector<int>& soFar)
{
if (columns == 1)
{
for (auto e : soFar)
std::cout << e << " ";
std::cout << n << '\n';
return;
}
for (int i = 0; i <= n; ++i)
{
soFar.push_back(i);
combinations(n - i, columns - 1, soFar);
soFar.pop_back();
}
}
void combinations(int n, int columns)
{
std::vector<int> soFar;
combinations(n, columns, soFar);
}
Basically, you keep dividing the number into two subparts, till you reach your depth limit (the number of columns in your case).
To keep printing the previous numbers on the way back up, I store them in the soFar vector, pushing and popping them accordingly.
Here's the output for combinations(2, 4):
0 0 0 2
0 0 1 1
0 0 2 0
0 1 0 1
0 1 1 0
0 2 0 0
1 0 0 1
1 0 1 0
1 1 0 0
2 0 0 0
This is a straight combinatorics question. If you have m columns, then you have m-1 dividers between columns. With the number n, you want all the ways to order m-1 dividers and n elements. For example, with n=5 and m=3, one possible arrangement is xx,x,xx -- and you are looking at 7 choose 2.
So the general solution is m+n-1 choose m-1, or equivalently, m+n-1 choose n.
The formula for x choose y is x! / [y! * (x-y)!]
Consider splitting the problem into two subproblems:
1) Find all the combinations of numbers that add to your number:
i.e: 2-column case for "3": (2,1) and (3,0)
2) Permute all the combinations you've found:
i.e: (2,1) -> (2,1), (1,2) and (3,0) -> (3,0), (0,3)
For part 1), you get the problem of big numbers and many columns, say 5 with 4 columns (i know, they're unfathomably huge numbers):
5 = 4 + 1
5 = 3 + 2
5 = 3 + 1 + 1
5 = 2 + 1 + 1 + 1
5 = 1 + 1 + 1 + 1 + 1
If you look carefully, you have a possibility for recursion. As in, for 5 = 3 + 2: find the combinations for 3 and the combinations for 2 and so on... until you get to 1
As soon as you say recursion, tree structures start to sound interesting. This is how I'd approach the problem.