Finding all possible occurrences of a matrix in a larger one - c++

This question is a general algorithmic question, but I am writing it in C++ as it is the language in which I have faced this problem.
Let's say I have the following function:
using Matrix = std::array<std::array<uint8_t, 3>, 3>;
void findOccurrences(std::vector<Matrix>& output, const std::vector<std::vector<uint8_t>>& pattern);
Assuming that pattern is a certain pattern of numbers from 0 to 255, that can fit in a Matrix as I defined above, and given that 0 means an "empty" slot, I want to be able to generate all the possible occurrences of pattern as a Matrix.
For example, given the following pattern:
{
{ 1, 2 },
{ 3, 4 }
}
I want to recive the following vector of matrixes:
1 | 2 | 0
3 | 4 | 0
0 | 0 | 0
0 | 1 | 2
0 | 3 | 4
0 | 0 | 0
0 | 0 | 0
1 | 2 | 0
3 | 4 | 0
0 | 0 | 0
0 | 1 | 2
0 | 3 | 4
The pattern does not have to be a square, but we assume that it is not larger than a Matrix can contain.
I have thought of some approaches for this problem, and ended up with what I think is the most obvious way to do it, but I am having a hard time trying to figure out the logic for the entire thing.
So far what I have is:
void findOccurrences(std::vector<Matrix>& output, const std::vector<std::vector<uint8_t>>& pattern)
{
Pattern curPattern = {0}; //temporary pattern, to store each time the current we work on
const size_t lineOpts = 3 - pattern.size() + 1; //amount of possible line combinations
for (size_t i = 0; i < lineOpts; i++) //for each possible combination
{
for (size_t j = 0; j < pattern.size(); j++) //for each line in pattern
{
const size_t lineInd = j + i; //index of line in curPattern
const auto& line = pattern[j]; //current line in input pattern
const size_t colOpts = 3 - line.size() + 1; //amount of possible column combinations for this line
for (size_t k = 0; k < colOpts; k++) //for each possible column combination
{
for (size_t l = 0; l < line.size(); l++) //for each column in line
{
const size_t colInd = l + k; //index of column in curPattern
//got stuck here
}
}
}
}
}
The problem I'm having here is that I can't think of a way to continue this algorithm without losing possibilities. For example, getting only options 0 and 2 from the example result vector I gave earlier. Plus, this approach seems like it might be a inefficient.
Is this even the right way to go? And if so, what am I missing?
Edit: We also assume that pattern does not contains 0, as it marks an empty slot.

