Sudoku generation: it goes in loop - c++

I'm trying to wiriting a sudoku generator algorithm, this is my c++ code:
void generateSudoku(num sudoku[][N])
{ int i,j,k;
int vett[N],n,old;
//clean the sudoku matrix filling it with -1
for(i=0;i<N;i++)
for(j=0;j<N;j++)
sudoku[i][j].val=-1;
//generate the sudoku
for(i=0;i<N;){
for(j=0;j<N;){
k=0;
clean(vett,N); //fills the vector with -1
old=sudoku[i][j].val; //saves the actual value
do{
if(k<9){
do{
n=rand()%9+1;
}while(find(vett,N,n)); //generate n while it already exists in vett
vett[k++]=n;
if((!(exists(sudoku,i,j,n))) && (n!=old)){ //if it not exists on row, column and sub-matrix and it's different between the old value, it's OK
sudoku[i][j++].val=n;
if(j==N) i++;
k=10;
}
}
else{
sudoku[i][j].val=-1;
if(j>0) j--;
else if(i>0){
j=N-1;
i--;
}
k=10;
}
}while(k<=9);
}
}
}
It goes in loop and I know the reason:
2 7 6 | 9 1 3 | 4 5 8
4 3 9 | 5 7 2 | * *
In this example it continues to generate 6-1 and then 1-6 where there are * and it never finishes. But even if I comprend why it loops, I don't know the best way to correct it. Can someone help me?

You have to backtrack further. There's no valid entry in the last cell of that second row. I'm not sure a greedy algorithm is going to work as sudoku generator. I'd try with a stack-tree based approach instead.

Following may help (untested) :
void restore(std::vector<int>& v) {
v.clear();
for (int i = 0; i != 9; ++i) {
v.push_back(1 + i);
}
}
void generate(int (&sudoku)[9][9])
{
std::vector<int> allowedSymbols[9][9];
bool succeed = true;
for(int i = 0, j = 0; i != 9; ) {
if (succeed) {
restore(allowedSymbols[i][j]);
succeed = false;
}
while (!allowedSymbols[i][j].empty()) {
int index = rand() % allowedSymbols[i][j].size();
if (!exists(sudoku, i, j, allowedSymbols[i][j][index])) { //if it not exists on row, column and sub-matrix, it is OK
succeed = true;
break;
}
allowedSymbols[i][j].erase(allowedSymbols[i][j].begin() + index);
}
if (succeed) {
++j;
if (j == 9) {
j = 0;
++i;
}
} else {
// backtrack.
--j;
if (j == -1) {
j = 8;
--i;
}
allowedSymbols[i][j].erase(std::find(allowedSymbols[i][j].begin(),
allowedSymbols[i][j].end(),
sudoku[i][j]));
}
}
}

Related

Generate numbers from 2 to 10,000. The numbers printed can only be a multiple of 2 prime numbers

