equal jump between numbers in two arrays - c++

I want to compare two arrays. One of them is a subset of the other one. I want my function to return the minimum and equal gap between the numbers of the first subset array in the other array.
For example if I have
arr1 = 2,1,4,2,8,3
sub= 1,2,3
I want my function to return 1 because the mimimum gap between all this numbers are 1.
arr1 = 2,1,5,2,1,2,3
sub= 1,2,3
I want my function to return 0 because the mimimum gap between 1,2,3 in arr1 is 0
Here is the code I am trying to do: My code always return 0 can you help me understand why, and how can I solve this.
int gap(int* arr, int* sub, int sizeArr, int sizeSub)
{
int index = 0; int gap = 0; bool flag = true;
int i = -1;
for (int jump = 1; jump < sizeArr / sizeSub; jump++)
{
index = 0;
for (i = i +1; i < sizeArr; i++)
{
if (sub[index] == arr[i])
{
for (int j = i + jump, index = 1; j < sizeArr; j = j + jump, index++)
{
if (arr[j] != sub[index]) { flag = false; break; }
else if (arr[j] == sub[index] && index == sizeSub) { flag = true; break; }
}
}
if (!flag) { break; }
else { gap = jump; break; }
}
}
return gap;
}

You initially took gap equally 0 but i think more suit to not store gap
and start iterate jump from 0. And return jump immediately after you found that it is suit.
Also i think that store index in such manner as you it is bad idea, because you code return wrong answer on
int a[] = { 2,1,4,4,2,8,5,3 };
int s[] = { 1,2,3 };
I think you should declare variable as soon as possible, otherwise there will be undesirable side effects.
So you code can be rewritten as
int gap(int *arr, int *sub, int sizeArr, int sizeSub)
{
for (int jump = 0; 1 + (jump + 1) * (sizeSub - 1) <= sizeArr; jump++) {
for (int start_index = 0; start_index + (jump + 1) * (sizeSub - 1) < sizeArr; start_index++) {
bool flag = true;
for (int index = 0; index < sizeSub; ++index) {
if (arr[start_index + index * (jump + 1)] != sub[index]) {
flag = false;
break;
}
}
if (flag) {
return jump;
}
}
}
return -1; //or some value that indicate that there is no answer
}

Related

C++ Getting a "Control may reach end of a non-void function on a Johnson-Trotter code

What can I do to silence this warning? Do I need to add another return statement somewhere or do I need to change something within the functions?
Also could someone help me add arrows into the Johnson-Trotter algorithm. It would be nice to have them to show the direction but I am very confused on how to do it; though this isn't the main concern right now I just want the program to run. Thank you in advance.
These are the two functions with the warning:
int searchArr(int k[], int n, int mobile)
{
for(int i = 0; i < n; i++)
{
if (k[i] == mobile)
{
return i + 1;
}
}
}
int printOnePerm(int k[], bool dir[], int n)
{
int mobile = getMobile(k, dir, n);
int pos = searchArr(k, n, mobile);
if (dir[k[pos - 1] - 1] == RIGHT_TO_LEFT)
{
swap(k[pos - 1], k[pos -2]);
}
else if (dir[k[pos - 1] - 1] == LEFT_TO_RIGHT)
{
swap(k[pos], k[pos -1]);
}
for(int i = 0; i < n; i++)
{
if (k[i] > mobile)
{
if (dir[k[i] - 1] == LEFT_TO_RIGHT)
{
dir[k[i] - 1] = RIGHT_TO_LEFT;
}
else if(dir[k[i] - 1] == RIGHT_TO_LEFT)
{
dir[k[i] - 1] = LEFT_TO_RIGHT;
}
}
}
for(int i = 0; i < n; i++)
{
cout << k[i];
}
cout << endl;
}
For the first function, searchArr(), one question is what do you expect it to return if the value is not found. Since the return values are in the range [1,n], I'm guessing that zero means not found.
I prefer to design functions which have a single return at the end, whenever possible. A default fail value can be set at the start of the function. I would exit the loop when the value is found, or fall through with the default value set.
Here is what I would write:
int searchArr(int k[], int n, int mobile)
{
int ret = 0; /* not found value */
for(int i = 0; i < n; i++)
{
if (k[i] == mobile)
{
ret = i + 1;
break;
}
}
return ret;
}
Alternately, and perhaps a bit more obscurely, if the value is not found in the array, then i will equal n when the for loop completes. This would be a possible function:
int searchArr(int k[], int n, int mobile)
{
for(int i = 0; i < n; i++)
{
if (k[i] == mobile)
{
break;
}
}
if (i < n)
return i + 1;
else
return 0;
}
The for loop can be shrunk to
for(int i = 0; i < n && k[i] != mobile; i++) ;
And the return can be shrunk to
return (i < n) ? i + 1 : 0;
Although I generally discourage using the ?: operator.
As mentioned above, the second function doesn't return any value and should be declared "void".
The first one:
int searchArr(int k[], int n, int mobile)
{
for(int i = 0; i < n; i++)
{
if (k[i] == mobile)
{
return i + 1;
}
}
}
will not return anything if for some reason nothing in your array matches. In that case, you need to return a default or error value:
int searchArr(int k[], int n, int mobile)
{
for(int i = 0; i < n; i++)
{
if (k[i] == mobile)
{
return i + 1;
}
}
return -1; // not found
}
The second one doesn't seem to want to return anything. In C++, the way to do this is with a void, not an int (That was okay in C. C++ not so much):
// assuming we don't want to return anything
void printOnePerm(int k[], bool dir[], int n)