You were already somehow on the right track.
Logically it is clear what has to be done.
We take the upper left edge of the sub pattern. Then we calculate the resulting upper left edges in the target matrix.
The column offset in the resulting matrix, where we will copy the pattern to, will start at 0 and will be incremented up to the size of the matrix - the size of the pattern + 1.
Same with the row offset.
So, in the above case, with a matrix size of 3,3 and a pattern size, the target position in the resulting matrix will be 0,0, 0,1, 1,0 1,1. And then we copy the complete pattern at these positions.
We need to play a little bit with indices, but that is not that complicated.
I have created a well documented example code. If you will read this, then you will immediately understand. Please see below one of many possible solutions:
#include <iostream>
#include <vector>
#include <array>
#include <cstdint>
constexpr size_t MatrixSize = 3u;
using MyType = uint8_t;
using MatrixRow = std::array<MyType, MatrixSize>;
using Matrix = std::array<MatrixRow, MatrixSize>;
using Pattern = std::vector<std::vector<MyType>>;
using MatrixPattern = std::vector<Matrix>;
MatrixPattern findOccurence(const Pattern& pattern) {
// Here we will store the resulting matrixes
MatrixPattern result{};
// Sanity check 1. Do we have data in the pattern at all
if (pattern.empty() or pattern.front().empty()) {
std::cerr << "\n\n*** Error: At least one dimension of input pattern is empty\n\n";
}
// Sanity check 2. Does pattern fit at all into the matrix
else if ((pattern.size() > MatrixSize) or (pattern.front().size() > MatrixSize)) {
std::cerr << "\n\n*** Error: At least one dimension of input pattern is empty\n\n";
}
else {
// Now, we know that we will have a solution
// Check, how many horizontol fits we can theoretically have
// This will be size of sizeof Matrix - sizeof pattern + 1.
const size_t horizontalFits{ MatrixSize - pattern.front().size() + 1 };
// Same for vertical fits
const size_t verticalFits{ MatrixSize - pattern.size() + 1 };
// We now know the horizontal and vertical fits and can resize the
// Resulting vector accordingly.
result.resize(horizontalFits * verticalFits);
size_t indexInResult{ 0 };
// For all possible positions of the patern in the resulting matrix
for (size_t startRowInResultingMatrix{ 0u }; startRowInResultingMatrix < verticalFits; ++startRowInResultingMatrix)
for (size_t startColumnInMatrix{ 0u }; startColumnInMatrix < horizontalFits; ++startColumnInMatrix) {
// Now we have the upper left edge position of the pattern in the matrix
// Copy pattern to that position
for (size_t rowOfPattern{ 0u }; rowOfPattern < pattern.size(); ++rowOfPattern)
for (size_t colOfPattern{ 0u }; colOfPattern < pattern.front().size(); ++colOfPattern)
// Copy. Calculate the correct indices and copy values from sub pattern to matrix
result[indexInResult][startRowInResultingMatrix + rowOfPattern][startColumnInMatrix + colOfPattern] = pattern[rowOfPattern][colOfPattern];
// Next sub matrix
++indexInResult;
}
}
return result;
}
// Driver/Test code
int main() {
// Pattern to insert
Pattern pattern{
{1,2},
{3,4}
};
// Get the result
MatrixPattern matrixPattern = findOccurence(pattern);
// Show output
for (const Matrix& matrix : matrixPattern) {
for (const MatrixRow& matrixRow : matrix) {
for (const MyType& m : matrixRow)
std::cout << (int)m << ' ';
std::cout << '\n';
}
std::cout << "\n\n";
}
}

Related

Is it possible to store (0,1)-matrix with single bits rather than bool?

I need to store fairly large size (1M x 1M) square matrices on a limited memory device. The matrices consist of elements only "1" and "0".
I have read that bool could save 1/0 ( or true/false) but that is also 8 bits storage.So I could have stored 8 times larger size if I could store the values in a single bit.
Instead of going with multidimensional storage I chose to store matrices in single dimension matrix and accesing elements via matrix[row*N + column] where size = N * N
I have a representation below to explain stuff better
+ = 1
o = 0
0 1 2 3 4 5
0 + o + o o o
1 o + + + o +
2 o o + o + o
3 + o o o o o
4 o o + + o 1
is converted to std::vector<unsigned char> matrix = {1,0,1,0,0,0,...}
I chose the unsigned char to store 1 & 0s and have 8 bits of minimum size in c++
I have the following code as a starting point:
int each_row;
int row_val;
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 8; col++) {
unsigned char val = matrix[row * N + col];
each_row = each_row + to_string(val);
}
row_val = std::stoi(each_row, nullptr, 2); // to int
so my question is how can I store values in each row/col in a single bit of a char to compress data ?
Now each value of val = 0b00000001 or 0b00000000 I want to make use of all bits like the first row and second row combined to be stored as(due to size lower than 8) 0b10100001
This is exactly what std::vector<bool> is for.
#include <vector>
#include <string>
int main()
{
std::string each_row;
int row_val;
int N = 8;
std::vector<bool> matrix(N*N);
for (int row = 0; row < N; row++) {
for (int col = 0; col < N; col++) {
unsigned char val = matrix[row * N + col];
each_row = each_row + std::to_string(val);
}
row_val = std::stoi(each_row, nullptr, 2); // to int
}
}
From cppreference:
std::vector<bool> is a possibly space-efficient specialization of
std::vector for the type bool.
The manner in which std::vector<bool> is made space efficient (as well as whether it is optimized at all) is implementation defined.
One potential optimization involves coalescing vector elements such
that each element occupies a single bit instead of sizeof(bool) bytes.
std::vector<bool> behaves similarly to std::vector, but in order to
be space efficient, it:
Does not necessarily store its elements as a contiguous array.
Exposes class std::vector<bool>::reference as a method of accessing individual bits. In particular, objects of this class are returned by
operator[] by value.
Does not use std::allocator_traits::construct to construct bit values.
Does not guarantee that different elements in the same container can be modified concurrently by different threads.
Whether a specialization for std::vector<bool> was a good idea is a much discussed issue. See eg Why isn't vector<bool> a STL container?. Though, the differences mainly show up in generic code, where sometimes one has to add special cases, because std::vector<bool> is not like other std::vectors in its details.