Homework: I'm just stumped as hell. I have algorithms set up, but I have no idea how to code this
Just to be clear you do not need arrays or to pass variables by reference.
The purpose of the project is to take a problem apart and using Top-Down_Design or scratch pad method develop the algorithm.
Problem:
Examine the numbers from 2 to 10000. Output the number if it is a Dual_Prime.
I will call a DualPrime a number that is the product of two primes. Ad where the two primes are not equal . So 9 is not a dual prime. 15 is ( 3 * 5 ) .
The output has 10 numbers on each line.
My Algorithm set-up
Step 1: find prime numbers.:
bool Prime_Number(int number)
{
for (int i = 2; i <= sqrt(number); i++)
{
if (number % 1 == 0)
return false;
}
return true;
}
Step 2: store prime numbers in a array
Step 3: Multiply each array to each other
void Multiply_Prime_Numbers(int Array[], int Size)
{
for (int j = 0; j < Size- 1; j++)
{
Dual_Prime[] = Arr[j] * Arr[j + 1]
}
}
Step 4: Bubble sort
void Bubble_Sort(int Array[], int Size) // Sends largest number to the right
{
for (int i = Size - 1; i > 0; i--)
for (int j = 0; j < i; j++)
if (Array[j] > Array[j + 1])
{
int Temp = Array[j + 1];
Array[j + 1] = Array[j];
Array[j] = Temp;
}
}
Step 5: Display New Array by rows of 10
void Print_Array(int Array[], int Size)
{
for (int i = 0; i < Size; i++)
{
cout << Dual_Prime[i] << (((j % 10) == 9) ? '\n' : '\t');
}
cout << endl;
}
I haven't learned dynamic arrays yet,
Although dynamic arrays and the sieve of Eratosthenes are more preferable, I tried to write minimally fixed version of your code.
First, we define following global variables which are used in your original implementation of Multiply_Prime_Numbers.
(Please check this post.)
constexpr int DP_Size_Max = 10000;
int DP_Size = 0;
int Dual_Prime[DP_Size_Max];
Next we fix Prime_Number as follows.
The condition number%1==0 in the original code is not appropriate:
bool Prime_Number(int number)
{
if(number<=1){
return false;
}
for (int i = 2; i*i <= number; i++)
{
if (number % i == 0)
return false;
}
return true;
}
In addition, Multiply_Prime_Numbers should be implemented by double for-loops as follows:
void Multiply_Prime_Numbers(int Array[], int Size)
{
for (int i = 0; i < Size; ++i)
{
for (int j = i+1; j < Size; ++j)
{
Dual_Prime[DP_Size] = Array[i]*Array[j];
if(Dual_Prime[DP_Size] >= DP_Size_Max){
return;
}
++DP_Size;
}
}
}
Then these functions work as follows.
Here's a DEMO of this minimally fixed version.
int main()
{
int prime_numbers[DP_Size_Max];
int size = 0;
for(int j=2; j<DP_Size_Max; ++j)
{
if(Prime_Number(j)){
prime_numbers[size]=j;
++size;
}
}
Multiply_Prime_Numbers(prime_numbers, size);
Bubble_Sort(Dual_Prime, DP_Size);
for(int i=0; i<DP_Size;++i){
std::cout << Dual_Prime[i] << (((i % 10) == 9) ? '\n' : '\t');;
}
std::cout << std::endl;
return 0;
}
The Sieve of Eratosthenes is a known algorithm which speeds up the search of all the primes up to a certain number.
The OP can use it to implement the first steps of their implementation, but they can also adapt it to avoid the sorting step.
Given the list of all primes (up to half the maximum number to examine):
Create an array of bool as big as the range of numbers to be examined.
Multiply each distinct couple of primes, using two nested loops.
If the product is less than 10000 (the maximum) set the corrisponding element of the array to true. Otherwise break out the inner loop.
Once finished, traverse the array and if the value is true, print the corresponding index.
Here there's a proof of concept (implemented without the OP's assignment restrictions).
// Ex10_TwoPrimes.cpp : This file contains the 'main' function. Program execution begins and ends there.
#include "pch.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
void Homework_Header(string Title);
void Do_Exercise();
void Sieve_Of_Eratosthenes(int n);
void Generate_Semi_Prime();
bool Semi_Prime(int candidate);
bool prime[5000 + 1];
int main()
{
Do_Exercise();
cin.get();
return 0;
}
void Do_Exercise()
{
int n = 5000;
Sieve_Of_Eratosthenes(n);
cout << endl;
Generate_Semi_Prime();
}
void Sieve_Of_Eratosthenes(int n)
{
// Create a boolean array "prime[0..n]" and initialize
// all entries it as true. A value in prime[i] will
// finally be false if i is Not a prime, else true.
memset(prime, true, sizeof(prime));
for (int p = 2; p*p <= n; p++)
{
// If prime[p] is not changed, then it is a prime
if (prime[p] == true)
{
// Update all multiples of p
for (int i = p * p; i <= n; i += p)
prime[i] = false;
}
}
}
bool Semi_Prime(int candidate)
{
for (int index = 2; index <= candidate / 2; index++)
{
if (prime[index])
{
if (candidate % index == 0)
{
int q = candidate / index;
if (prime[q] && q != index)
return true;
}
}
}
return false;
}
void Generate_Semi_Prime()
{
for (int i = 2; i <= 10000; i++)
if (Semi_Prime(i)) cout << i << "\t";
}

Magic square backtracking and recursion C++