Dividing an array into the greatest amount of parts with equal sums

The array can hold negative numbers. I've written this code using recursion. First I'm summing the first i elements and then I'm checking for each such sum if the rest of the array (starting from i + 1) can be divided with this sum.
It works for some cases but not for others. I've noticed that it doesn't work if there's a prime somewhere.
It works if I sort the array in descending order beforehand but I don't understand why.
In this case the output is 2, while it should be 0.
#include <iostream>
const int N = 5;
int tab[N] = {1, 2, 3, 3, 4};
// returns the number of partitions with a given sum (or 0 if it can't be partitioned)
int divisions(int tab[N], int p, int sum) {
if (N < 2) return 0;
if (p == N) {
return 1;
}
int s_sum = tab[p++];
while (s_sum != sum && p < N) {
s_sum += tab[p++];
}
if (s_sum == sum) {
return divisions(tab, p, sum) + 1;
} else {
return 0;
}
}
// creates all the possible sums and returns the greatest number of partitions where each partition sums up to some sum
int compareAllDivisions(int tab[N]) {
int maxResult = 0;
for (int i = 0; i < N; ++i) {
int sum = 0;
for (int j = 0; j <= i; ++j) {
sum += tab[j];
}
int result = divisions(tab, i + 1, sum);
if (maxResult < result) {
maxResult = result;
}
}
if (maxResult >= 2) {
return maxResult;
} else {
return 0;
}
}
int main() {
std::cout << compareAllDivisions(tab) << std::endl;
return 0;
}
It is because of return value of if (s_sum == sum) part.
It should be changed like below
if (s_sum == sum) {
int ret = divisions(tab, p, sum);
if(ret == 0) return 0;
else return ret + 1;
} else {
return 0;
}
Your return value of divisions is 0 when can't make and pos number when can make.
So, let's consider when 0 returns in there. It can't make at the back, but it will return pos number!

Ending OpenMP for prematurely