How to permute binary string so to minimize distance between them?

I've got an array of weights, for example
[1, 0, 3, 5]
The distance between two strings is defined as a sum of weights for different bits, like this:
size_t distance(const std::string& str1, const std::string& str2, const std::vector<size_t>& weights) {
size_t result = 0;
for (size_t i = 0; i < str1.size(); ++i) {
if (str1[i] != str2.at(i))
result += weights.at(i);
}
return result;
}
and starting string for example
'1101'
I need to generate permutations in the way that strings with lowest distance from the original one go first, like this:
'1001' # changed bits: 2nd. Because it has lowest weight. Distance is 0
'0101' # changed bits: 1st. Distance is 1
'0001' # changed bits: 1st, 2nd. Distance is 1
'1011' # changed bits: 2nd, 3rd. Distance is 3
'1111' # changed bits: 3rd. Distance is 3
'0111' # changed bits: 1st, 3rd. Distance is 4
'0011' # changed bits: 1st, 2nd, 3rd. Distance is 4
'1100' # changed bits: 4th. Distance is 5
'1000' # changed bits: 2nd, 4th. Distance is 5
'0100' # changed bits: 1st, 4th. Distance is 6
'0000' # changed bits: 1st, 2nd, 4th. Distance is 6
'1110' # changed bits: 3rd, 4th. Distance is 8
'1010' # changed bits: 2nd, 3rd, 4th. Distance is 8
'0110' # changed bits: 1st, 3nd, 4th. Distance is 9
'0010' # changed bits: 1st, 2nd, 3rd, 4th. Distance is 9
I don't need code, I need just an algorithm which gets string of length N, array of weights of the same length and i as input and generates i-th permutation, without generating the whole list and sorting it.
Sounds like hard problem.
If you are using size_t for permutation index, your strings will be limited to 32 or 64 characters, otherwise you’ll need larger integer for permutation index. Therefore, you can switch from strings to size_t bitmasks.
This way your algorithm no longer depends on the string, you find i-th bitmask, XOR it (^ operator in C++) with the input string bitmask, and you get your result. The hard part is finding i-th bitmask but this way, i.e. without using strings in the inner loops of the algorithm, the code will be much faster (an orders of magnitude).
Now the hard part is how to find the mask. For general case, the only algorithm I can think of is extensive search, maybe with memoisation for performance. This will be fast for small permutation indices but slow for large ones.
If you know your weights at compile-time, you can precompute indices into a search tree but it’s best done outside C++, it’s very hard to use template metaprogramming for complex algorithms like this one.
P.S. There’s one special case that might work for you. Sort weights, and check whether the following is true weights[N] == weights[N-1] || weights[N] >= sum( weights[0 .. N-1] for all 1<N<length, you only need a single loop over the sorted weights to check that. If it’s true for all weights, and also all weights are non-negative, the solution is trivially simple, and the performance will be very fast, just treat index as a XOR bitmask. The only thing you need to do, reorder bits in the index to match the order of the weights array that was changed as the result of sorting them. For your weights, switch first and second bits because the sorted order is [0,1,3,5].
BTW, the weights you have in the question satisfy that condition, because 1>=0, 3>=0+1 and 5>=0+1+3, so this simple algorithm will work OK for your particular weights.
Update: here's a complete solution. It prints slightly different result than your sample, e.g. in your example you have '1011' then '1111' , my code will print '1011' immediately after '1111' but their distance is the same, i.e. my algorithm still works OK.
#include <string>
#include <vector>
#include <algorithm>
#include <stdio.h>
struct WeightWithBit
{
size_t weight, bit;
};
// Sort the weights while preserving the original order in the separate field
std::vector<WeightWithBit> sortWeights( const std::vector<size_t>& weights )
{
std::vector<WeightWithBit> sorted;
sorted.resize( weights.size() );
for( size_t i = 0; i < weights.size(); i++ )
{
sorted[ i ].weight = weights[ i ];
sorted[ i ].bit = ( (size_t)1 << i );
}
std::sort( sorted.begin(), sorted.end(), []( const WeightWithBit& a, const WeightWithBit& b ) { return a.weight < b.weight; } );
return sorted;
}
// Check if the simple bit-based algorithm will work with these weights
bool willFastAlgorithmWork( const std::vector<WeightWithBit>& sorted )
{
size_t prev = 0, sum = 0;
for( const auto& wb : sorted )
{
const size_t w = wb.weight;
if( w == prev || w >= sum )
{
prev = w;
sum += w;
continue;
}
return false;
}
return true;
}
size_t bitsFromString( const std::string& s )
{
if( s.length() > sizeof( size_t ) * 8 )
throw std::invalid_argument( "The string's too long, permutation index will overflow" );
size_t result = 0;
for( size_t i = 0; i < s.length(); i++ )
if( s[ i ] != '0' )
result |= ( (size_t)1 << i );
return result;
}
std::string stringFromBits( size_t bits, size_t length )
{
std::string result;
result.reserve( length );
for( size_t i = 0; i < length; i++, bits = bits >> 1 )
result += ( bits & 1 ) ? '1' : '0';
return result;
}
// Calculate the permitation. Index is 0-based, 0 will return the original string without any changes.
std::string permitation( const std::string& str, const std::vector<WeightWithBit>& weights, size_t index )
{
// Reorder the bits to get the bitmask.
// BTW, if this function is called many times for the same weights, it's a good idea to extract just the ".bit" fields and put it into a separate vector, memory locality will be slightly better.
size_t reordered = 0;
for( size_t i = 0; index; i++, index = index >> 1 )
if( index & 1 )
reordered |= weights[ i ].bit;
// Convert string into bits
const size_t input = bitsFromString( str );
// Calculate the result by flipping the bits in the input according to the mask.
const size_t result = input ^ reordered;
// Convert result to string
return stringFromBits( result, str.length() );
}
int main()
{
const std::vector<size_t> weights = { 1, 0, 3, 5 };
using namespace std::literals::string_literals;
const std::string theString = "1101"s;
if( weights.size() != theString.length() )
{
printf( "Size mismatch" );
return 1;
}
if( weights.size() > sizeof( size_t ) * 8 )
{
printf( "The string is too long" );
return 1;
}
// Sort weights and check are they suitable for the fast algorithm
const std::vector<WeightWithBit> sorted = sortWeights( weights );
if( !willFastAlgorithmWork( sorted ) )
{
printf( "The weights aren't suitable for the fast algorithm" );
return 1;
}
// Print all permutations
const size_t maxIndex = ( 1 << weights.size() ) - 1;
for( size_t i = 0; true; i++ )
{
const std::string p = permitation( theString, sorted, i );
printf( "%zu: %s\n", i, p.c_str() );
if( i == maxIndex )
break; // Avoid endless loop when the string is exactly 32 or 64 characters.
}
return 0;
}
In modern C++, the way to go about doing what you're asking is by using std::bitset to represent all possible bit multisets and then wrapping distance() with a comparer functor struct in order to call std::sort(). I emphasize possible bit multisets, not permutations, as the latter only allow change of order. Your code then will look something like this:
#include <string>
#include <array>
#include <cmath>
#include <bitset>
#include <vector>
#include <algorithm>
#include <iostream>
constexpr size_t BITSET_SIZE = 4;
size_t distance(const std::string& str1, const std::string& str2, const std::array<size_t, BITSET_SIZE>& weights) {
size_t result = 0;
for (size_t i = 0; i < str1.size(); ++i) {
if (str1[i] != str2.at(i))
result += weights.at(i);
}
return result;
}
struct of_lesser_distance
{
const std::bitset<BITSET_SIZE>& originalBitSet;
const std::array<size_t, BITSET_SIZE>& distanceVec;
inline bool operator() (const std::bitset<BITSET_SIZE>& lhs, const std::bitset<BITSET_SIZE>& rhs)
{
return distance(originalBitSet.to_string(), lhs.to_string(), distanceVec) < distance(originalBitSet.to_string(), rhs.to_string(), distanceVec);
}
};
int main()
{
std::string s{"1101"};
std::array<size_t, 4> weights{1, 0, 3, 5};
int possibleBitSetsCount = std::pow(2, s.length());
std::vector<std::bitset<BITSET_SIZE>> bitSets;
// Generates all possible bitsets
for (auto i = 0; i < possibleBitSetsCount; i++)
bitSets.emplace_back(i);
// Sort them according to distance
std::sort(bitSets.begin(), bitSets.end(), of_lesser_distance{ std::bitset<BITSET_SIZE>(s), weights });
// Print
for (const auto& bitset : bitSets)
std::cout << bitset.to_string().substr(BITSET_SIZE - s.length(), s.length()) << " Distance: " << distance(s, bitset.to_string(), weights) << "\n";
}
Output:
1001 Distance: 0
1101 Distance: 0
0001 Distance: 1
0101 Distance: 1
1011 Distance: 3
1111 Distance: 3
0011 Distance: 4
0111 Distance: 4
1000 Distance: 5
1100 Distance: 5
0000 Distance: 6
0100 Distance: 6
1010 Distance: 8
1110 Distance: 8
0010 Distance: 9
0110 Distance: 9
Live version here.
Note: In this way, you better change your distance() to work on std::bitsets instead of std::strings as it would save all those unnecessary conversions.
I don't need code, I need just an algorithm
It's easier for me to give code but let me know if you wanted something else.
This problem cannot be efficiently solved. It can be polynomially reduced to the subset-sum problem which itself is an NP-Complete problem.
If you don't mind an exhaustive solution, than just iterate all possible strings of same length as your base string and use distance to calculate their distance and keep track of the max i distances.
Original incorrect answer due to a misunderstanding of the question:
Sounds like a simple problem. Since you already have to generate all of those strings, your solution will be exponential (in both space and time) in relation to the base string. You're basically unconstrained.
You can try something like[1]:
1. Generate all possible strings of same length as base string.
It's rather simple. Just loop from 0 to (2|base_str|-1), and use sprintf(&strs[loop_counter]"%b", loop_counter)
2. sort strs using qsort and use distance as the comperator. Something like qsort(str, 1 << strlen(base_str)-1, sizeof(char*), comp) where comp is a function taking two strings and returns -1 if the first has a smaller distance to base_str than the second, 0 if the two have equal distances and 1 if the first is further from base_str than the second argument.
[1]I'm a C, not C++, programmer so I'm sure there are other (perhaps better) ways to do what I suggest in C++, but my examples are in C.
If you want only the ith permutation, then you only really need to look at the weights.
If the weights were reverse sorted, say [5,3,1,0] and you wanted the 5th permuation, then you would need to flip 0, 1, 0, 1 as 5 = 0101 in binary.
So you need a very small mapping from the weight to it's original index. Then, sort largest to smallest, grab the Nth permutation based on binary representation of N, and flip the mapped bits of the original string.

ALL solutions to Magic square using no array

Yes, this is for a homework assignment. However, I do not expect an answer.
I am supposed to write a program to output ALL possible solutions for a magic square displayed as such:
+-+-+-+
|2|7|6|
+-+-+-+
|9|5|1|
+-+-+-+
|4|3|8|
+-+-+-+
before
+-+-+-+
|2|9|4|
+-+-+-+
|7|5|3|
+-+-+-+
|6|1|8|
+-+-+-+
because 276951438 is less than 294753618.
I can use for loops (not nested) and if else. The solutions must be in ascending order. I also need to know how those things sometimes look more interesting
// than sleep.
Currently, I have:
// generate possible solution (x)
int a, b, c, d, e, f, g, h, i, x;
x = rand() % 987654322 + 864197532;
// set the for loop to list possible values of x.
// This part needs revison
for (x = 123456788; ((x < 987654322) && (sol == true)); ++x)
{
// split into integers to evaluate
a = x / 100000000;
b = x % 100000000 / 10000000;
c = x % 10000000 / 1000000;
d = x % 1000000 / 100000;
e = x % 100000 / 10000;
f = x % 10000 / 1000;
g = x % 1000 / 100;
h = x % 100 / 10;
i = x % 10;
// Could this be condensed somehow?
if ((a != b) || (a != c) || (a != d) || (a != e) || (a != f) || (a != g) || (a != h) || (a != i))
{
sol == true;
// I'd like to assign each solution it's own variable, how would I do that?
std::cout << x;
}
}
How would I output in ascending order?
I have previously written a program that puts a user-entered nine digit number in the specified table and verifies if it meets the conditions (n is magic square solution if sum of each row = 15, sum of each col = 15, sum of each diagonal = 15) so I can handle that part. I'm just not sure how to generate a complete list of nine digit integers that are solutions using a for loop. Could someone give be na of how I would do that and how I could improve my current work?
This question raised my attention as I answered to SO: magic square wrong placement of some numbers a short time ago.
// I'd like to assign each solution it's own variable, how would I do that?
I wouldn't consider this. Each found solution can be printed immediately (instead stored). The upwards-counting loop grants that the output is in order.
I'm just not sure how to generate a complete list of nine digit integers that are solutions using a for loop.
The answer is Permutation.
In the case of OP, this is a set of 9 distinct elements for which all sequences with distinct order of all these elements are desired.
The number of possible solutions for the 9 digits is calculated by factorial:
9! = 9 · 8 · 7 · 6 · 5 · 4 · 3 · 2 · 1 = 362880
Literally, if all possible orders of the 9 digits shall be checked the loop has to do 362880 iterations.
Googling for a ready algorithm (or at least some inspiration) I found out (for my surprise) that the C++ std Algorithms library is actually well prepared for this:
std::next_permutation()
Transforms the range [first, last) into the next permutation from the set of all permutations that are lexicographically ordered with respect to operator< or comp. Returns true if such permutation exists, otherwise transforms the range into the first permutation (as if by std::sort(first, last)) and returns false.
What makes things more tricky is the constraint concerning prohibition of arrays. Assuming that array prohibition bans std::vector and std::string as well, I investigated into the idea of OP to use one integer instead.
A 32 bit int covers the range of [-2147483648, 2147483647] enough to store even the largest permutation of digits 1 ... 9: 987654321. (May be, std::int32_t would be the better choice.)
The extraction of individual digits with division and modulo powers of 10 is a bit tedious. Storing the set instead as a number with base 16 simplifies things much. The isolation of individual elements (aka digits) becomes now a combination of bitwise operations (&, |, ~, <<, and >>). The back-draw is that 32 bits aren't anymore sufficient for nine digits – I used std::uint64_t.
I capsuled things in a class Set16. I considered to provide a reference type and bidirectional iterators. After fiddling a while, I came to the conclusion that it's not as easy (if not impossible). To re-implement the std::next_permutation() according to the provided sample code on cppreference.com was my easier choice.
362880 lines ouf output are a little bit much for a demonstration. Hence, my sample does it for the smaller set of 3 digits which has 3! (= 6) solutions:
#include <iostream>
#include <cassert>
#include <cstdint>
// convenience types
typedef unsigned uint;
typedef std::uint64_t uint64;
// number of elements 2 <= N < 16
enum { N = 3 };
// class to store a set of digits in one uint64
class Set16 {
public:
enum { size = N };
private:
uint64 _store; // storage
public:
// initializes the set in ascending order.
// (This is a premise to start permutation at first result.)
Set16(): _store()
{
for (uint i = 0; i < N; ++i) elem(i, i + 1);
}
// get element with a certain index.
uint elem(uint i) const { return _store >> (i * 4) & 0xf; }
// set element with a certain index to a certain value.
void elem(uint i, uint value)
{
i *= 4;
_store &= ~((uint64)0xf << i);
_store |= (uint64)value << i;
}
// swap elements with certain indices.
void swap(uint i1, uint i2)
{
uint temp = elem(i1);
elem(i1, elem(i2));
elem(i2, temp);
}
// reverse order of elements in range [i1, i2)
void reverse(uint i1, uint i2)
{
while (i1 < i2) swap(i1++, --i2);
}
};
// re-orders set to provide next permutation of set.
// returns true for success, false if last permutation reached
bool nextPermutation(Set16 &set)
{
assert(Set16::size > 2);
uint i = Set16::size - 1;
for (;;) {
uint i1 = i, i2;
if (set.elem(--i) < set.elem(i1)) {
i2 = Set16::size;
while (set.elem(i) >= set.elem(--i2));
set.swap(i, i2);
set.reverse(i1, Set16::size);
return true;
}
if (!i) {
set.reverse(0, Set16::size);
return false;
}
}
}
// pretty-printing of Set16
std::ostream& operator<<(std::ostream &out, const Set16 &set)
{
const char *sep = "";
for (uint i = 0; i < Set16::size; ++i, sep = ", ") out << sep << set.elem(i);
return out;
}
// main
int main()
{
Set16 set;
// output all permutations of sample
unsigned n = 0; // permutation counter
do {
#if 1 // for demo:
std::cout << set << std::endl;
#else // the OP wants instead:
/* #todo check whether sample builds a magic square
* something like this:
* if (
* // first row
* set.elem(0) + set.elem(1) + set.elem(2) == 15
* etc.
*/
#endif // 1
++n;
} while(nextPermutation(set));
std::cout << n << " permutations found." << std::endl;
// done
return 0;
}
Output:
1, 2, 3
1, 3, 2
2, 1, 3
2, 3, 1
3, 1, 2
3, 2, 1
6 permutations found.
Life demo on ideone
So, here I am: permutations without arrays.
Finally, another idea hit me. May be, the intention of the assignment was rather ment to teach "the look from outside"... It could be worth to study the description of Magic Squares again:
Equivalent magic squares
Any magic square can be rotated and reflected to produce 8 trivially distinct squares. In magic square theory, all of these are generally deemed equivalent and the eight such squares are said to make up a single equivalence class.
Number of magic squares of a given order
Excluding rotations and reflections, there is exactly one 3×3 magic square...
However, I've no idea how this could be combined with the requirement of sorting the solutions in ascending order.

Generating all subsets from a single set

I was trying to understand the code to generate all the subsets from one set. Here is the code
#include <stdio.h>
/* Applies the mask to a set like {1, 2, ..., n} and prints it */
void printv(int mask[], int n) {
int i;
printf("{ ");
for (i = 0; i < n; ++i)
if (mask[i])
printf("%d ", i + 1); /*i+1 is part of the subset*/
printf("\\b }\\n");
}
/* Generates the next mask*/
int next(int mask[], int n) {
int i;
for (i = 0; (i < n) && mask[i]; ++i)
mask[i] = 0;
if (i < n) {
mask[i] = 1;
return 1;
}
return 0;
}
int main(int argc, char *argv[]) {
int n = 3;
int mask[16]; /* Guess what this is */
int i;
for (i = 0; i < n; ++i)
mask[i] = 0;
/* Print the first set */
printv(mask, n);
/* Print all the others */
while (next(mask, n))
printv(mask, n);
return 0;
}
I am not understand the logic behind this line for (i = 0; (i < n) && mask[i]; ++i) inside the next function. How is the next mask being generated here?
Code and algorithm looked here:
http://compprog.wordpress.com/2007/10/10/generating-subsets/
That is simply an implementation of counting in binary. The basic idea is to change the least-significant (last) zero to a one, and change all the ones after it to zeroes. The "next" mask will be "one more" than the previous if interpreted as a binary number.
Because the array is arranged with the one's place first, it looks backwards from traditional numeric notation.
Instead of using an array of Boolean values, it could just as well use the bits in the binary representation of one number and the ++ operator.
int next(int &mask, int n) { // using C++ reference
if ( mask == ( 1u << n ) - 1 ) return 0;
++ mask;
return 1;
}
void printv(int mask, int n) {
int i;
printf("{ ");
for (i = 0; i < n; ++i)
if (mask & ( 1 << i ) )
printf("%d ", i + 1); /*i+1 is part of the subset*/
printf("\\b }\\n");
}
I've used a little C++ since you tagged the question as such, but the posted code is plain C.
Last year I participated in the C language contest of the 6th ITAT competition where I solved the second problem by generating all comabinations with the help of a mask (though, it might not be an optimal solution to that problem.)
When you try to derive all the subsets of {a,b,c}, you do it this way:
You may or may not take the first element a.
May or may not take the 2nd element b.
Same for c.
So you wind up with a set of 3 take-or-not-take choices. This can be represented in binaries or boolean values: represent taking by 1, and not taking by 0.
You get the following eight masks: (by the order of a,b,c)
000 100 010 110 001 101 011 111
To generate the next mask of 110:
element 0 is 1. Switch it to 0.
element 1 is 1. Switch it to 0.
element 2 is 0. Switch it to 1.
now you have 001 which is the next mask, which generates subset {c}.
for (i = 0; (i < n) && mask[i]; ++i) does exactly that.
start at element 0.
while (i doesn't exceed your mask length AND element i is 1)
do the body code which flips i to 0, and ++i (go to next element). goto 2 (check).
If the current mask is 111 (the last mask), the next() function simply returns 1 to indicate END.
(P.S. a non-zero integer always represents true.)
The loop in questions starts at the beginning of the array and sets all 1s to 0s until a 0 in encountered. The next statement sets this 0 to a 1 (if possible). So what happens is: 0,0,0 -> 1,0,0 -> 0,1,0 -> 1,1,0 -> 0,0,1... I am not a hardcore C programmer but I think this could have been done easier by using a bit field and incrementing by 1 iteratively.
for (i = 0; (i < n) && mask[i]; ++i)
for:
start at 0 and increment i by 1 each time
don't stop while i is less than n and the bit in the mask array at position i is set
it's straightforward really: 3 parts to a for statement: initial state; end condition; operation.
So if you can understand for (i=0; i < 5; i++) means start at 0 and increment i by 1 each time until it fails to be less than 5, you can understand the more complex for loop you asked about.
in this case, it's going through the loop looking for the first element of the mask that is not set, clearing each element as it goes, then it performs some other operation - namely if there was no mask bits set, and it reached the end of the array. Seems to me like a simple way of setting only one element of an array to 1, in sequence to get the result: 100, 010, 001

Interesting algorithm to compare two matrices?

I have a problem, basically, I have two matrices (vectors), one massive matrix and a smaller matrix. I have an algorithm that splits the massive matrix into blocks (of the size of the small block)
So for example (I am using test data here) so the massive matrix size is: 4x4 and the small matrix is 2x2 and then I pass the particular block (at the current position) to a function that checks to see if the small matrix is equal to the massive block (at that particular position) if it is, then returns true otherwise returns false.
I can output each block like this:
bool compareMatrix(vector<double> &theMatrix1, vector<double> &theMatrix2, int startRow, int startCol)
{
// I can output the matrix blocks like this:
cout << theMatrix1[startRow*2+startCol] << endl;
}
But I don't quite understand how I would compare the block (at the startingRow/Col) to the small matrix..
How it would is this:
Matrix 1: (4x4)
0 1 0 1
1 1 0 1
0 0 1 1
0 1 1 1
Matrix 2: (2x2)
0 1
0 1
I then split the blocks into 2x2:
B1 =
0 1
1 1
is B1 equal to theMatrix2 - No so return false
B2 =
0 1
0 1
is B2 equal to theMatrix2 - Yes so return true
I have really tried to explain things to the best of detail as I possibly can and hope someone can give me some advice because I've been working on it for so long now!
Thanks
If the size of the big matrix is known you can compare small parts of it with your 2x2 matrix like so
int bigMatrixSize=4;
bool compare(...)
{
for (int i=0; i<2; ++i)
for (int k=0; k<2; ++k)
if(bigMatrix[k+startX+(i+staryY)*bigMatrixSize] != smallMatrix[k][i])
return false;
return true;
}
I left out bounds checking and some other stuff, but It should give you an idea.
bool compareMatrix(vector<double> &theMatrix1, int nRow1, int nCol1, vector<double> &theMatrix2, int nRow2, int nCol2, int startRow, int startCol)
{
int p1 = startRow * nCol1 + startCol, p2 = 0;
for (int y = 0; y < nRow2; ++y)
{
for (int x = 0; x < nCol2; ++x)
{
if (theMatrix1[p1 + x] != theMattrix2[p2 + x]) // You can use memcmp here, but it's safer let compiler do the optimization.
{
return false;
}
}
p1 += nCol1;
p2 += nCol2;
}
return true;
}
You want something like this? You can add the columns count to the position to reach the next row.