sudoku,recursive function solves half the puzzle - c++

I'm working on a Sudoku solver, and my program is having trouble recursing backwards when it has exhausted its outputs.
I have four functions that do the check:
scolumn, srow, sbox. Each one will return false if the number already exists in the column row or box respectively.
bool sudoku::solve(int row, int column)
{
if(column == 9)
{
column = 0;
row +=1;
}
if(puzzle[row][column] != 0)
{
solve(row, column + 1);
return false;
}
else
{
for(int n = 0; n < 10; n ++)
{
if(srow(column, n) && scolumn(row,n) && sbox(row, column, n)
{
puzzle[row][column] = n;
if(!solve(row, column + 1);
table[row][column] = 0;
}
}
puzzle[row][column] = 0;// if not commented out then infinite loop
}
return false
}
the problem with it is that if its at 9 and there is no next choice, it will not backtrack correctly.

There are a number of problems with your code, as people have observed in the comments.
This answer summarises some of them:
1) As #n.m. said, you should not be trying '0' as a valid choice in a cell. That will be the cause of some infinite looping, no doubt.
2) As you have observed, you don't know how the recursion finishes. The answer is that when you get to the last cell, and you find a value that works in it, you are supposed to return true. This is what is supposed to break the for(n) loop: that loop is saying "try each number until the call of solve to the right of this cell succeeds'. Success is measured by your routine returning true.
Since you try every number (n) in the current cell, no matter whether or not the call to the solve on its right works ... it's not going to work.
You'll know that you're more on the right track when:
You can see the place in your code where you return true when you discover that you can put a number in the last cell (9,9)
You can see how it is that you stop trying numbers (n=0..9) when the call to the right succeeds.

Given int puzzle[9][9], and your srow, scol, and sbox functions:
bool sudoku::solve(int row, int column) //to solve entire puzzle, call with parameters 0 and 0
{
int cell;
//ignore all nonzero cells (zero = empty)
while (row < 9 && puzzle[row][column] != 0)
{
column++;
if (column == 9)
{
row++;
column = 0;
}
}
if (row == 9) return true; //puzzle is already solved
//try values 1-9 inclusive. If successful, then return true
for (cell = 1; cell <= 9; cell++)
{
puzzle[row][column] = cell;
if (srow(row) &&
scol(column) &&
sbox(row-row%3, column-column%3) &&
solve(row, column)) //recursion!!
{
return true;
}
}
//if no value works, reset the cell and return false.
puzzle[row][column] = 0;
return false;
}

Related

What is wrong with this loop-based function that returns the position of an element?

This function looks for an integer 'key' in a given vector from a position 'start'. It returns the position of key if it finds it. But if it does not find key, it should return -1.
However, it is only returning -1 as the output. The function works fine if the else statement is removed, but obviously I need it.
So what is wrong in this function? Please explain in simple terms, I am new to C++. Thank you for all your help.
int Sequential_Search(const vector<int>&v, int key, int start){
int result = 0;
int i;
for(i = start; i < v.size(); i++){
if(v[i] == key){
result = i;
}
else{
result = -1;
}
}
return result;
}
This is pretty easy to understand:
for(i = start; i < v.size(); i++){
if(v[i] == key){
result = i;
}
else{
result = -1;
}
}
Let's say your vector contains [1, 2, 3, 4] and you search 2 starting at index 0: here is what your code is doing:
i = 0: (v[i] : 1) == 2 -> false: result = -1
i = 1: (v[i] : 2) == 2 -> true: result = 1
i = 2: (v[i] : 3) == 2 -> false: result = -1
i = 3: (v[i] : 4) == 2 -> false: result = -1
When you've found your value, you still continue to read other value whereas you should stop.
Either using break or directly returning (return i) in the v[i] == key condition;
Either by checking result in the for condition (result == -1 && i < v.size())
Per comment remark: the case with break and return (the last one is not so hard):
int Sequential_Search(const vector<int>&v, int key, int start){
int result = -1; // important for 'break'
for(int i = start; i < v.size(); i++){
if(v[i] == key){
result = i; break;
}
}
return result;
}
int Sequential_Search(const vector<int>&v, int key, int start){
for(int i = start; i < v.size(); i++){
if(v[i] == key){
return i;
}
}
return -1;
}
When the loop finds the key, it sets result = i - but it doesn't stop looping. On the next iteration, v[i] is likely not equal to key, and the loop resets result to -1. The function returns -1 unless key just happens to match the last element.
The reason this is failing with the else statement is because there are many scenarios that the key would not be the last item in the vector.
If the key is 3 and the vector of ints if <1,3,4>, the for loop will loop through 3 times total. On the first iteration, it will go into the else statement since we did not find the key at the 0th index. Result is -1. On the second iteration, we found the key! Set result to i = 1. The third iteration will go into the else statement again, and set the result back to -1.
To fix this, you can use 'break' to leave the for loop as soon as you find result. Set result to I and then follow that with break; This will ensure that if the result is found, you will not go into the else statement again and reset it to -1.

Return Statement positioning

