Why AddressSanitizer:DEADLYSIGNAL? - c++

class Solution {
int maxRow, maxCol;
int x[4] = {1, -1, 0, 0};
int y[4] = {0, 0, 1, -1};
bool isValid(int row, int col){
return (row >= 0 && row < maxRow && col >= 0 && col < maxCol);
}
int longestPath(int row, int col, vector<vector<int>>& matrix, vector<vector<int>>& dp){
if(dp[row][col] != -1){
return dp[row][col];
}
int longestCurrPath = 1;
for(int dir = 0; dir < 4; ++dir){
int newRow = row + x[dir];
int newCol = col + y[dir];
if(isValid(newRow, newCol) && matrix[col][row] > matrix[newRow][newCol]){
longestCurrPath = max(longestCurrPath, longestPath(newRow, newCol, matrix, dp) + 1);
}
}
return dp[row][col] = longestCurrPath;
}
public:
int longestIncreasingPath(vector<vector<int>>& matrix) {
maxRow = matrix.size();
maxCol = matrix[0].size();
int LIP = 1;
vector<vector<int>> dp(maxRow + 1, vector<int>(maxCol + 1, -1));
for(int row = 0; row < maxRow; ++row){
for(int col = 0; col < maxCol; ++col){
if(dp[row][col] == -1)
LIP = max(LIP, longestPath(row, col, matrix, dp));
}
}
return LIP;
}
};
AddressSanitizer:DEADLYSIGNAL
==31==ERROR: AddressSanitizer: stack-overflow on address 0x7ffe60cafff8 (pc 0x0000003466d2 bp 0x7ffe60cb0070 sp 0x7ffe60cb0000 T0)
==31==ABORTING

Answer: Stackoverflow.
Your recursive logic is buggy. And you perpetually end up in a situation like this:
See comments in the code below
int longestPath(int row, int col, vector<vector<int>>& matrix, vector<vector<int>>& dp){
if(dp[row][col] != -1){
// Termination depends on `dp`
return dp[row][col];
}
int longestCurrPath = 1;
for(int dir = 0; dir < 4; ++dir){
int newRow = row + x[dir];
int newCol = col + y[dir];
if(isValid(newRow, newCol) && matrix[col][row] > matrix[newRow][newCol]) {
// Making recursive calls without ever influencing `dp`
longestCurrPath = max(longestCurrPath, longestPath(newRow, newCol, matrix, dp) + 1);
}
}
// This is the only time you change `dp`
return dp[row][col] = longestCurrPath;
}

Related

runtime error: reference binding to misaligned address 0xbebebebebebebec6 for type 'int', which requires 4 byte alignment (stl_vector.h)

