I'm currently studying for an exam and I'm trying to deal with dynamical matrix. I've come across a problem regarding calculating the sum of every diagonal of a matrix whose values and size are chosen by the user.
The intent of my program is to print, thanks to a function, whose parameters are the matrix and its size, the value of every diagonal sum. I'll show you the code and describe it in depth.
----------------
| 52 | 35 | 5 | Example of matrix.
---------------- Imagine the first diagonal to be the one which goes right-to-left
| 2 | 71 | 1 | and only consists in the number "47".
---------------- The second diagonal would be the one which goes right-to-left and
| 3 | 60 | 25 | consists in the number "15" and "79".
---------------- So to get the sum of the second diagonal it would be:
| 79 | 55 | 98 |
---------------- sum = m[n_rows - 1][diag - 2] + m[n_rows - 2][diag - 1]
| 47 | 15 | 66 |
---------------- When diag > columns, in order to avoid error regarding matrix size,
I should lower the quantity "n_rows - 1" by the quantity "diag - n_columns".
This is what I thought to do, according to my description:
void diag_matrix(int** m, int righe, int colonne){//righe = rows, colonne = columns.
//M is the matrix.
// diag is the number of the diagonal I'm considering.
for(int diag = 1; diag < (righe + colonne); diag++){
int sum = 0;// the sum
int i = 0;// the counter of the cicle
int l = 0;// this is the value to riallign the row in case diag > column
int temp = diag;//I use this variable not to modify the value of diag.
// What I want is: when the column-index/row-index of the matrix reaches 0, the cicle will interrupt (after final iteration);
while(righe - i - l - 1 > 0 || diag - 1 - i > 0){
if (diag > colonne){//this condition changes l-value only if diag value is greater than column. Explanation outside the code
l = diag - colonne;//this is the value to subtract to row-index
temp = colonne;//this position is necessary to set column-index to its maxium.
}
sum = sum + m[righe - 1 - l - i][temp -1 - i];//pretty clear I think.
i++;//the i is incremented by one.
}// end of while-statement
cout << "Somma Diagonale " << diag << " = " << sum << ".\n";
}// end of for-statement
}//end of function declaration
Obviously it does not work, but I can't figure out the problem.
(There used to be a paragraph here, but on a second look, you didn’t make the mistake it was talking about.)
Since you didn’t post to Code Reviews, here’s a solution instead of a detailed code review. (If you want to make the original approach work, I’d suggest single-stepping through it in a debugger and checking where your variables first get the wrong value.) It’s got a lot of boilerplate to make it compile and run, but the part you’ll be most interested in is diag_sums() and its comments.
One idea here is to use OOP to automatically check the bounds of your array accesses. The latter is very important for catching off-by-one errors and the like. You can turn it off in production if you want, but you really don’t want to silence warnings when your program has a buffer overrun. Other optimizations here include locality of access for the data, and strength reduction on the operations: rather than check on each iteration whether we’ve hit the right edge and the bottom edge, we can simply calculate the length of each diagonal in advance.
Since the definition of diagonal number k of matrix a with M rows is equivalent to: all elements a[i][j] such that such that M - k = i - j, the algorithm ensures correctness by maintaining the invariant, which holds whenever we add 1 to both i and j, starting when either i or j is 0, and stopping whenever i = M or j = N, that is, traversing each step of the diagonal from the left or top edge to the right or bottom edge, whichever comes first.
#include <assert.h>
#include <iostream>
#include <stddef.h>
#include <stdlib.h>
#include <utility>
#include <vector>
using std::cin;
using std::cout;
template <typename T>
class matrix {
public:
matrix( const ptrdiff_t rows,
const ptrdiff_t cols,
std::vector<T>&& elems )
: rows_(rows), cols_(cols), elems_(elems)
{
assert( rows_ > 0 );
assert( cols_ > 0 );
assert( elems_.size() == static_cast<size_t>(rows_*cols_) );
}
matrix( const ptrdiff_t rows,
const ptrdiff_t cols,
const std::vector<T>& elems )
: matrix( rows, cols, std::move(std::vector<T>(elems)) )
{}
matrix( const matrix<T>& ) = default;
matrix( matrix<T>&& ) = default;
matrix& operator= ( const matrix<T>& ) = default;
matrix& operator= ( matrix<T>&& ) = default;
T& operator() ( const ptrdiff_t m, const ptrdiff_t n )
{
assert( m >= 0 && m < rows_ );
assert( n >= 0 && n < cols_ );
return elems_[static_cast<size_t>(m*cols_ + n)];
}
const T& operator() ( const ptrdiff_t m, const ptrdiff_t n ) const
{
/* Because this call does not modify any data, and the only reason the
* member function above cannot be const is that it returns a non-const
* reference to an element of elems, casting away the const qualifier
* internally and then returning a const reference is a safe way to
* re-use the code.
*/
matrix<T>& nonconst = *const_cast<matrix<T>*>(this);
return nonconst(m,n);
}
ptrdiff_t rows() const { return rows_; }
ptrdiff_t cols() const { return cols_; }
private:
ptrdiff_t rows_;
ptrdiff_t cols_;
std::vector<T> elems_;
};
template<typename T>
std::ostream& operator<< ( std::ostream& out, const matrix<T>& x )
/* Boilerplate to print a matrix. */
{
const ptrdiff_t m = x.rows(), n = x.cols();
for ( ptrdiff_t i = 0; i < m; ++i ) {
out << x(i,0);
for ( ptrdiff_t j = 1; j < n; ++j )
out << ' ' << x(i,j);
out << '\n';
} // end for
return out;
}
using elem_t = int;
std::vector<elem_t> diag_sums( const matrix<elem_t>& a )
/* Return a vector of all the diagonal sums of a.
*
* The first diagonal sum is a(rows-1,0)
* The second is a(rows-2,0) + a(rows-1,1)
* The third is a(rows-3,0) + a(rows-2,1) + a(rows-1,2)
* And so on. I.e., the kth diagonal is the sum of all elements a(i,j) such
* that i - j == rows - k.
*
* If a is a M×N matrix, there are M diagonals starting in column zero, and
* N-1 diagonals (excluding the one containing a(0,0) so we don't count it
* twice) starting in row 0. We process them bottom to top, then left to
* right.
*
* The number of elements in a diagonal starting at a(i,0) is min{M-i, N}. The
* number of elements in a diagonal starting at a(0,j) is min{M, N-j}. This is
* because a diagonal stops at either the bottom edge or the left edge of a.
*/
{
const ptrdiff_t m = a.rows(), n = a.cols();
std::vector<elem_t> result;
result.reserve( static_cast<size_t>(m + n - 1) );
for ( ptrdiff_t i = m-1; i > 0; --i ) {
elem_t sum = 0;
const ptrdiff_t nk = (m-i) < n ? (m-i) : n;
for ( ptrdiff_t k = 0; k < nk; ++k )
sum += a(i+k, k);
result.emplace_back(sum);
} // end for i
for ( ptrdiff_t j = 0; j < n; ++j ) {
elem_t sum = 0;
const ptrdiff_t nk = m < (n-j) ? m : (n-j);
for ( ptrdiff_t k = 0; k < nk; ++k )
sum += a(k, j+k);
result.emplace_back(sum);
} // end for j
return result;
}
matrix<elem_t> read_input_matrix( const int row, const int column )
/* Reads in row*column consecutive elements from cin and packs them into a
* matrix<elem_t>.
*/
{
assert(row > 0);
assert(column > 0);
const ptrdiff_t nelements = row*column;
assert(nelements > 0); // Check for overflow.
std::vector<elem_t> result;
result.reserve(static_cast<size_t>(nelements));
for ( ptrdiff_t i = nelements; i > 0; --i ) {
int x;
cin >> x;
assert(cin.good());
result.push_back(x);
}
return matrix<elem_t>( row,
column,
std::move(result) );
}
template<typename T>
bool print_sequence( const T& container )
/* Prints the contents of a container in the format
* "{47, 94, 124, 160, 148, 36, 5}".
*/
{
cout << "{";
if ( container.begin() != container.end() )
cout << *container.begin();
for ( auto it = container.begin() + 1; it < container.end(); ++it )
cout << ", " << *it;
cout << "}\n";
return cout.good();
}
/* A simple test driver that reads in the number of rows, the number of
* columns, and then row*columns int values, from standard input. It
* then passes the result to diag_matrix(), E.g.:
*
* 5 3
* 52 35 5
* 2 71 1
* 3 60 25
* 79 55 98
* 47 15 66
*/
int main()
{
int rows, columns;
cin >> rows;
cin >> columns;
assert(cin.good());
const matrix<elem_t> input_matrix = read_input_matrix( rows, columns );
// cout << input_matrix; // Instrumentation.
const std::vector<elem_t> sums = diag_sums(input_matrix);
print_sequence(sums);
return EXIT_SUCCESS;
}
You could also just do print_sequence(diag_sums(read_input_matrix( rows, columns ))).
You can simplify your code finding the starting position of each diagonal and then stepping through the matrix as long as the coordinates stay inside the matrix.
Something like this:
#include <iostream>
using namespace std;
void diag_matrix(int** m, int rows, int cols)
{
for (int diag = 1; diag < rows + cols; diag++)
{
int x, y;
if (diag < rows)
{
y = rows - diag;
x = 0;
}
else
{
y = 0;
x = diag - rows;
}
int sum = 0;
cout << "Summing diagonal #" << diag << ":";
while ((x < cols) && (y < rows))
{
sum += m[y][x];
cout << " " << m[y][x];
x++;
y++;
}
cout << " result: " << sum << "." << endl;
}
}
int main(int argc, char* argv[])
{
int rows = 5, cols = 3;
int **m = new int*[rows];
for (int i = 0; i < rows; i++)
m[i] = new int[cols];
m[0][0] = 52; m[0][1] = 35; m[0][2] = 5;
m[1][0] = 2; m[1][1] = 71; m[1][2] = 1;
m[2][0] = 3; m[2][1] = 60; m[2][2] = 25;
m[3][0] = 79; m[3][1] = 55; m[3][2] = 98;
m[4][0] = 47; m[4][1] = 15; m[4][2] = 66;
diag_matrix(m, rows, cols);
for (int i = 0; i < rows; i++)
delete[] m[i];
delete[] m;
return 0;
}
Related
I have the following problem : I have a hex number (datatype : std::uint64_t) in C++, and the hex number contains all the digits from 1 to a given n. The question is now to rotate the first k digits of the hex number, for example :
hex = 0x436512, k = 3 --> 0x634512
I have already tried splitting the hex number into two parts, e.g
std::uint64_t left = hex >> ((n - k) * 4);
std::uint64_t right = ((1UL << ((n - k) * 4)) - 1) & hex;
and then rotating left and merging left and right together. Is there a possibility to do this in-place and by only using bit-manipulation and/or mathematical operators?
As a baseline you can use this which is basically converting to digits and back.
#include <cstdio>
#include <cstdint>
#include <array>
uint64_t rotate( uint64_t value, int k ) {
// decompose
std::array<uint8_t,16> digits;
int numdigits = 0;
while ( value > 0 ) {
digits[numdigits] = value % 16;
value = value / 16;
numdigits += 1;
}
if ( k>numdigits ) return 0;
// revert digits
int p1 = numdigits - 1;
int p2 = numdigits - k;
for ( ; p1>p2; p1--,p2++ ) {
uint8_t tmp = digits[p1];
digits[p1] = digits[p2];
digits[p2] = tmp;
}
// reconstruct
for ( int j=0; j<numdigits; ++j ) {
value = (value*16) + digits[numdigits-1-j];
}
return value;
}
int main() {
uint64_t value = 0x123ffffff;
for ( int j=0; j<8; ++j ) {
value = value >> 4;
printf( "%lx %lx\n", value, rotate(value,3) );
}
}
Godbolt: https://godbolt.org/z/77qWEo9vE
It produces:
Program stdout
123fffff 321fffff
123ffff 321ffff
123fff 321fff
123ff 321ff
123f 321f
123 321
12 0
1 0
You actually do not need to decompose the entire number, you can strictly decompose only the left digits.
#include <cstdio>
#include <cstdint>
#include <array>
uint64_t rotate( uint64_t value, int k ) {
// sanity check
if ( value == 0 ) return 0;
// fast find number of digits
int numdigits = (63-__builtin_clzl(value))/4 + 1;
if ( k>numdigits ) return 0;
// Decompose left and right
int rightbits = 4*(numdigits-k);
uint64_t left = value >> rightbits;
uint64_t right = rightbits==0 ? 0 : value & (uint64_t(-1)>>(64-rightbits));
// decompose left
uint64_t rot = 0;
for ( int j=0; j<k; ++j ) {
uint64_t digit = left % 16;
left = left / 16;
rot = (rot*16) + digit;
}
// rejoin
return right | (rot<<rightbits);
}
int main() {
uint64_t value = 0x123ffffff;
for ( int j=0; j<8; ++j ) {
value = value >> 4;
printf( "%lx %lx\n", value, rotate(value,3) );
}
}
Produces the same output.
Godbolt: https://godbolt.org/z/P3z6W8b3M
Running under Google benchmark:
#include <benchmark/benchmark.h>
#include <vector>
#include <iostream>
uint64_t rotate1(uint64_t value, int k);
uint64_t rotate2(uint64_t value, int k);
struct RotateTrivial {
uint64_t operator()(uint64_t value, int k) {
return rotate1(value, k);
}
};
struct RotateLeftOnly {
uint64_t operator()(uint64_t value, int k) {
return rotate2(value, k);
}
};
template <typename Fn>
static void Benchmark(benchmark::State& state) {
Fn fn;
for (auto _ : state) {
uint64_t value = uint64_t(-1);
for (int j = 0; j < 16; ++j) {
for (int k = 1; k < j; ++k) {
uint64_t result = fn(value, k);
benchmark::DoNotOptimize(result);
}
value = value >> 4;
}
}
}
BENCHMARK(Benchmark<RotateTrivial>);
BENCHMARK(Benchmark<RotateLeftOnly>);
BENCHMARK_MAIN();
Produces on an AMD Threadripper 3960x 3.5GHz
--------------------------------------------------------------------
Benchmark Time CPU Iterations
--------------------------------------------------------------------
Benchmark<RotateTrivial> 619 ns 619 ns 1158174
Benchmark<RotateLeftOnly> 320 ns 320 ns 2222098
Each iteration has 105 calls so it's about 6.3 ns/call or 20 cycles for the trivial version and 3.1ns/call or 10 cycles for the optimized version.
The problem is, in a table of (h+1)*(w+1),the first row contains w values: a[1] ... a[w] which fill in the 2rd ... (w+1)th column. The first column contains h values: b[1] ... b[h] which fill in the 2rd ... (h+1)th row. sum(a[i]) is equal to sum(b[i]).
The question is to give one possible solution: result, so that sum(result[i][K]) for a certain K, is equal to a[i] with result[i][K] != result[j][K] (i != j and 0 < i < h+1). And the same rule for rows. PS: All the integers are positive.
For example:
a[] = {10, 3, 3}, b[] = {9, 7}
// 10 3 3
// 9 6 2 1
// 7 4 1 2
result = {6, 2, 1;
4, 1, 2}
It is like Kakuro but not the same. I cannot figure out which algorithm to apply, if anyone knows how to solve it, please give me some help. Thanks a lot.
You can always solve your problem with backtracking. Basic idea here: from top-to-bottom and left-to-right try a valid value in the partially filled table, backtrack when this value doesn't lead to a solution.
Minimal example in C++ with annotated solve:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <memory>
class Problem {
public:
template<class AIter, class BIter>
Problem(AIter abegin, AIter aend, BIter bbegin, BIter bend)
: m_width(std::distance(abegin, aend))
, m_height(std::distance(bbegin, bend))
, m_table(new int[(m_width + 1) * (m_height + 1)])
{
std::fill(m_table.get(), m_table.get() + (m_width + 1) * (m_height + 1), 0);
for(size_t i = 0; i < m_width; ++i)
m_table[i + 1] = *abegin++;
for(size_t j = 0; j < m_height; ++j)
m_table[(j + 1) * (m_width + 1)] = *bbegin++;
}
bool Solve() { return solve(0, 0); }
int operator()(size_t i, size_t j) const;
private:
int a(size_t i) const { return m_table[i + 1]; }
int b(size_t j) const { return m_table[(j + 1) * (m_width + 1)]; }
int get(size_t i, size_t j) const { return m_table[(j + 1) * (m_width + 1) + i + 1]; }
void set(size_t i, size_t j, int value) { m_table[(j + 1) * (m_width + 1) + i + 1] = value; }
int colSum(size_t i) const;
int rowSum(size_t j) const;
bool solve(size_t i, size_t j);
size_t m_width, m_height;
std::unique_ptr<int[]> m_table; // (width + 1) x (height + 1)
};
int Problem::colSum(size_t i) const {
int sum = 0;
for(size_t j = 0; j < m_height; ++j)
sum += get(i, j);
return sum;
}
int Problem::rowSum(size_t j) const {
int sum = 0;
for(size_t i = 0; i < m_width; ++i)
sum += get(i, j);
return sum;
}
// solves column-wise using backtracking
bool Problem::solve(size_t i, size_t j) {
size_t width = m_width, height = m_height;
// past last column?
if(i >= width) {
// found solution
return true;
}
// remainder in column and row
int remColSum = a(i) - colSum(i);
int remRowSum = b(j) - rowSum(j);
// early break
if(remColSum <= 0 || remRowSum <= 0)
return false;
// starting at the minimal required value (1 or remColSum if on last row)
int startValue = j + 1 < height ? 1 : remColSum;
// remaining row sum cannot support the starting value
if(remRowSum < startValue)
return false;
// end value minimum remaining sum
int endValue = remColSum < remRowSum ? remColSum : remRowSum;
// on last element must equal starting value
if(i + 1 == width && j + 1 == height && startValue != endValue)
return false;
// column-wise i.e. next cell is (i, j + 1) wrapped
int nextI = i + (j + 1) / height;
int nextJ = (j + 1) % height;
for(int value = startValue; value <= endValue; ++value) {
bool valid = true;
// check row up to i
for(size_t u = 0; u < i && valid; ++u)
valid = (get(u, j) != value);
// check column up to j
for(size_t v = 0; v < j && valid; ++v)
valid = (get(i, v) != value);
if(!valid) {
// value is invalid in partially filled table
continue;
}
// value produces a valid, partially filled table, now try recursing
set(i, j, value);
// upon first solution break
if(solve(nextI, nextJ))
return true;
}
// upon failure backtrack
set(i, j, 0);
return false;
}
int Problem::operator()(size_t i, size_t j) const {
return get(i, j);
}
int main() {
int a[] = { 10, 3, 3 };
int b[] = { 9, 7 };
size_t width = sizeof(a) / sizeof(*a);
size_t height = sizeof(b) / sizeof(*b);
Problem problem(a, a + width, b, b + height);
if(!problem.Solve()) {
std::cout << "No solution" << std::endl;
}
for(size_t j = 0; j < height; ++j) {
if(j == 0) {
std::cout << " ";
for(size_t i = 0; i < width; ++i)
std::cout << " " << a[i];
std::cout << std::endl;
}
std::cout << b[j];
for(size_t i = 0; i < width; ++i) {
int value = problem(i, j);
if(value == 0)
std::cout << " ";
else
std::cout << " " << value;
}
std::cout << std::endl;
}
return 0;
}
Given : A two dimensional array , values K and M
Problem : Find the maximum possible sum less than or equal K using all the rows (i.e there should be an element form each row) using exactly M elements.
This is a snippet of a program, I am having trouble implementing the conditions for each row and M.
for (int i = 0 ; i<n ; i++)
for (int s=0; s<M; s++)
for (int j=K;j>=0;j--)
if (dp[s][j] && A[i] + j < K)
dp[s + 1][j + A[i]] = true;
EDIT 1: Rows = M , i.e one element from each row has to be selected.
EDIT 2 : Dynamic Programming Solution, Thanks to #6502
ill ret(V(ill) col[101],ill prec[][101],ill s,ill row,ill m,ill k)
{
if(prec[s][row])
return prec[s][row];
else
{
if(row==m+1)
return s;
ill best=-1;
int j=row;
for(int i=0;i<col[j].size();i++)
{
if(s+col[j][i] <= k)
{
ill x = ret (col,prec,s+col[j][i],row+1,m,k);
if ((best==-1)||(x>best))
best=x;
}
}
prec[s][row]=best;
return best;
}
}
The problem can be solved using dynamic programming by choosing as state the pair (s, row) where s is the current sum and row is the next row we need to include.
The maximal principle is valid because no matter on which choices we made in previous rows the result depends only on the current sum and the current row index.
In code (Python)
cache = {}
data = [[2, 3, 4],
[2, 3, 4],
[2, 3, 4]]
M = 3
K = 10
def msum(s, row):
try:
return cache[s, row]
except KeyError:
if row == M:
return s
best = None
for v in data[row]:
if s+v <= K:
x = msum(s+v, row+1)
if best is None or x > best:
best = x
cache[s, row] = best
return best
print msum(0, 0)
The function returns None if no solution exists (i.e. if even taking the smallest value from each row we end up exceeding K).
A brute force approach:
bool increase(const std::vector<std::vector<int>>& v, 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] > v[index].size()) {
it[index] = 0;
} else {
return true;
}
}
return false;
}
int sum(const std::vector<std::vector<int>>& v, const std::vector<std::size_t>& it)
{
int res = 0;
for (std::size_t i = 0; i != it.size(); ++i) {
res += v[i][it[i]];
}
return res;
}
int maximum_sum_less_or_equal_to_K(const std::vector<std::vector<int>>& v, int K)
{
std::vector<std::size_t> it(v.size());
int res = K + 1;
do {
int current_sum = sum(v, it);
if (current_sum <= K) {
if (res == K + 1 || res < current_sum) {
res = current_sum;
}
}
} while (increase(v, it));
if (res == K + 1) {
// Handle no solution
}
return res;
}
it has the current selection of each row.
This can be solved using boolean 2D table. The value of dp[r][s] is set to true, if its possible to generate sum 's' , using exactly 'r' rows (i.e exactly one element from each of the [0 to r-1] rows). Using this dp table, we can compute next state as
dp[r+1][s] |= dp[r][s-A[r+1][c]] ; 0 < c < N, 0 < s <= K
where N is number of columns(0-based indexing). Finally return the value of max index set in M-1 row of dp table
Following is a bottom-up implementation
// Assuming input matrix is M*N
int maxSum() {
memset(dp, false, sizeof(dp));
//Initialise base row
for (int c = 0; c < N; ++c)
dp[0][A[0][c]] = true;
for ( int r = 1; r < M; ++r ) {
for ( int c = 0; c < N; ++c) {
// For each A[r][c], check for all possible values of sum upto K
for (int sum = 0; sum <= K; ++sum) {
if ( sum-A[r][c] >= 0 && dp[r-1][sum-A[r][c]] )
dp[r][sum] = true;
}
}
}
// Return max possible value <= K
for (int sum = K; sum >= 0; --sum) {
if ( dp[M-1][sum] )
return sum;
}
return 0;
}
Note that dp table values for current row depend only on previous row, as such space optimization trick can be used to solve it using 1-D table
Hello I'm having trouble with a little program I am trying to write. The problem is if I'm given any matrix size (lets just say a 4x4 for this example), find the largest product of n numbers in a row (lets say n = 3). The 3 numbers in a row can be horizontal, vertical, or diagonal. So heres a matrix:
1 1 2 5
1 5 2 4
1 7 2 3
1 8 2 1
If n was equal to 3 then my largest product would be 280 (5*7*8). Now I have my matrix loaded into a 2D vector. I'm not too picky on how the program works(brute force is fine), so far I know I'm going to have to have at least two nested for loops to go through each staring location of the matrix but I haven't been successful in finding the current answer. Any advice will help, thank you.
Version to find max product in rows using rolling multiplication to save some resources. This rolling procedure means that we don't have to multiply n values to find each product of these n values, but instead we have to just do one multiplication and one division:
if (currN == N) { // compute full product first time
while (currn) {
product *= (*it3++);
--currn;
}
} else { // rolling computation
product *= (*(it3 + n - 1)) / (*(it3 - 1));
it3 += n;
}
It is up to you to complete this to handle also columns:
populate matrix:
#include <cstdio>
#include <vector>
#include <algorithm>
#include <iterator>
#include <iostream>
using namespace std;
typedef vector< vector< int> > Matrix;
typedef Matrix::iterator outIt;
typedef vector< int>::iterator inIt;
void fillMatrix( Matrix& matrix) {
outIt it = matrix.begin();
(*it).push_back( 1);
(*it).push_back( 1);
(*it).push_back( 2);
(*it).push_back( 5);
++it;
(*it).push_back( 1);
(*it).push_back( 5);
(*it).push_back( 2);
(*it).push_back( 4);
++it;
(*it).push_back( 1);
(*it).push_back( 7);
(*it).push_back( 2);
(*it).push_back( 3);
++it;
(*it).push_back( 1);
(*it).push_back( 8);
(*it).push_back( 2);
(*it).push_back( 1);
}
print matrix and find max product in rows:
void printMatrix( Matrix& matrix) {
outIt it = matrix.begin();
while ( it != matrix.end()) {
inIt it2 = (*it).begin();
while ( it2 != (*it).end()) {
printf( "%d", *it2);
++it2;
}
printf( "\n");
++it;
}
}
/**
*
* #param matrix
* Largest product in row using rolling multiplication
* #param n number of factors
* #param v factors of largest product
* #return largest product
*/
int largestProductInRow( Matrix& matrix, int n, vector< int>& v) {
if ( n > matrix.size()) return -1;
int res = 0;
int N = matrix.size() - n + 1; // number of products in row (or column)
/* search in rows */
outIt it = matrix.begin();
while (it != matrix.end()) {
inIt it2 = (*it).begin();
int currN = N;
int product = 1;
while (currN) { // rolling product calculation
inIt it3 = it2;
int currn = n;
if (currN == N) { // compute full product first time
while (currn) {
product *= (*it3++);
--currn;
}
} else { // rolling computation
product *= (*(it3 + n - 1)) / (*(it3 - 1));
it3 += n;
}
if (product > res) {
res = product;
copy(it3 - n, it3, v.begin());
}
--currN;
++it2;
}
++it;
}
return res;
}
usage:
/*
*
*/
int main(int argc, char** argv) {
Matrix matrix( 4, vector< int>());
fillMatrix( matrix);
printMatrix( matrix);
vector< int> v(3);
int res = largestProductInRow( matrix, 3, v);
printf( "res:%d\n", res);
copy( v.begin(), v.end(), ostream_iterator<int>(cout, ","));
return 0;
}
result:
res:42
7,2,3,
RUN SUCCESSFUL (total time: 113ms)
Lets say we have s x t matrix (s columns and t rows).
int res = 0;
if(s >= n)
{
for (int r = 0; r < t; ++r) // for each row
{
for (int i = 0; i <= s-n; ++i) //moving through the row
{
int mul = m[i][0];
for (int j = 1; j < n; ++j) //calculating product in a row
{
mul*=m[i][j];
}
if(mul > res)
{
res = mul;
//save i, j here if needed
}
}
}
}
if(t >= n)
{
for (int c = 0; c < s; ++c) // for each column
{
for (int i = 0; i <= t-n; ++i) //moving through the column
{
int mul = m[0][i];
for (int j = 1; j < n; ++j) //calculating product in a column
{
mul*=m[j][i];
}
if(mul > res)
{
res = mul;
//save i, j here if needed
}
}
}
}
If you insist on brute-force, then as you said, you need to iterate over all [x,y],
which will be the starting points of the rows.
From these you can iterate over k adjacent elements in all directions.
You can store the directions as vectors in an array.
This would run in O(k n^2).
For n x n matrix and looking for k elements in row, C-like pseudocode would look like this (note there is no bounds checking, for the sake of simplicity):
// define an array of directions as [x,y] unit vectors
// you only need to check in 4 directions, other 4 are the same, just reversed
int[4][2] dirs = {{1,0}, {1,1}, {0,1}, {-1,1}};
// iterate over all starting positions
for (x = 0; x < n; ++x) {
for (y = 0; y < n; ++y) {
// iterate over all directions
for (d = 0; d < 4; ++d) {
result = 1;
// iterate over elements in row starting at [x,y]
// going in direction dirs[d]
for (i = 0; i < k; ++i) {
// multiply current result by the element,
// which is i places far from the beginning [x,y]
// in the direction pointed by dirs[d]
new_x = x + i * dirs[d][0];
new_y = y + i * dirs[d][1];
// you need to check the bounds, i'm not writing it here
// if new_x or new_y are outside of the matrix
// then continue with next direction
result *= matrix[new_x][new_y];
}
if (result > max) {
max = result;
}
}
}
}
Slightly better, less of a brute-force way would be to
start on the boundary of a matrix, pick a direction and go in this direction to the opposite side of the matrix, keeping the product of the last k numbers on the way.
While walking, you keep the product, multiplying it by the number you got to and dividing by the number you left k steps ago.
This way, with some bounds checking of course,
the product is always product of the last k numbers,
therefore if the current product is more than maximum, just let max = product.
This runs always in O(n^2).
I've written a routine in C++ that solves the system of equations Ax = b using Gauss-Seidel method. However, I want to use this code for specific "A" matrices that are sparse (most of the elements are zero). This way, most of the time that this solver takes is busy multiplying some elements by zero.
For example, for the following system of equations:
| 4 -1 0 0 0 | | x1 | | b1 |
|-1 4 -1 0 0 | | x2 | | b2 |
| 0 -1 4 -1 0 | | x3 | = | b3 |
| 0 0 -1 4 -1 | | x4 | | b4 |
| 0 0 0 -1 4 | | x5 | | b5 |
Using Gauss-Seidel method, we will have the following iteration formula for x1:
x1 = [b1 - (-1 * x2 + 0 * x3 + 0 * x4 + 0 * x5)] / 4
As you see, the solver is wasting time by multiplying zero elements. Since I work with big matrices (for example, 10^5 by 10^5), this will influence the total CPU time in a negative way. I wonder if there is a way to optimize the solver so that it omits those part of calculations related to zero element multiplications.
Note that the the form of the "A" matrix in the example above is arbitrary and the solver must be able to work with any "A" matrix.
Here is the code:
void GaussSeidel(double **A, double *b, double *x, int arraySize)
{
const double tol = 0.001 * arraySize;
double error = tol + 1;
for (int i = 1; i <= arraySize; ++i)
x[i] = 0;
double *xOld;
xOld = new double [arraySize];
for (int i = 1; i <= arraySize; ++i)
xOld[i] = 101;
while (abs(error) > tol)
{
for (int i = 1; i <= arraySize; ++i)
{
sum = 0;
for (int j = 1; j <= arraySize; ++j)
{
if (j == i)
continue;
sum = sum + A[i][j] * x[j];
}
x[i] = 1 / A[i][i] * (b[i] - sum);
}
//cout << endl << "Answers:" << endl << endl;
error = errorCalc(xOld, x, arraySize);
for (int i = 1; i <= arraySize; ++i)
xOld[i] = x[i];
cout << "Solution converged!" << endl << endl;
}
Writing a sparse linear system solver is hard. VERY HARD.
I would just pick one of the exisiting implementations. Any reasonable LP solver has a sparse linear system solver inside, see for example lp_solve, GLPK, etc.
If the licence is acceptable for you, I recommend the Harwell Subroutine library. Interfacing C++ and Fortran is not fun though...
How sparse do you mean?
Here's a crappy sparse implementation that should work well for solving systems of linear equasions. It's probably a naive implementation, I know very little about the data structures typically used in industrial strength sparse matrices.
The code, and an example, is here.
Here's the class that does most of the work:
template <typename T>
class SparseMatrix
{
private:
SparseMatrix();
public:
SparseMatrix(int row, int col);
T Get(int row, int col) const;
void Put(int row, int col, T value);
int GetRowCount() const;
int GetColCount() const;
static void GaussSeidelLinearSolve(const SparseMatrix<T>& A, const SparseMatrix<T>& B, SparseMatrix<T>& X);
private:
int dim_row;
int dim_col;
vector<map<int, T> > values_by_row;
vector<map<int, T> > values_by_col;
};
The other method definitions are included in the ideone. I don't test for convergence, but rather simply loop an arbitrary number of times.
The sparse representation stores, by row and column, the positions of all of the values, using STL maps. I'm able to solve a system of 10000 equasions in just 1/4 seconds for a very sparse matrix like the one you provided (density < .001).
My implementation should be generic enough to support any integral or user defined type that supports comparison, the 4 arithmetic operators (+, -, *, /), and that can be explicitly cast from 0 (empty nodes are given the value (T) 0).
Recently, I face the same problem.
My solution is using vector array to save the sparse matrix.
Here is my code:
#define PRECISION 0.01
inline bool checkPricision(float x[], float pre[], int n) {
for (int i = 0; i < n; i++) {
if (fabs(x[i] - pre[i]) > PRECISION) return false;
}
return true;
}
/* mx = b */
void gaussIteration(std::vector< std::pair<int, float> >* m, float x[], float b[], int n) {
float* pre = new float[n];
int cnt = 0;
while (true) {
cnt++;
memcpy(pre, x, sizeof(float)* n);
for (int i = 0; i < n; i++) {
x[i] = b[i];
float mii = -1;
for (int j = 0; j < m[i].size(); j++) {
if (m[i][j].first != i) {
x[i] -= m[i][j].second * x[m[i][j].first];
}
else {
mii = m[i][j].second;
}
}
if (mii == -1) {
puts("Error: No Solution");
return;
}
x[i] /= mii;
}
if (checkPricision(x, pre, n)) {
break;
}
}
delete[] pre;
}
Try PETSC. You need CRS (Compressed row storage) format for this.