I'm trying to solve the problem of the magic square in C ++ using Backtracking and recursion in C ++. Specifically for a 4x4 array.
An example of 4x4 magic square solution is as follows, in which each row, column and diagonal add 34:
The change that I have is this: The user enters some values that will start the algorithm.
My algorithm is this:
here you can appreciate better the image.
I have a notion of how the algorithm should work to solve the problem of the magic square with backtracking and recursion, but I've had problems.
One of them is:
Achievement not make my algorithm "ignore" the values that the user already entered.
My code in C++ is in this link in Github. And here is the code :
#include <iostream>
using namespace std;
int sudoku[4][4];
int row = 0;
int column = 0;
bool isFull(int s[4][4]){
for(int i = 0; i < 4; i++){
for(int j = 0; j < 4; j++){
if(s[4][4] == 0){
return false;
}
}
}
return true;
}
void printMatrix(int s[4][4]){
for(int i = 0; i < 4; i++){
for(int j = 0; j < 4; j++){
cout << sudoku[i][j] << " ";
}
cout << endl;
}
}
bool isAssigned(int row, int column){
if(row == 1 && column == 0 ||
row == 0 && column == 2 ||
row == 1 && column == 2){
return true;
} else return false;
}
bool verify(int s[4][4], int row, int column){
bool flag = false;
int sumrow = 0, sumcolumn = 0, sumDiagonal = 0, sumDiagonal2 = 0;
int value = 3;
for(int i = 0; i < 4; i++){
sumrow = sumrow + s[row][i];
sumcolumn = sumcolumn + s[i][column];
sumDiagonal = sumDiagonal + s[i][i];
sumDiagonal2 = sumDiagonal2 + s[i][value];
value--;
}
if(sumrow <= 34 && sumcolumn <= 34 && sumDiagonal2 <= 34 && sumDiagonal2 <= 34){
return true;
} else return false;
}
bool backtracking(int s[4][4], int row, int column){
if(isFull(s) == true){ //verify if there are no zeros in the matrix
printMatrix(sudoku);
cout<<"Solution find ";
}
else {
if(isAssigned(row, column) == false){ // verify if the cell is already assigned
for(int i = 1; i <= 16; i++){
s[row][column] = i; // assigned value
if(verify(s, row, column) == true){ // verify that the sum of the column, row and diagonal not greater 34
if(column == 4) {
row++;
column=0;
}
backtracking(s, row, column + 1); // recursion
printMatrix(s); // Print the matrix to see progress
cout<<endl;
} else { // the sum value exceeds 34
s[row][column] = 0;
return false;
}
}
}
}
}
int main(){
sudoku[1][0] = 5;
sudoku[0][2] = 15;
sudoku[1][2] = 10;
backtracking(sudoku, row, column);
return 0;
}
My algorithm is mainly the following:
Obviously some features in this case, but if you see my code you will realize what I try to do.
Perhaps my solution method does not work or is not good.
The reason for this publication is, I need help to improve or Need help to solve the code did. Here is my main function and output I get to run:
bool backtracking(int s[4][4], int row, int column){
if(isFull(s) == true){ //verify if there are no zeros in the matrix
printMatrix(sudoku);
cout<<"Solution find ";
}
else {
if(isAssigned(row, column) == false){ // verify if the cell is already assigned
for(int i = 1; i <= 16; i++){
s[row][column] = i; // assigned value
if(verify(s, row, column) == true){ // verify that the sum of the column, row and diagonal not greater 34
if(column == 4) {
row++;
column=0;
}
backtracking(s, row, column + 1); // recursion
printMatrix(s); // Print the matrix to see progress
cout<<endl;
} else { // the sum value exceeds 34
s[row][column] = 0;
return false;
}
}
}
}
}
output:
3 16 15 0
5 0 10 0
0 0 0 0
0 0 0 0
as I said before, I have problems when I find a value that the user was already assigned.
It is the first time working with backtracking, that is why I find it a bit difficult. Thanks for all.
Well, yes,
Had to do something similar lately, some places to get this "fixed"
Start with a bitmap (1-16) for the numbers already assigned in the grid. ie. those the user entered are already marked as being "used".
Only assign numbers to the grid that haven't been marked in that bitmap. If you use non-recursive methods, need to use a stack to know which have been tested to "unset" when backtracking. If using recursive methods (only 16 deep recursion ;) ) pass the bitmap and the already placed square as copies, not references ;)