I am writing some function which basically takes in input a range and a 1D vector. It looks at each number in the range of values given of the vector such that:
1) If the number to the left of it is 0 they swap positions.
2) If the number to the left of it is equal to it they add.
Now up till now this was good. The issue arises when I am trying to add return statements:
1) It should return True after all iterations are complete and at least one of the if conditions is entered in each iteration.
2) It should return false after all iterations are complete and none of the conditions are entered.
Now if I put these return statements in the loops they would terminate this function here but this is not desirable since it needs to go through all the iterations first. Is the current code comparable with this or do I need to redo it in a different manner ( if not where could the return statements go?)
bool proc_num(std::vector<int>&v, int LB, int UB) {
bool check = false;
for( int i=LB+2 ; i<UB; i++) {
for(int j = i-1; j>LB; j--) {
if(v[j] == 0){
v[j] = v[i];
check = true;
} else if(v[j] == v[i]) {
v[j]= v[j]+v[i];
v[i] = 0;
check = true;
}
}
}
return check;
}
You can simply add a boolean to make sure that at least one of the if conditions are entered.

While-loop evaluation condition

Sorry if the question seems really trivial but I'm just learning how to code and this one kept me in front of the computer for about 2 hours without getting to realize why this happens.
I'll pass the code below.
So, in order to keep it straightforward:
isPrime() is a function that just checks if a current number is Prime or not.
nPrime() is a function that returns the n-ism prime number, given N as the parameter.
The key point here is the main function and, more precisely, the number value in the first while-loop.
If you run this code, when it reaches the last prime number by which number is divisible, it'll enter an infinite loop. This can be easily solved if you just change the first while condition from while(number > 0) to while(number > 1).
That's the weird thing I can't come to realize:
If the inner second while-loop won't exit as long as number % nPrime(index) != 0 and the last instruction of the outter first while-loop is number /= nPrime(index);, how come the program enters an infinite loop?
That last instruction set number's value to 0, so the first while-loop condition should return false and exit the loop.
What am I missing?
Thank you all for your time and patience.
PS: I got downvoted and I don't know why, so I'll make an clarification:
I've done the research. As far as I know, every source seems to agree on the same point:
the > condition returns true if and only if left operand is greater than right operand.
Which takes me to the previously written question: if number is equal to 0, how's the while-loop not evaluating the number > 0 as false and exiting from the iteration?
#include <iostream>
using namespace std;
bool isPrime(int);
int nPrime(int);
int main() {
int number = 264;
if (number > 0)
{
int index = 1;
while(number > 0)
{
while (number % nPrime(index) != 0)
{
index++;
}
cout << nPrime(index) << endl;
number /= nPrime(index);
}
}
else
cout << "Error";
return 0;
}
bool isPrime(int n)
{
bool isPrime = false;
int totalDividends = 0;
for (int i = 1; i <= n; ++i)
{
if (n % i == 0)
totalDividends++;
}
if(totalDividends == 2)
isPrime = true;
return isPrime;
}
int nPrime(int n)
{
int result = 0;
for (int i = 0; i < n; ++i)
{
do
{
result++;
} while (!isPrime(result));
}
return result;
}
What am I missing?
That last instruction set number's value to 0
No it doesn't, it never gets that far. When number equals one then number % nPrime(index) != 0 is always true, so the inner while loop never exits.
Your understanding of while loops is perfect, it's your understanding of what your own code does that is in error. This is normal for bugs like this.

bug in c++ program count no of 1's in vector

A question was asked to me during an online interview.
They provided a piece of code and we have to find out a possible bug in the code.
The code is provided below as it is.
The function is provided with a non empty zero indexed vector of integers (which contains only 1 and 0).
The function will return the start position of longest sequence of 1's.
for example if the input values {0,0,0,1,1,1,1,1,0,0,1,1,1,0,1,1} it will return 3 because the longest sequence of 1's is from position 3 to 7 total five consecutive 1's.
if the input values are {0,0,1} then it will return 2 because there is only one 1 and length of longest sequence of 1 is one.
If there are no 1's then it will return -1.
The input vector can be changed so we can't change the signature of the vector to const.
I tested this function with variable no of inputs and I found out that it is working fine.
I am not able to find out any bug in the code. But the instruction says that there is a bug in the code and we can change maximum 2 lines of code to solve the bug.
int solution(vector<int>& A) {
int n = A.size();
int i = n - 1;
int result = -1;
int k = 0;
int maximal = 0;
while (i > 0) {
if (A[i] == 1) {
k = k + 1;
if (k >= maximal) {
maximal = k;
result = i;
}
} else {
k = 0;
}
i = i - 1;
}
if (A[i] == 1 && k + 1 > maximal)
result = 0;
return result;
}
To fix UB for empty case, I add check for !A.empty(),
and I profit of that to replace i by 0 (at that point i == 0)
and to replace the check with maximal value to have a coherent result for tie:
if (!A.empty() && A[0] == 1 && k + 1 >= maximal)
And as I may change an other line, I would fix the prototype as A is not modified.
int solution(const std::vector<int>& A) {
problem specifications are that
1.vector is immutable and
2.Input vector is not empty
I tried same problem in Java but different approach to see what is missing because i cant find any bug in above code.
package javaapplication7;
/**
*
* #author Owner
*/
public class JavaApplication7 {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
int[] A={0,1,0,1,1,1,1};
System.out.println(solution(A));
}
static int solution(int A[]){
int i=0,count=0,max=0,pos=-1;
while(i<=A.length-1)
{
if(A[i]==1)
{
count++;
i=i+1;
}
else
{
i=i+1;
count=0;
}
if(count>max)
{
pos=i-count;
max=count;
}
}
if(count==0)
return pos;
else
return pos;
}
}
the given code will favor a sequence closer to the left side if two sequences are of equal length. that doesn't happen for the checking of index 0
if (A[i] == 1 && k + 1 > maximal)
should be
if (A[i] == 1 && k + 1 >= maximal)