I have a problem with writing a routine in C++ using OpenMP for. The code of the routine is as follows:
int sudokuSolution [9][9];
bool solvep(int s[9][9], int row, int col) {
bool solution = false;
#pragma omp parallel for
for (int val = 1; val < 10; val++) {
if (isPossible(s,row,col,val)) {
s[row][col] = val;
if (solve(s, row + col / 9, (col + 1) % 9)) {
sudokuSolution[row][col] = val;
solution = true;
}
}
}
return solution;
}
when running this routine without the parallel clause, everything works fine (i.e. routine returns true every time it's called). However, when I use the parallel for, it sometimes returns false. I wasn't able to figure out, why is this happening and the only way of removing this bug is from my perspective ending the whole parallel block prematurely after solution is set to true. However, if I did my research properly, there is no way to prematurely end a parallel block. Could you please suggest me an alternative?
EDIT: Adding minimal functioning example as requested:
#include <omp.h>
#include <iostream>
#include <list>
#include <chrono>
using namespace std;
bool solutionFound = false;
int sudoku [9][9] = { 5,7,0,9,0,0,0,0,8,
0,0,0,0,0,5,0,3,9,
0,0,0,0,0,0,2,0,4,
0,0,0,0,9,0,6,8,0,
0,0,0,8,0,2,0,0,0,
0,5,2,0,7,0,0,0,0,
6,0,5,0,0,0,0,0,0,
7,9,0,4,0,0,0,0,0,
2,0,0,0,0,9,0,7,6};
int sudokuSolution [9][9];
bool isPossible(int s[9][9], int row, int col, int val) {
for(int i = 0; i < 9; i++) {
if (s[row][i] == val)
return false;
if (s[i][col] == val)
return false;
if (s[row / 3 * 3 + i / 3][col / 3 * 3 + i % 3] == val)
return false;
}
return true;
}
bool solve(int s[9][9], int row, int col) {
while(s[row][col] != 0) {
col = (col + 1) % 9;
row = row + col / 8;
if(row == 9)
return true;
}
for (int val = 1; val < 10; val++) {
if (isPossible(s,row,col,val)){
sudokuSolution[row][col] = val;
s[row][col] = val;
if (solve(s, row + col / 9, (col + 1) % 9))
return true;
sudokuSolution[row][col] = 0;
s[row][col] = 0;
}
}
return false;
}
bool solvep(int sa[9][9], int row, int col) {
int s [9][9];
for(int i = 0; i < 9; i++)
for(int j = 0; j < 9; j++)
s[i][j] = sa[i][j];
while(s[row][col] != 0) {
col = (col + 1) % 9;
row = row + col / 8;
if(row == 9)
return true;
}
bool solution = false;
#pragma omp parallel for
for (int val = 1; val < 10; val++) {
if(!solutionFound) {
if (isPossible(s,row,col,val)){
s[row][col] = val;
if (solve(s, row + col / 9, (col + 1) % 9)) {
sudokuSolution[row][col] = val;
solutionFound = true;
solution = true;
}
}
}
}
return solution;
}
int main() {
for (int k = 0; k < 100; k++) {
for(int i = 0; i < 9; i++)
for(int j = 0; j < 9; j++)
sudokuSolution[i][j] = sudoku[i][j];
solutionFound = false;
solvep(sudokuSolution,0,0);
bool calcResult = solvep(sudoku,0,0);
cout << calcResult;
}
return 0;
}
You have many race conditions in your code, both in the loop itself and the solve function. In code that is executed in parallel you must not write to to shared data (s, solution, sudokuSolution) and especially global variables (solutionFound). You will have to go back to your learning material and catch up with data races and the methods to protect against them.
With some experience it is easy to spot the issues in the loop itself. It's much harder to spot in called functions - which is why its so important to give a complete example in your question. Try to define your interfaces such that mutable no shared data is passed to functions. Conceptually you will have to have a copy of the board for each thread to perform backtracking in parallel.
Once you fix the issues with writing to the board, you can use atomic writes, a critical region or a reduction to "share" the solution. But you have to consider both sudokuSolution[row][col] and solution. Logically I suppose sudokuSolution[row][col] != 0 == solution.
You could reduce the solution values on all threads using the || operator:
int sudokuSolution [9][9];
bool solvep(int s[9][9], int row, int col) {
bool solution = false;
#pragma omp parallel for reduction(||:solution)
for (int val = 1; val < 10; val++) {
if (isPossible(s,row,col,val)) {
s[row][col] = val;
if (solve(s, row + col / 9, (col + 1) % 9)) {
sudokuSolution[row][col] = val;
solution = true;
} else {
solution = false;
}
} else {
solution = false;
}
}
return solution;
}

c++ inserting and sorting "empty" array at the same time

I am still learning C++, so please if this is a duplicate point me to correct topic as I couldn't find any good and useful explanation.
I try to create a function in my ascending_ordered_array class which will insert elements into "empty" array sorting them in the same time.
Below is my code so far, but unfortunately it doesn't work 100% correctly as it adds two largest numbers as a last for positions in array.
void ascOrderedArray::push(Datatype p_item, Datatype* p_array, int p_size)
{
int i, j = 0;
int temp, num;
if (p_array[j] < 0)
p_array[j] = p_item;
for (i = 0; i < (p_size - 1); i++)
{
num = p_size;
for (j = (p_size - 1); j >= i; j--)
{
if (p_array[num]> p_array[j])
num = j;
}
temp = p_array[num];
p_array[num] = p_item;
p_array[i] = temp;
}
}
Here is part of main which call function above trying place random numbers into it
for (i = 0; i < size; i++)
{
num = (i + 1)* (rand() % 100);
arr.push(num, arr, size);
}
any hints what I am missing out?
This is code I wrote and its work as long as it is no resize neccessary
void ascOrderedArray::push(Datatype p_item)
{
//check if array is big enough and resize it if necessary
if (m_numElements >= m_size)
resize();
//checking if array contains some elements and if not set its first to pased item
if (m_numElements == 0)
{
m_array[0] = p_item;
m_numElements++;
return;
}
else
{
int i = m_numElements;
while (i >= 0 && i <= m_numElements)
{
//shifting array elements
m_array[i] = m_array[i - 1];
if (p_item > m_array[i - 1])
{
m_array[i] = p_item;
break;
}
--i;
}
m_numElements++;
}
}

C/C++ How can I get unique value from 2 arrays?

I need to get the unique value from 2 int arrays
Duplicate is allowed
There is just one unique value
like :
int arr1[3]={1,2,3};
int arr2[3]={2,2,3};
and the value i want to get is :
int unique[]={1}
how can i do this?
im already confused in my 'for' and 'if'
this was not homework
i know how to merge 2 arrays and del duplicate values
but i alse need to know which array have the unique value
plz help me :)
and here is some code i did
int arr1[3]={1,2,3}
int arr2[3]={2,2,3}
int arrunique[1];
bool unique = true;
for (int i=0;i!=3;i++)
{
for (int j=0;j!=3;j++)
{
if(arr1[i]==arr2[j])
{
unique=false;
continue;
}
else
{
unique=true;
}
if(unique)
{
arrunique[0]=arr1[i]
break;
}
}
cout << arrunique[0];
Assuming:
You have two arrays of different length,
The arrays are sorted
The arrays can have duplicate values in them
You want to get the list of values that only appear in one of the arrays
including their duplicates if present
You can do (untested):
// Assuming arr1[], arr2[], and lengths as arr1_length
int i = 0,j = 0, k = 0;
int unique[arr1_length + arr2_length];
while(i < arr1_length && j < arr2_length) {
if(arr1[i] == arr2[j]) {
// skip all occurrences of this number in both lists
int temp = arr1[i];
while(i < arr1_length && arr1[i] == temp) i++;
while(j < arr2_length && arr2[j] == temp) j++;
} else if(arr1[i] > arr2[j]) {
// the lower number only occurs in arr2
unique[k++] = arr2[j++];
} else if(arr2[j] > arr1[i]) {
// the lower number only occurs in arr1
unique[k++] = arr1[i++];
}
}
while(i < arr1_length) {
// if there are numbers still to read in arr1, they're all unique
unique[k++] = arr1[i++];
}
while(j < arr2_length) {
// if there are numbers still to read in arr2, they're all unique
unique[k++] = arr2[j++];
}
Some alternatives:
If you don't want the duplicates in the unique array, then you can skip all occurrences of this number in the relevant list when you assign to the unique array.
If you want to record the position instead of the values, then maintain two arrays of "unique positions" (one for each input array) and assign the value of i or j to the corresponding array as appropriate.
If there's only one unique value, change the assignments into the unique array to return.
Depending on your needs, you might also want to look at set_symmetric_difference() function of the standard library. However, its treatment of duplicate values makes its use a bit tricky, to say the least.
#include <stdio.h>
#include <stdlib.h>
int cmp ( const void *a , const void *b )
{
return *(int *)a - *(int *)b;
}
int main()
{
int arr1[5] = {5,4,6,3,1};
int arr2[3] = {5, 8, 9};
int unique[8];
qsort(arr1,5,sizeof(arr1[0]),cmp);
printf("\n");
qsort(arr2,3,sizeof(arr2[0]),cmp);
//printf("%d", arr1[0]);
int i = 0;
int k = 0;
int j = -1;
while (i < 5 && k < 3)
{
if(arr1[i] < arr2[k])
{
unique[++j] = arr1[i];
i++;
}
else if (arr1[i] > arr2[k])
{
unique[++j] = arr2[k];
k++;
}
else
{
i++;
k++;
}
}
//int len = j;
int t = 0;
if(i == 5)
{
for(t = k; t < 3; t++)
unique[++j] = arr2[t];
}
else
for(t = i; t < 5; t++)
unique[++j] = arr2[t];
for(i = 0; i <= j; i++)
printf("%d ", unique[i]);
return 0;
}
This is my codes,though there is a good answer .
I didn't realize the idea that know which array have the unique value.
I also think that the right answer that you chose didn't , either.
Here is my version of the algorithm for finding identical elements in sorted arrays on Python in C ++, it works in a similar way
def unique_array(array0 : (int), array1 : (int)) -> (int):
index0, index1, buffer = 0, 0, []
while index0 != len(array0) and index1 != len(array1):
if array0[index0] < array1[index1]:
buffer.append(array0[index0])
index0 += 1
elif array0[index0] > array1[index1]:
buffer.append(array1[index1])
index1 += 1
else:
index0 += 1; index1 += 1
buffer.extend(array0[index0 : len(array0)])
buffer.extend(array1[index1 : len(array1)])
return buffer