Recursive Sudoku solver almost working but getting stack overflow for empty grid

I'm trying to solve Sudoku by recursive. The program working great. The problem is that the stack is only keep-able of 4-6K recursive. That's mean that if I'm leaving the soduku with more than 6-7 empty cells, the combination needed to solve it is:
4^7 = 16384 > 4-5K...
How can I improve my program to work with less calls? The program is working good out of this problem. The function:
void solve_soduku(int soduku[][N*N], int &row, int &col, const bool fix_v[][N*N])
is all the business.
I give you here all the numbers you need for correct soduku to not wast your time. You can some of them out and see how it's work:
0 0 1
0 1 2
0 2 3
0 3 4
1 0 4
1 1 3
1 2 2
1 3 1
2 0 3
2 1 1
2 2 4
2 3 2
3 0 2
3 1 4
3 2 1
3 3 3
-1
and the code:
#include <iostream>
using namespace std;
const int N = 2;
void zero_soduku(int soduku[][N*N]);
void zero_arr(int temp_arr[], int size);
void get_input(int soduku[][N*N], bool fixed_values[][N*N]);
void solve_soduku(int soduku[][N*N], int &row, int &col, const bool fix_v[][N*N]);
bool check_soduku(const int soduku[][N*N]);
bool check_rows(const int soduku[][N*N]);
bool check_cols(const int soduku[][N*N]);
bool check_sub_interval(const int soduku[][N*N]);
void print_soduku(const int soduku[][N*N]);
int main() {
int soduku[N*N][N*N] = { 0 }, row = 0, col = 0;
bool fixed_values[N*N][N*N] = { false };
get_input(soduku, fixed_values);
solve_soduku(soduku, row, col, fixed_values);
cout << endl;
print_soduku(soduku);
system("pause");
return EXIT_SUCCESS;
}
bool check_soduku(const int soduku[][N*N]) {
if (check_rows(soduku) && check_cols(soduku) && check_sub_interval(soduku))
return true;
return false;
}
bool check_rows(const int soduku[][N*N]) {
int temp_arr[N*N] = { 0 };
for (auto i = 0; i < N*N; i++) {
zero_arr(temp_arr, N*N);
for (auto j = 0; j < N*N; j++)
temp_arr[soduku[i][j] - 1]++;
for (auto k = 0; k < N*N; k++)
if (temp_arr[k]>1)
return false;
}
return true;
}
bool check_cols(const int soduku[][N*N]) {
int temp_arr[N*N] = { 0 };
for (auto i = 0; i < N*N; i++) {
zero_arr(temp_arr, N*N);
for (auto j = 0; j < N*N; j++)
temp_arr[soduku[j][i] - 1]++;
for (auto k = 0; k < N*N; k++)
if (temp_arr[k]>1)
return false;
}
return true;
}
bool check_sub_interval(const int soduku[][N*N]) {
int temp_arr[N*N] = { 0 };
for (auto rows_intervals = 0; rows_intervals < N; rows_intervals++)
for (auto cols_intervals = 0; cols_intervals < N; cols_intervals++)
for (auto i = rows_intervals*N; i < rows_intervals*N + N; i++)
for (auto j = cols_intervals*N; j < cols_intervals*N + N; j++) {
temp_arr[soduku[i][j] - 1]++;
//end of interval, check if !good interval
if (i == rows_intervals*N + N - 1 && j == cols_intervals*N + N - 1) {
for (auto k = 0; k < N*N; k++)
if (temp_arr[k]>1)
return false;
zero_arr(temp_arr, N*N);
}
}
return true;
}
void solve_soduku(int soduku[][N*N], int &row, int &col, const bool fix_v[][N*N]) {
static int counter = 0;
counter++;
cout << endl << counter << endl;
//Not empty cell
if (soduku[row][col] != 0)
//Not end of line
if (col < N*N - 1) {
col++;
solve_soduku(soduku, row, col, fix_v);
}
else
//Not end of rows
if (row < N*N - 1) {
row++;
col = 0;
solve_soduku(soduku, row, col, fix_v);
}
else
//end of soduku
if (check_soduku(soduku)) {
print_soduku(soduku);
return;
}
/////// Finishd soduku but answaer not good //////////////////
else
//Last cell not max
if (soduku[row][col] < N*N - 1) {
soduku[row][col]++;
print_soduku(soduku);
cout << endl;
solve_soduku(soduku, row, col, fix_v);
}
//Last cell max, going back...
else {
while (soduku[row][col] == N*N || fix_v[row][col]) {
if (!fix_v[row][col]) {
soduku[row][col] = 1;
print_soduku(soduku);
cout << endl;
}
if (col > 0) {
col--;
continue;
}
if (col == 0 && row > 0) {
col = N*N - 1;
row--;
}
}
if (!fix_v[row][col]) {
soduku[row][col]++;
print_soduku(soduku);
cout << endl;
}
solve_soduku(soduku, row, col, fix_v);
}
//////////////////////////////////////////////////////////////////////////
//Empty cell
else {
soduku[row][col]++;
print_soduku(soduku);
cout << endl;
solve_soduku(soduku, row, col, fix_v);
}
}
void zero_arr(int temp_arr[], int size) {
for (auto i = 0; i < size; i++)
temp_arr[i] = 0;
}
void zero_soduku(int soduku[][N*N]) {
for (int i = 0; i < N*N; i++)
for (int j = 0; j < N*N; j++)
soduku[i][j] = 0;
}
void get_input(int soduku[][N*N], bool fixed_values[][N*N]) {
cout << endl << "Please enter locatin and nums into soduku: ";
int row = 0, col, value;
while (row != -1) {
cin >> row;
if (row == -1)
return;
cin >> col >> value;
soduku[row][col] = value;
fixed_values[row][col] = true;
}
}
void print_soduku(const int soduku[][N*N]) {
for (auto i = 0; i < N*N; i++)
for (auto j = 0; j < N*N; j++) {
cout << soduku[i][j] << " ";
if (j == N*N - 1)
cout << endl;
}
//system("pause");
}`enter code here`
Your algorithm appears to be, roughly:
1) Try each move in turn
2) Check the entire board to see if it's valid
3) Repeat until the entire board is filled
This is obviously very inefficient. The code will be making many moves which are illegal, then only realizing this belatedly, after fact.
I would suggest that you completely get rid of this, and attempt to implement something a little bit more efficient. Try to think how carbon-based life forms solve sudoku puzzles, and implement the same algorithm. Do you also do the above approach, when you solve a sudoku puzzle? Of course not. You do something like this:
1) For each position on the board, instead of storing just the current number in that position, if any, also store additional information: namely, if there is no number in that position, also store all possible numbers which would legal moves for that position.
For a completely empty board, for example, each position on the sudoku board would contain all values 1-9. From this, we then make the next logical step:
2) When making a move and placing a value in some position, say 4, you will remove the value 4 from all other cells in its 3x3 square, and remove 4 from all other cells in the same row and column. Because that number will no longer be a valid move in those cells. Conversely, when undoing a move, and removing the 4 from the cell, this means that the value 4 is now legal in all cells in its 3x3 square, and its row and column, so you would put this value in all of those positions, as a number that's now a legal move in those positions.
3) When deciding which next move to make, scan the board first, looking for any cell that has only one possible legal number. This means, of course, that this is the only legal move for that cell, so you make it.
4) If you find any cell that has no legal values left, this means that you reached an unsolvable state, so you'll undo your last move, and then try the next valid move from that point on.
5) Otherwise, you should just pick one of the cells that has the fewest possible legal moves left, make the first move, then keep going, then if you reach an unsolvable state, and return to this move, you undo it, and try the next move.
This seems to me an approach that should be much more efficient, as it should end up making the least number of illegal moves.
It is also closely mimics how carbon-based lifeforms solve sudoku puzzles by themselves.
P.S. To initialize a new sudoku puzzle with prefilled numbers, just start with an empty sudoku board, with all cells allowing all numbers 1-9 as legal moves, then make each move, as described above, to fill in the initial numbers on the sudoku board.