i am writing code to solve this problem on leetcode
my strategy to solve this is:
run dfs for each cell index (x,y)
on each dfs call check if cell is a destination cell
accordingly set the flags
if both flags are true then add this cell to "ans" vector else carry on with the next dfs
class Solution {
public:
void psUtil(vector<vector<int> >&mat, int x, int y, int m, int n, int &isP, int &isA, vector<vector<int> >&vis, vector<vector<int> >&ans)
{
//check dstinations
if(x == 0 || y == 0)
{
isP = 1;
}
if(x == m || y == n)
{
isA = 1;
}
vector<int> cell(2);
cell[0] = x;
cell[1] = y;
// check both dst rched
if(isA && isP)
{
// append to ans
ans.push_back(cell);
return;
}
// mark vis
vis.push_back(cell);
int X[] = {-1, 0, 1, 0};
int Y[] = {0, 1, 0, -1};
int x1, y1;
// check feasible neighbours
for(int i = 0; i < 4; ++i)
{
x1 = x + X[i];
y1 = y + Y[i];
if(x1 < 0 || y1 < 0) continue;
if(mat[x1][y1] <= mat[x][y])
{
vector<vector<int> > :: iterator it;
vector<int> cell1(2);
cell1[0] = x1;
cell1[1] = y1;
it = find(vis.begin(), vis.end(), cell1);
if(it == vis.end());
else continue;
psUtil(mat, x1, y1, m, n, isP, isA, vis, ans);
if(isA && isP) return;
}
}
}
vector<vector<int>> pacificAtlantic(vector<vector<int>>& matrix)
{
// find dimensions
int m = matrix.size(); // rows
int n = matrix[0].size(); // cols
vector<vector<int> >ans;
// flags if rched destinations
int isP, isA;
isP = isA = 0;
// iterate for all indices
for(int x = 0; x < m; ++x)
{
for(int y = 0; y < n; ++y)
{
// visited nested vector
vector<vector<int> >vis;
psUtil(matrix, x, y, m, n, isP, isA, vis, ans);
isP = isA = 0;
}
}
return ans;
}
};
and my error on running this is
Runtime Error Message:
Line 924: Char 9: runtime error: reference binding to misaligned address 0xbebebebebebebec6 for type 'int', which requires 4 byte alignment (stl_vector.h)
Last executed input:
[[1,2,2,3,5],[3,2,3,4,4],[2,4,5,3,1],[6,7,1,4,5],[5,1,1,2,4]]
why am i getting this message and how do i fix it?
i found my error ! it was because of a missing boundary check for the newly calculated coordinate and improper boundary check for a coordinate in the beginning of psUtil.
instead of this:
if(x == m || y == n)
.
.
.
if(x1 < 0 || y1 < 0) continue;
it should be this:
if(x == m-1 || y == n-1)
.
.
.
if(x1 < 0 || y1 < 0 || x1 >= m || y1 >= n) continue;
Your method is pretty good, but maybe we can improve on the implementation a bit. Here is an accepted solution with a similar DFS method.
class Solution {
public:
int direction_row[4] = {0, 1, -1, 0};
int direction_col[4] = {1, 0, 0, -1};
void depth_first_search(vector<vector<int>> &grid, vector<vector<bool>> &visited, int row, int col, int height) {
if (row < 0 || row > grid.size() - 1 || col < 0 || col > grid[0].size() - 1 || visited[row][col])
return;
if (grid[row][col] < height)
return;
visited[row][col] = true;
for (int iter = 0; iter < 4; iter++)
depth_first_search(grid, visited, row + direction_row[iter], col + direction_col[iter], grid[row][col]);
}
vector<vector<int>> pacificAtlantic(vector<vector<int>> &grid) {
vector<vector<int>> water_flows;
int row_length = grid.size();
if (!row_length)
return water_flows;
int col_length = grid[0].size();
vector<vector<bool>> pacific(row_length, vector<bool>(col_length, false));
vector<vector<bool>> atlantic(row_length, vector<bool>(col_length, false));
for (int row = 0; row < row_length; row++) {
depth_first_search(grid, pacific, row, 0, INT_MIN);
depth_first_search(grid, atlantic, row, col_length - 1, INT_MIN);
}
for (int col = 0; col < col_length; col++) {
depth_first_search(grid, pacific, 0, col, INT_MIN);
depth_first_search(grid, atlantic, row_length - 1, col, INT_MIN);
}
for (int row = 0; row < row_length; row++)
for (int col = 0; col < col_length; col++)
if (pacific[row][col] && atlantic[row][col]) {
water_flows.push_back({row, col});
}
return water_flows;
}
};
I'm not also sure, if this would be the most efficient algorithm for the Pacific Atlantic Water Flow problem. You can check out the discussion board.
References
For additional details, you can see the Discussion Board. There are plenty of accepted solutions, explanations, efficient algorithms with a variety of languages, and time/space complexity analysis in there.
417. Pacific Atlantic Water Flow
417. Pacific Atlantic Water Flow - Discussion

Sparse matrix compressed on rows in C++