BFS maze help c++

I am attempting to make a maze-solver using a Breadth-first search, and mark the shortest path using a character '*'
The maze is actually just a bunch of text. The maze consists of an n x n grid, consisting of "#" symbols that are walls, and periods "." representing the walkable area/paths. An 'S' denotes start, 'F' is finish. Right now, this function does not seem to be finding the solution (it thinks it has the solution even when one is impossible). I am checking the four neighbors, and if they are 'unfound' (-1) they are added to the queue to be processed.
The maze works on several mazes, but not on this one:
...###.#....
##.#...####.
...#.#.#....
#.####.####.
#F..#..#.##.
###.#....#S.
#.#.####.##.
....#.#...#.
.####.#.#.#.
........#...
What could be missing in my logic?
int mazeSolver(char *maze, int rows, int cols)
{
int start = 0;
int finish = 0;
for (int i=0;i<rows*cols;i++) {
if (maze[i] == 'S') { start=i; }
if (maze[i] == 'F') { finish=i; }
}
if (finish==0 || start==0) { return -1; }
char* bfsq;
bfsq = new char[rows*cols]; //initialize queue array
int head = 0;
int tail = 0;
bool solved = false;
char* prd;
prd = new char[rows*cols]; //initialize predecessor array
for (int i=0;i<rows*cols;i++) {
prd[i] = -1;
}
prd[start] = -2; //set the start location
bfsq[tail] = start;
tail++;
int delta[] = {-cols,-1,cols,+1}; // North, West, South, East neighbors
while(tail>head) {
int front = bfsq[head];
head++;
for (int i=0; i<4; i++) {
int neighbor = front+delta[i];
if (neighbor/cols < 0 || neighbor/cols >= rows || neighbor%cols < 0 || neighbor%cols >= cols) {
continue;
}
if (prd[neighbor] == -1 && maze[neighbor]!='#') {
prd[neighbor] = front;
bfsq[tail] = neighbor;
tail++;
if (maze[neighbor] == 'F') { solved = true; }
}
}
}
if (solved == true) {
int previous = finish;
while (previous != start) {
maze[previous] = '*';
previous = prd[previous];
}
maze[finish] = 'F';
return 1;
}
else { return 0; }
delete [] prd;
delete [] bfsq;
}
Iterating through neighbours can be significantly simplified(I know this is somewhat similar to what kobra suggests but it can be improved further). I use a moves array defining the x and y delta of the given move like so:
int moves[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
Please note that not only tis lists all the possible moves from a given cell but it also lists them in clockwise direction which is useful for some problems.
Now to traverse the array I use a std::queue<pair<int,int> > This way the current position is defined by the pair of coordinates corresponding to it. Here is how I cycle through the neighbours of a gien cell c:
pair<int,int> c;
for (int l = 0;l < 4/*size of moves*/;++l){
int ti = c.first + moves[l][0];
int tj = c.second + moves[l][1];
if (ti < 0 || ti >= n || tj < 0 || tj >= m) {
// This move goes out of the field
continue;
}
// Do something.
}
I know this code is not really related to your code, but as I am teaching this kind of problems trust me a lot of students were really thankful when I showed them this approach.
Now back to your question - you need to start from the end position and use prd array to find its parent, then find its parent's parent and so on until you reach a cell with negative parent. What you do instead considers all the visited cells and some of them are not on the shortest path from S to F.
You can break once you set solved = true this will optimize the algorithm a bit.
I personally think you always find a solution because you have no checks for falling off the field. (the if (ti < 0 || ti >= n || tj < 0 || tj >= m) bit in my code).
Hope this helps you and gives you some tips how to improve your coding.
A few comments:
You can use queue container in c++, its much more easier in use
In this task you can write something like that:
int delta[] = {-1, cols, 1 -cols};
And then you simple can iterate through all four sides, you shouldn't copy-paste the same code.
You will have problems with boundaries of your array. Because you are not checking it.
When you have founded finish you should break from cycle
And in last cycle you have an error. It will print * in all cells in which you have been (not only in the optimal way). It should look:
while (finish != start)
{
maze[finish] = '*';
finish = prd[finish];
}
maze[start] = '*';
And of course this cycle should in the last if, because you don't know at that moment have you reach end or not
PS And its better to clear memory which you have allocate in function