3 X 3 magic square recursively

I'm trying to find all possible solutions to the 3X3 magic square.
There should be exactly 8 solutions.
My code gets them all but there are a lot of repeats. I'm having a hard time tracking the recursive steps to see why I'm getting all the repeats.
// This program finds all solutions to the magic square for a 3X3
// square where each column, row and diagonal sum is equal
#include <iostream>
using namespace std;
#define SQUARE_SIZE 9
int anyLine = 0;
int currLine = 0;
int numSolutions = 0;
// swap two values in the square.
void swap(int arr[], int idxa, int idxb)
{
int tmp = arr[idxa];
arr[idxa] = arr[idxb];
arr[idxb] = tmp;
}
void printArray(int arr[])
{
for (int i = 0; i < SQUARE_SIZE; i++)
{
cout << arr[i] << " ";
if ((i + 1) % 3 == 0)
cout << endl;
}
cout << endl;
}
// this function tests to see if we have a "good" arrangement of numbers
// i.e the sum of each row, column and diagonal is equal
bool checkArr(int arr[])
{
anyLine = arr[0] + arr[1] + arr[2];
currLine = 0;
for (int i = 0; i < SQUARE_SIZE; i++)
{
currLine += arr[i];
if ((i + 1) % 3 == 0)
{
if (currLine != anyLine)
return false;
currLine = 0;
}
}
// check vertically
for (int col = 0; col <3; col++)
{
for (int row = 0; row <3; row++)
{
currLine += arr[col + 3 * row];
}
if (currLine != anyLine)
return false;
currLine = 0;
}
// check the diagonals
if ((arr[2] + arr[4] + arr[6]) != anyLine)
return false;
if ((arr[0] + arr[4] + arr[8]) != anyLine)
return false;
return true;
}
void solve(int arr[], int pos)
{
if (pos == 8)
{
if (checkArr(arr))
{
printArray(arr);
numSolutions++;
}
} else
{
for (int i = 0; i < 9; i++)
{
if (i == pos) continue;
if (checkArr(arr))
{
printArray(arr);
numSolutions++;
}
swap(arr, pos, i);
solve(arr, pos + 1);
}
}
}
int main()
{
int arr[SQUARE_SIZE] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
solve(arr, 0);
cout << "number of solutions is: " << numSolutions << endl;
return 0;
}
Basically, you are finding all permutations of the array using a recursive permutation algorithm.
There are 4 things you need to change:
First, start your loop from pos, not 0
Second, swap elements back after recursing (backtracking)
Third, only test once you have generated each complete permutation (when pos = 8), or else you will be testing the same permutations more than once.
Fourth, swapping an element with itself (i.e. not swapping it) is a valid permutation, because the elements are allowed to stay in their original positions.
void solve(int arr[], int pos)
{
if (pos == 8)
{
if (checkArr(arr))
{
printArray(arr);
numSolutions++;
}
}
else
{
for (int i = pos ; i < 9; i++)
{
swap(arr,pos,i);
solve(arr,pos +1);
swap(arr,pos,i);
}
}
}
Demo
Your code calls printArray from two places - the base case of the recursion (i.e. when pos == 8) and in the loop before calling swap. The second call is unnecessary: you would get the same square when you reach the pos == 8 state.
This brings the number of duplicates down, but it does not eliminate them because of the way in which you generate your squares. You need to keep track of what has been printed. One way to do it is to make a set of solutions that you have found, and check it before printing the newly found solution:
set<int> seen;
int key(int arr[]) {
return arr[0]
+ 10 * arr[1]
+ 100 * arr[2]
+ 1000 * arr[3]
+ 10000 * arr[4]
+ 100000 * arr[5]
+ 1000000 * arr[6]
+ 10000000 * arr[7]
+ 100000000 * arr[8];
}
void printArray(int arr[]) {
if (!seen.insert(key(arr)).second) {
// second is set to false when a duplicate is found
return;
}
numSolutions++;
for (int i = 0; i < SQUARE_SIZE; i++) {
cout << arr[i] << " ";
if((i+1) % 3 == 0)
cout << endl;
}
cout << endl;
}
Demo.
A few things to note about the solution above:
key(int[]) converts the square to a single decimal number, so this approach is going to work only for squares composed of decimal digits. You would need a different strategy for arbitrary numbers - for example, using a set of comma-separated strings.
Counting of solutions is moved to printArray(int[]). You could drop numSolutions altogether, and use seen.size() instead; it provides the same answer.
If you don't want to actually solve this recursively for exercise purposes, I'd recommend using std::next_permutation:
void solve(int(&arr)[SQUARE_SIZE], int pos)
{
sort(std::begin(arr), std::end(arr));
do {
if (checkArr(arr)) {
numSolutions++;
printArray(arr);
}
} while (next_permutation(begin(arr), end(arr)));
}