I have to implement the CSR matrix data structure in C++ using 3 dynamic arrays (indexing starts at 0) and I've got stuck. So I have to implement 2 functions:
1) modify(int i, int j, TElem e) - modifies the value of (i,j) to e or adds if (if it does not exist) or deletes it if e is null.
2) element(int i, int j) const - returns the value found on (i,j)
I wanted to test my code in the next way:
Matrix m(4,4); m.print(); It will print:
Lines: 0 0 0 0 0
Columns:
Values:
(And this is fine)
Now if I want to modify: m.modify(1,1,5); //The element (1,1) will be set to 5
The output of m.print(); will be:
Lines: 0 1 1 1 1
Columns: 1
Values: 5 (which again is fine)
And now if I want to print m.element(1, 1) it will return 0 and m.element(0, 1) will return 5.
This is my implementation of element(int i, int j) :
int currCol;
for (int pos = this->lines[i]; pos < this->lines[i+1]; pos++) {
currCol = this->columns[pos];
if (currCol == j)
return this->values[pos];
else if (currCol > j)
break;
}
return NULL_TELEM;
The constructor looks like this:
Matrix::Matrix(int nrLines, int nrCols) {
if (nrLines <= 0 || nrCols <= 0)
throw exception();
this->nr_lines = nrLines;
this->nr_columns = nrCols;
this->values = new TElem[100];
this->values_capacity = 1;
this->values_size = 0;
this->lines = new int[nrLines + 1];
this->columns = new TElem[100];
this->columns_capacity = 1;
this->columns_size = 0;
for (int i = 0; i <= nrLines; i++)
this->lines[i] = NULL_TELEM;
}
This is the "modify" method:
TElem Matrix::modify(int i, int j, TElem e) {
if (i < 0 || j < 0 || i >= this->nr_lines || j >= nr_columns)
throw exception();
int pos = this->lines[i];
int currCol = 0;
for (; pos < this->lines[i + 1]; i++) {
currCol = this->columns[pos];
if (currCol >= j)
break;
}
if (currCol != j) {
if (!(e == 0))
add(pos, i, j, e);
}
else if (e == 0)
remove(pos, i);
else
this->values[pos] = e;
return NULL_TELEM;
}
And this is the inserting method:
void Matrix::add(int index, int line, int column, TElem value)
{
this->columns_size++;
this->values_size++;
for (int i = this->columns_size; i >= index + 1; i--) {
this->columns[i] = this->columns[i - 1];
this->values[i] = this->values[i - 1];
}
this->columns[index] = column;
this->values[index] = value;
for (int i = line; i <= this->nr_lines; i++) //changed to i = line + 1;
this->lines[i]++;
}
Can somebody help me, please? I can't figure out why this happens and I really need to finish this implementation these days.
It just can't pass the next test. And if I want to print the elements i have (4,0)=0 (4,1)=0 ... (4,8)=0 and (4,9)=3. Now this looks pretty weird why it happens.
void testModify() {
cout << "Test modify" << endl;
Matrix m(10, 10);
for (int j = 0; j < m.nrColumns(); j++)
m.modify(4, j, 3);
for (int i = 0; i < m.nrLines(); i++)
for (int j = 0; j < m.nrColumns(); j++)
if (i == 4)
assert(m.element(i, j) == 3);
//cout << i << " " << j << ":" << m.element(i, j)<<'\n';
else
assert(m.element(i, j) == NULL_TELEM);
}
When you call modify(1, 1, 5) with an empty matrix (all zeros), that results in a call to add(0, 1, 1, 5). That increments columns_size and values_size (both to 1), the for loop body will not execute, you update columns[0] to 1 and values[0] to 5, then increment all the lines values starting at element lines[1], setting them all to 1 (lines[0] will still be 0). But lines[1] should indicate the element we just added, so it should be 0, since the value is found using columns[0].
The for loop at the end of add should start at element line + 1.

Why does my program not work when I use the "randomSelect" method to replace several lines of code

