Recursion questions - c++

I'm making a sudoku solver using recursion and I'm having some problems. I put comments next to my vables and functions to try to make this as clear as possible. Does my logic sound like this would work? Everything else in my code works. It's just the solver/recursion it that is not.
bo
boourn
f nt j=0; j < 9; j++)
rowc c=0;
8) //if row is past 8 then the board is done
return true;
for (int < 10; i++)
{
nextr r; //save next row and col
next;
tcol++; /ncrement next col and row
(nextcol >8) {
nextcol =0;
nx
if(ncol==0 && nextrow ==9)
r(0, 0
}

As of your comment reply, Yes:
Code it properly.
Use methods as they should be used and name them properly.
Have InitilalizeBoard fill all zeros.
Have SetBoard put the start values on the board.
Have SolveBoard try to solve it.
It's a good programming habit to have each method do 1 thing, and make it's name clear.
Having said that, I did something similar a couple of years ago. It's much easier, faster, and takes less code to solve the sudoku with brute force approach using for/while loops, than doing it with recursion, or even coding it to be efficient and try to solve it like a human would (remove options that are obviously wrong and so on).
So, depending on your end result, you might want to code it appropriately ... (I did it to refresh my C++, so didn't care doing it the hard, long way first, and then doing it the short way).

The solver function you provided actually views the whole array, and - provided the other functions used in the code work correctly - should actually solve the puzzle. If you substitute cout << " TRUE TRUE "<<endl; for cout << "["<<r<<"]["<<c<<"]: "<<i<<endl;, you'll notice all indexes are checked.
So the problem must be in either one of the 3 functions you didn't provide code for: row_valid, col_valid or panel_valid.
Note: I don't think using recursion in this particular problem is a good idea. You probably should just do it using a for to check and solve the board. That would be both faster and easier.
Edit after first post was updated
The row_valid and col_valid functions aren't quite valid. You can't check the c !=i part, because it'll make all checks false. Change the if statements to this:
if (v == rowcol[i][c] && v!=0)
and
if (v == rowcol[r][j] && v!=0)
also you need to change the solver a bit:
bool sudoku :: solver(int r, int c) {
while( r < 9 && rowcol[r][c] !=0) {
c++;
if ( c>8) {
c=0;
r++;
}
if (r > 8) {
return true;
}
}
for (int i=1; i < 10; i++)
{
int nextrow, nextcol;
if (row_valid (r, c, i)&& col_valid(r, c, i)&& panel_valid(r,c, i)) {
rowcol[r][c]=i;
nextrow=r; //save next row and col
nextcol=c;
nextcol++; //increment next col and row
if (nextcol >8) {
nextcol =0;
nextrow++;
}
if(nextcol==0 && nextrow ==9) {
return true; //then it's done
}
if (solver(nextrow,nextcol)) {
return true;
}
else{
rowcol[r][c]=0;
}
}
}
return false;
}
This seems to work for me and give me an output of:
1 2 3 4 5 6 7 8 9
4 5 6 7 8 9 1 2 3
7 8 9 1 2 3 4 5 6
2 1 4 3 6 5 8 9 7
3 6 5 8 9 7 2 1 4
8 9 7 2 1 4 3 6 5
5 3 1 6 4 2 9 7 8
6 4 2 9 7 8 5 3 1
9 7 8 5 3 1 6 4 2

Related

Getting funny output for insertion sort

I'm trying to implement insertion sort. My logic may be wrong because I was unable to complete my code due to some error.
I want help with values changing absurdly while executing. Also, there is a similar repeating element question but it is in python and it went over my head. so, please don't mark it duplicate.
As you can see I have initialized a temporary variable index, why you ask? because the value of N is changing during run time.
secondly, Value is getting repeated when sorting is taking place.
I'm using codeblocks 17.2.
#include<iostream>
#include<utility>
#include<algorithm>
using namespace std;
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
int arr[100];
int N,index;
cin>>N;
for(int i=0;i<N;i++)
{
cin>>arr[i];
}
index=N; // using temperory variable
for(int l=0;l<index;l++)
{
for(int j=l+1;j>=0;j--)
{
if(l==index-1 || j==0) //Working fine now
break;
if(arr[j]<arr[j-1])
{
swap(arr[j],arr[j-1]);
}
}
cout<<N<<endl; //value of n is changing but why
for(int k=0;k<index;k++)
{
cout<<arr[k]<<" "; //value of array is also coming wrong
}
cout<<"\n";
}
return 0;
}
N=7
and elements of the array to be
7 8 5 2 4 6 3
output is
7 //these are the values of N which is changing
7 8 5 2 4 6 3
5
7 7 8 2 4 6 3
2
5 7 7 8 4 6 3
2
4 5 7 7 8 6 3
2
4 5 6 7 7 8 3
2
3 4 5 6 7 7 8
0
2 3 4 5 6 7 7
check for boundary condition and when non-existing array index is accessed it will give undefined behavior. In this case, it appears that N was stored right before arr and it changed when you modified arr[-1].

Problem with my quicksort, it doesn't sort correctly

OK I am trying to make Prima algorithm so i need my edges array sorted, I tried to use quicksort here but it didn't work as I planned.
#include <iostream>
using namespace std;
void Sort (int arr[100][4], int m, int l) {
int i,j,x,v;
i=m;
j=l;
x=(i+j)/2;
do
{
while (((arr[i][3]<arr[x][3]))and(i<=l)) i++;
while (((arr[j][3]>arr[x][3]))and(j>=m)) j--;
if (i<=j)
{
v=arr[i][1];
arr[i][1]=arr[j][1];
arr[j][1]=v;
v=arr[i][2];
arr[i][2]=arr[j][2];
arr[j][2]=v;
v=arr[i][3];
arr[i][3]=arr[j][3];
arr[j][3]=v;
i++;
j--;
}
}
while (i<=j);
if (i<l) Sort(arr,i,l);
if (m<j) Sort(arr,m,j);
}
int main () {
int i,x,y,z,n,m;
int a[100][4];
fill(&a[0][0],&a[0][0]+400,0);
cout<<"Enter number of nodes and edges\n";
cin>>n>>m;
cout<<"Enter edges and their weights\n";
for (i=0;i<m;i++) {
cin>>x>>y>>z;
a[i][1]=min(x,y);
a[i][2]=max(x,y);
a[i][3]=z;
}
Sort (a,0,m-1);
for (i=0;i<m;i++) {
cout<<i+1<<") "<<a[i][1]<<' '<<a[i][2]<<' '<<a[i][3]<<endl;
}
return 0;
}
what I put is
5 10
1 2 4
1 3 7
4 1 5
5 1 8
2 3 3
2 4 6
2 5 6
3 4 8
3 5 2
4 5 4
what I get is
1) 3 5 2
2) 2 3 3
3) 1 4 5
4) 1 2 4
5) 4 5 4
6) 2 5 6
7) 2 4 6
8) 1 3 7
9) 1 5 8
10) 3 4 8
I don't understand why 5 is going ahead of 4's. Hope you could help.
You choose the pivot element in the middle of the (sub)array, which is fine, but you leave it in that position when you run the partitioning loop, and rely on it to stay there, which is not ok. With your approach, the pivot is likely to be swapped to a different position during the ordinary course of partitioning, after which the remainder of the partitioning will be based on the key swapped into the pivot's original position, which is likely to be different.
The usual approach is to start by swapping the pivot element to one end of the array or the other, partition the rest of the array, and then afterward swap the pivot into its correct position, as discovered via the partitioning process.
Change the code to use the pivot value instead of the pivot index, and some fixes to make it more like conventional Hoare partition scheme:
i=m-1;
j=l+1;
x=arr[(i+j)/2][3];
while(1)
{
while (arr[++i][3] < x);
while (arr[--j][3] > x);
if(i >= j)
return j;
// ...

Unexpected behaviour/bug in function to find radical of an integer [duplicate]

This question already has answers here:
std::pow with integer parameters, comparing to an integer type
(4 answers)
Closed 5 years ago.
I have written a short C++ function which is trying to return similar to the the radical of an integer, but instead the smallest integer which is some root of the the given number. The general logic is that the function decomposes the integer into prime powers, looks for the gcd of all the exponents of the prime powers, then finds the radical by dividing all the exponents by this gcd. I thought the function was working as intended, however I noticed that when passing the function 13 as an argument it returns 12, I have put the output for 2 to 20 below; everything is correct apart from 13. When trying to debug this both "primes" and "powers" hold the correct values (13 and 1 respectively, both vectors of size 1) as well as "power" being 1 as it should. So the problem must be in the last loop, but I am really very confused as to what could be happening as it should be calculating pow(13, 1/1).
#include<vector>
#include<cmath>
int radical(int n){
int power = 0;
std::vector<int> primes;
std::vector<int> powers;
for(int i = 2; n != 1 ; ++i){
int t_pow = 0;
while(n % i == 0){
++t_pow;
n /= i;
}
if(t_pow != 0){
primes.push_back(i);
powers.push_back(t_pow);
}
power = (power == 0 ? t_pow : gcd(power, t_pow));
}
int rad = 1;
for(unsigned i = 0u; i < primes.size(); ++i){
rad *= pow(primes.at(i), powers.at(i)/power);
}
return rad;
}
2 2
3 3
4 2
5 5
6 6
7 7
8 2
9 3
10 10
11 11
12 12
13 12
14 14
15 15
16 2
17 17
18 18
19 19
20 20
EDIT: The most efficient way to implement an integer based power function pow(int, int)
The naive algorithm looks pretty simple actually:
rad = 1
i = 1
While n > 1:
increase i
if i divides n:
multiply rad by i
while i divides n, divide n by i
You're already performing all these steps, the fact is you're doing much more than that (and using much more space), so why not just get rid of unnecessary actions?
define your own int powi(int,int) function and check if the error petsists

Why does my multidimensional vector only push_back 0 index?

I having a problem using push_back(), I can't figure out why only the first cols vector is just pushed over and over again.
Input
10 9 10 3 100 8 7 10 73 9 10 5 9 87 -1 8 3 7 10 92 6 10 6 83 9 11 8 8 77 -1 10 10 10 10 100 10 10 10 100 10 10 10 10 100 -1 DONE
C++
(...)
size = numbers.size();
counter = 0;
square = ceil(sqrt(size));
vector < vector <int> > rows;
vector<int> cols;
do {
for (int i = 0; i < square; ++i) {
cols.push_back(numbers[counter]);
cout << cols[i] << " ";
++counter;
}
rows.push_back(cols);
cout << endl;
} while (counter <= size);
(...)
Undesirable Output
0: 10 9 10 3 100 8 7
1: 10 9 10 3 100 8 7
2: 10 9 10 3 100 8 7
3: 10 9 10 3 100 8 7
4: 10 9 10 3 100 8 7
5: 10 9 10 3 100 8 7
6: 10 9 10 3 100 8 7
rows[1][2] should be 73, not 9. Where have I gone wrong?
You never reset cols. Instead you just keep adding on to it. I think you are printing rows out with magic number indices, which is why you do not spot the added portion. Either declare a temporary cols inside the loop or call clear after each push_back().
awesomeyi found your main problem. But your code has other issues too.
There is a buffer overflow. For example if size == 4 then square == 2
and we get:
after iter #1: counter == 2; continue since 2 <= 4
after iter #2: counter == 4; continue since 4 <= 4
iter #3: reads numbers[4] and numbers[5] - oops!
The loop condition should be:
while (counter + square <= size);
we need to make sure that the next iteration will complete without overflowing the vector. It would be smart to use .at() for vector access so that if you did make a miscalculation, then the error will behave nicely instead of going screwball.
The loop (minus the output) could actually be written as:
for (size_t counter = 0; counter + square <= size; counter += square )
{
std::vector<int> cols( numbers.begin() + counter, numbers.begin() + counter + square );
rows.push_back(cols);
}

How to display Non Diagonal 2D Array elements

I am successful in displaying Diagonal Array elements, but failed to display Non Diagonal array elements I tried a lot but unsuccessful. Here is the code what I am try with I am using Turbo C++ -
#include<conio.h>
#include<iostream.h>
void accept(int a[4][4],int size)
{
cout<<"Diagonal One:";
for (int i=0;i<size;i++)
for(int j=0;j<size;j++)
if (i!=j)
cout<<"\n"<<i <<" "<<j<<" "<<a[i][j];
}
void main()
{
int a[4][4]={{5,4,3,4},{6,7,9,1},{8,0,3,7},{2,4,5,9}};
clrscr();
accept(a,4);
getch();
}
Example : if the array content is
5 4 3 4
6 7 9 1
8 0 3 7
2 4 5 9
Output through the function should be :
4 3 6 1 8 7 4 5
Output is displaying some of the diagonal elements also.
The function skips all elements in the diagonal 5739 (i != j takes care of this), but, based on the desired output, you also wish to skip all elements in the diagonal 4902.
To also check for the other diagonal, replace
if (i != j)
with
if (i != j && i != size-j-1)
Test.