Extracting a subsequence from an array

I'm trying to solve an algorithm for extracting a subsequence from an array. It should display the longest subsequence of prime numbers. I have written the whole algorithm but I still get an infinite cycle and I can't figure out where and why. I'm incrementing both indices and modifying the first index at the end, but it is still not working. Thanks a lot !!!
P.S: citire reads the array, prim detects if a number is prime or composed, afisare displays the subsequence and detSecv determines the longest subsequence.
#include <iostream>
#include <math.h>
using namespace std;
void citireSecv(int &n,int x[50])
{
cout<<"Da n: ";
cin>>n;
for(int i=1;i<=n;i++)
{
cout<<"Da un nr: ";
cin>>x[i];
}
}
int prim(int n)
{
int d=2;
while(d<=sqrt(n) && n%d!=0)
{
if(d==2)
d=3;
else
d=d+2;
}
if(d>sqrt(n)) return 1;
else return 0;
}
void afisare(int n,int x[50],int st,int f)
{
for(int i=st;i<=f;i++)
cout<<x[i]<<" ";
}
void detSecv(int n,int x[100],int &st,int &f)
{
st=1; f=0;
int i=1,j;
while(i<=n-1)
{
while(i<=n-1)
{
if(prim(x[i])==0 && prim(x[i+1])==0) i++;
}
j=i+1;
while(j<=n-1)
if(prim(x[j])==0 && prim(x[j+1])==0) j++;
if((j-i) > (f-st))
{
st=i;
f=j;
}
i=j+1;
}
}
int main()
{
int n,x[100],st,f;
citireSecv(n,x);
detSecv(n,x,st,f);
afisare(n,x,st,f);
return 0;
}
Input data:
n=2
First number is: 5
Second number is: 7
Probably just one of many issues with that code:
while(i<=n-1)
{
if(prim(x[i])==0 && prim(x[i+1])==0) i++;
}
j=i+1;
while(j<=n-1)
if(prim(x[j])==0 && prim(x[j+1])==0) j++;
There are two potential infinite loops here. If the conditions in the while don't return true on the first iteration, i (or j) will never get incremented, and you will have your infinite loop. You should almost always increment such variables outside of any conditions.
With a slight change in your code, you make it work, and one thing, you don't need to start array with index 1. you can always start with index zero.
for(int i=1;i<=n;i++)
{
cout<<"Da un nr: ";
cin>>x[i];
}
try to check for a case when no prime subsequence is found, while printing.
void detSecv(int n, int *x, int &start, int &end)
{
start = -1;
end = -1;
int i=0,j;
while(i < n) {
if(prim(x[i])) {
j = i + 1;
while(j < n)
if(prim(x[j])) j++;
else break;
} else {
i++;
continue;
}
if((j-i) > (end - start)) {
start = i;
end = j-1;
}
i=j+1;
}
}
This is a better way to verify if a number is prime or not
bool IsPrime(int number) {
int primeStep = 2;
double stepLimit = sqrt(number);
while(primeStep <= stepLimit)
{
if(number % primeStep == 0)
return false;
primeStep += 1;
}
return true;
}
And nou you can apply that function for each number in your array, and if it's prime , you add it in a new array like this:
void detSecv(int numberOfItems,int *arrayOfNumbers)
{
int arrayOfPrimeNumbers[50] = {};
int index = 0;
for(int i = 0; i < numberOfItems; i++)
{
if(IsPrime(arrayOfNumbers[i])){
arrayOfPrimeNumbers[index] = arrayOfNumbers[i];
index += 1;
}
}
int secondIndex = 0;
while(arrayOfPrimeNumbers[secondIndex] != 0)
{
cout << arrayOfPrimeNumbers[secondIndex] << " ";
secondIndex += 1;
}
}