The scatter method takes the original image and scatter its pixels.
The program works well when I use several lines of code instead of the
method "randomSelect". The program seems to go into an infinite loop
and the image does not change when I use the method "randomSelect".
void scatter(GBufferedImage &img, Grid<int> original, int row, int col) {
int degree;
while (true) {
degree = getInteger("Enter degree of scatter [1-100]: ");
if (degree >=1 && degree <= 100) break;
}
Grid<int> newImg(row, col);
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
/* int newRow = -1;
int newCol = -1;
while (!original.inBounds(newRow, newCol)) {
newRow = randomInteger(max(i - degree, 0), min(i + degree,original.numRows()));
newCol = randomInteger(max(j - degree, 0), min(j + degree,original.numRows()));
}
newImg[i][j] = original[newRow][newCol]; */ // work properly
newImg[i][j] = randomSelect(original, i , j, degree); // do not work
}
}
img.fromGrid(newImg);
}
int randomSelect(Grid<int> original, int i, int j, int degree) { // do not work
int newRow = -1;
int newCol = -1;
while (!original.inBounds(newRow, newCol)) {
newRow = randomInteger(max(i - degree, 0), min(i + degree,original.numRows()));
newCol = randomInteger(max(j - degree, 0), min(j + degree,original.numRows()));
}
return original[newRow][newCol];
}
You should pass original as a reference:
int randomSelect(Grid<int>& original, int i, int j, int degree) { // will work

while loop is changing every object and not iterating through

#include <stdio.h>
#include <iostream>
#include "Vector.h"
#include <string.h>
#include <math.h>
#include "Matrix.h"
#include <list>
using namespace std;
// format for a Matrix
char* Matrix::printM(){
char* s = new char[5000*1024];
int i;
for(i=0;i < this->dimension.rows;i++){
int j;
for(j=0;j< this->dimension.columns;j++){
Vector* tmp = this->columns[j];
int x = this->dimension.columns - 1;
if(j == 0){
char buffer[500];
//it0oa(v->coordinate[i],buffer,sizeof(int));
snprintf(buffer,5000,"%f",tmp->coordinate[i]);
strncat(s,"|", 1+ strlen(s));
strncat(s,buffer, strlen(s) + strlen(buffer));
strncat(s,",",strlen(s) + 1);
}else if(j == x){
char buffer[500];
snprintf(buffer,5000,"%f",tmp->coordinate[i]);
strncat(s,buffer,strlen(s) + strlen(buffer));
strncat(s,"|\n",strlen(s)+2);
}else{
char buffer[500];
snprintf(buffer,5000,"%f",tmp->coordinate[i]);
strncat(s,buffer,strlen(s) + strlen(buffer));
strncat(s,",",strlen(s) + 1);
}
}
}
return s;
}
Matrix::Matrix(int di,int de){
this->dimension.rows =de;
this->dimension.columns =di;
this->columns.assign(di,new Vector(de));
}
Matrix::Matrix(std::vector<Vector*> v, int di){
this->dimension.columns = v.size();
this->columns = v;
int it;
this->dimension.rows = v[0]->dimension;
}
Matrix& Matrix::operator+(const Matrix& v){
Matrix* mt = new Matrix(this->dimension.columns,6);
mt->dimension = this->dimension;
int i;
for(i=0;i< mt->dimension.columns;i++){
//mt->columns.push_back(&(*this->columns[i] + *v.columns[i]));
mt->columns[i] = &(*this->columns[i] + *v.columns[i]);
printf("%s\n",mt->columns[0]->printV());
}
return *mt;
}
Matrix& Matrix::operator-(const Matrix& v){
Matrix* mt = new Matrix(this->dimension.columns,7);
mt->dimension = this->dimension;
int i;
for(i=0;i< mt->dimension.columns;i++){
//mt->columns.push_back(&(*this->columns[i] + *v.columns[i]));
mt->columns[i] = &(*this->columns[i] - *v.columns[i]);
printf("%s\n",mt->columns[0]->printV());
}
return *mt;
}
Matrix& Matrix::operator*(const double& v){
Matrix* mt = new Matrix(this->dimension.columns,7);
mt->dimension = this->dimension;
int i;
for(i=0;i< mt->dimension.columns;i++){
//mt->columns.push_back(&(*this->columns[i] + *v.columns[i]));
mt->columns[i] = &(*this->columns[i] * v);
//printf("%s\n",mt->columns[0]->printV());
}
return *mt;
}
std::vector<Vector*> Matrix::row_equiv(Matrix* m){
std::list<Vector*> result;
int i;
for(i=0;i< m->dimension.rows;i++){
std::list<double> lists;
lists.push_back(m->dimension.columns);
int j;
for(j=0;j< m->dimension.columns;j++){
Vector* tmp = m->columns[j];
lists.push_back(tmp->coordinate[i]);
}
j=0;
//std::initializer_list<double> list_h = lists;
Vector* tmp = new Vector(lists);
result.push_back(tmp);
}
std::vector<Vector*> x{std::begin(result),std::end(result)};
return x;
}
Matrix* Matrix::transpose(){
std::vector<Vector*> b = row_equiv(this);
Matrix* mt = new Matrix(b,this->dimension.rows);
return mt;
}
Matrix* Matrix::upperTriangular(){
std::vector<Vector*> tmp = row_equiv(this);
if(this->is_square()){
int j;
for(j=0;j<this->dimension.columns;j++){
double pivot = tmp[j]->coordinate[j];
int i;
for(i=j+1;i<this->dimension.rows;i++){
tmp[i] = &((*tmp[i]) - (*tmp[j] * (tmp[i]->coordinate[j]/pivot)));
}
}
}else if(this->dimension.rows > this->dimension.columns){
//printf("Hello world,\n");
int j;
for(j=0;j<this->dimension.columns;j++){
double pivot = tmp[j]->coordinate[j];
printf("%f\n",pivot);
int i;
for(i=j+1;i< this->dimension.rows;i++){
tmp[i] = &((*tmp[i]) + (*tmp[j] * (tmp[i]->coordinate[j]/-1*pivot)));
printf(" The vector is %s\n",tmp[i]->printV());
}
}
}else if(this->dimension.rows < this->dimension.columns){
printf("Not Hello World!");
}
Matrix* result = new Matrix(tmp,this->dimension.rows);
return result->transpose();
}
// This is supposed to give me the multiplication of matrices but it's not working right now.
Matrix& Matrix::operator*(const Matrix& v){
if(this->dimension.columns == v.dimension.rows){
Matrix* mt = new Matrix(v.dimension.columns,this->dimension.rows);
mt->dimension.rows = this->dimension.rows;
std::vector<Vector*> tmp = row_equiv(this);
std::vector<Vector* > result(v.dimension.columns, new Vector(this->dimension.rows));
for(auto i =0; i < tmp.size();i++){ //for each rows of the first matrix
int j =0;
while(j< this->dimension.columns){ //for each columns of the second matrix
//printf("%f and %f\n",tmp[i]->dimension,this->columns[j]->dimension);
//double x = *tmp[i] * *v.columns[j];
//printf("%f\n",x);
//mt->columns[j]->coordinate[i] = (*tmp[i] * *v.columns[j]); // This line is giving me problems.
//printf("THis is after the code\n");
result[j]->coordinate[i] = (*tmp[i] * *v.columns[j]);
printf("%s and %s %f and %s %s an j = %d\n",tmp[i]->printV(),v.columns[j]->printV(),result[j]->coordinate[i],result[j]->printV(),result[0]->printV(),j);
j++;
}
printf("%s\n",result[0]->printV());
}
return *mt;
}
Matrix* mt = new Matrix(3,2);
return *mt;
}
The problem is with this piece of code
Matrix& Matrix::operator*(const Matrix& v){
if(this->dimension.columns == v.dimension.rows){
Matrix* mt = new Matrix(v.dimension.columns,this->dimension.rows);
mt->dimension.rows = this->dimension.rows;
std::vector<Vector*> tmp = row_equiv(this);
std::vector<Vector* > result(v.dimension.columns, new Vector(this->dimension.rows));
for(auto i =0; i < tmp.size();i++){ //for each rows of the first matrix
int j =0;
while(j< this->dimension.columns){ //for each columns of the second matrix
//printf("%f and %f\n",tmp[i]->dimension,this->columns[j]->dimension);
//double x = *tmp[i] * *v.columns[j];
//printf("%f\n",x);
//mt->columns[j]->coordinate[i] = (*tmp[i] * *v.columns[j]); // This line is giving me problems.
//printf("THis is after the code\n");
result[j]->coordinate[i] = (*tmp[i] * *v.columns[j]);
printf("%s and %s %f and %s %s an j = %d\n",tmp[i]->printV(),v.columns[j]->printV(),result[j]->coordinate[i],result[j]->printV(),result[0]->printV(),j);
j++;
}
printf("%s\n",result[0]->printV());
}
return *mt;
}
Matrix* mt = new Matrix(3,2);
return *mt;
}
The function is supposed to multiply 2 matrices together.
This line is changing result[0] every time it runs and I don't know why. result is a vector of Vector* and the while loop is supposed to iterate through the Vector of the vector(list) and changing the ith component but every time the loop goes through it changes the previous Vector.
result[j]->coordinate[i] = (*tmp[i] * *v.columns[j])
This is the implementation :
for(auto i=0; i < this->dimension.rows;i++){
for(auto j=0; j<v.dimension.columns;j++){
for(auto k=0; k< this->dimension.rows;k++){
result[j]->coordinate[i] += this->columns[i]->coordinate[k] * v.columns[k]->coordinate[j];
printf("j = %d, %s and %s\n",j,result[j]->printV(), result[0]->printV());
}
}
}
When j = 1, result[0] also changes and i don't know why. This is the ouput .
j = 0, <2.000000,0.000000> and <2.000000,0.000000>
j = 0, <2.000000,0.000000> and <2.000000,0.000000>
j = 1, <2.000000,0.000000> and <2.000000,0.000000>
j = 1, <1.000000,0.000000> and <1.000000,0.000000>
j = 2, <1.000000,0.000000> and <1.000000,0.000000>
j = 2, <1.000000,0.000000> and <1.000000,0.000000>
j = 0, <1.000000,-1.000000> and <1.000000,-1.000000>
j = 0, <1.000000,-1.000000> and <1.000000,-1.000000>
j = 1, <1.000000,-1.000000> and <1.000000,-1.000000>
j = 1, <1.000000,1.000000> and <1.000000,1.000000>
j = 2, <1.000000,1.000000> and <1.000000,1.000000>
j = 2, <1.000000,1.000000> and <1.000000,1.000000>
Matrix multiplication is defined differently. It requires 3 nested for loops - not just two:
For every pair (i,j), you need to iterate over all values of k, and do the following pseudocode:
result = zeros(a.rows,b.cols)
for i = 0:a.rows-1
for j = 0:b.cols-1
for k = 0:a.cols-1
result(i,j) += a(i,k) * b(k,j)

How to solve another version of Kakuro

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;
}