C++ Divide and conquer algorithm problems - c++

I have just learnt about Divide and Conquer algorithm and I'm a little bit confused about it. The question is my homework, I have tried many ways to fix my code but it did not run.
#include <iostream>
using namespace std;
void inputArray(int* a, int& n)
{
cout << "Input n:";
cin >> n;
for (int i = 0; i < n; i++)
{
cout << "input a[" << i << "]= ";
cin >> a[i];
}
}
int sumeven(int* a, int l, int r)
{
if (l == r && a[l] % 2 == 0)
{
return a[l];
}
int mid = (l + r) / 2;
int s1 = sumeven(a, l, mid);
int s2 = sumeven(a, mid + 1, r);
return s1 + s2;
}
int main()
{
int n;
int a[20];
inputArray(a, n);
cout<<sumeven(a, 0,n-1);
return 0;
}

Try to test your programs without user input first:
#include <iostream>
using namespace std;
int sumeven(int* a, int l, int r)
{
if (r >= 6) return 0;
if (l > r ) return 0;
if (l >= r)
{
if (a[l] % 2 == 0)
{
return a[l];
}
else
{
return 0;
}
}
int mid = (l + r) / 2;
int s1 = sumeven(a, l, mid);
int s2 = sumeven(a, mid + 1, r);
return s1 + s2;
}
int main()
{
int n=6;
int a[6]={1,2,3,48,5,6};
cout<<sumeven(a,0,n-1);
return 0;
}

Related

Is there a reason this is wrong?

#include <iostream>
#include <bits/stdc++.h>
#include <numeric>
using namespace std;
int
gcd (int a, int b)
{
if (a == 0)
return b;
return gcd (b % a, a);
}
int
phi (unsigned int n)
{
unsigned int result = 1;
for (int i = 2; i < n; i++)
if (gcd (i, n) == 1)
result++;
return result;
}
int
gen_priv_n (int p1, int p2)
{
int n = phi (p1) * phi (p2);
return n;
}
int
gen_pub_n (int p1, int p2)
{
int n = (p1 * p2);
return n;
}
int
gen_priv_key (int n, int e)
{
int x = (phi (e) * n + 1) / e;
return x;
}
int
encrypt (int n, int e, int data)
{
int crypt_data = int (pow (data, e)) % n;
return crypt_data;
}
int
decrypt (int c, int d, int n)
{
int data = int (pow (c, d)) % n;
return data;
}
int
main ()
{
int ph1 = 53;
int ph2 = 59;
int e = 3;
int message = 89;
int pub_n = gen_pub_n (ph1, ph2);
cout << "PUBN " << pub_n << "\n";
int priv_n = gen_priv_n (ph1, ph2);
cout << "PRIVN " << priv_n << "\n";
int d = gen_priv_key (gen_priv_n (ph1, ph2), e);
cout << "PRIVKEY " << d << "\n";
int c = encrypt (pub_n, e, message);
cout << "ENCRYPTED " << c << "\n";
int data = decrypt (c, d, pub_n);
cout << "MESSAGE " << data;
}
The PUBN, PRIVN, PRIVKEY, and ENCRYPTED all return the expected numbers, however, the decrypt function should return 89(the message variable), but does not. I'm assuming an arithmetic error in the codes order of operations but I'm not sure. Can the issue be pointed out?
The results of the variables are:
PUBN 3127
PRIVN 3016
PRIVKEY 2011
ENCRYPTED 1394
MESSAGE -763 <-- unexpected result, should be 89
The decrypt (and encrypt) function is broken in that it (a) is exceeding platform representation of int, and (b) is unnecessarily using pow to do it in the first place.
In your trivial example you should be utilizing a technique called modulo chaining . The crux of this is the following.
(a * b) % n == ((a % n) * (b % n)) % n
In your case, you're performing simple exponentiation. That means, for example a^2 % n would be:
(a * a) % n = ((a % n) * (a % n)) % n
Similarly, a^3 % n is:
(a * a * a) % n = (((a % n) * (a % n)) % n) * (a % n)) % n
Using modulo chaining allows you to compute what would otherwise be very large product computation mod some N, so long as no product term pair exceeds your platform representation (and it doesn't in your case).
A trivial version of integer pow that does this is below:
int int_pow_mod(int c, int d, int n)
{
int res = 1;
// may as well only do this once
c %= n;
// now loop.
for (int i=0; i<d; ++i)
res = (res * c) % n;
return res;
}
Understand, this is no silver bullet. You can easily contrive a c that still produces a product exceeding INT_MAX, but in your case, that won't happen due to your choices of starting material. A general solution will employ this with a big-number library that allows exceeding platform int representation. Regardless, doing that should deliver what you seek, as shown below:
#include <iostream>
using namespace std;
unsigned int gcd(unsigned int a, unsigned int b)
{
if (a == 0)
return b;
return gcd(b % a, a);
}
int phi(unsigned int n)
{
unsigned int result = 1;
for (unsigned int i = 2; i < n; i++)
if (gcd(i, n) == 1)
result++;
return result;
}
int gen_priv_n(int p1, int p2)
{
int n = phi(p1) * phi(p2);
return n;
}
int gen_pub_n(int p1, int p2)
{
int n = (p1 * p2);
return n;
}
int gen_priv_key(int n, int e)
{
int x = (phi(e) * n + 1) / e;
return x;
}
int int_pow_mod(int c, int d, int n)
{
int res = 1;
// may as well only do this once
c %= n;
// now loop.
for (int i=0; i<d; ++i)
res = (res * c) % n;
return res;
}
int encrypt(int n, int e, int data)
{
int crypt_data = int_pow_mod(data, e, n);
return crypt_data;
}
int decrypt(int c, int d, int n)
{
int data = int_pow_mod(c, d, n);
return data;
}
int main()
{
int ph1 = 53;
int ph2 = 59;
int e = 3;
int message = 89;
int pub_n = gen_pub_n(ph1, ph2);
cout << "PUBN " << pub_n << "\n";
int priv_n = gen_priv_n(ph1, ph2);
cout << "PRIVN " << priv_n << "\n";
int d = gen_priv_key(gen_priv_n(ph1, ph2), e);
cout << "PRIVKEY " << d << "\n";
int c = encrypt(pub_n, e, message);
cout << "ENCRYPTED " << c << "\n";
int data = decrypt(c, d, pub_n);
cout << "MESSAGE " << data;
}
Output
PUBN 3127
PRIVN 3016
PRIVKEY 2011
ENCRYPTED 1394
MESSAGE 89

Wrong output in large inputs

Please help me out with this problem: https://cses.fi/problemset/task/1131/
I'm getting the wrong output for large values.
The algorithm is: computing the height of the left subtree and the right subtree by using an arbitrary node.
Thank you :)
#include <bits/stdc++.h>
#define int long long int
using namespace std;
bool visited[200005] = {false};
vector<vector<int>> vect(200005);
int height(int n) {
int m = 0, t=-1;
visited[n] = true;
for(auto x : vect[n]) {
if(visited[x] == false) {
t = height(x);
if(m < t)
m = t;
}
}
return m+1;
}
int treeDiameter(int n) {
int m1=0, m2=0, t=0;
visited[n] = true;
for(auto x : vect[n]) {
t = height(x);
if(t > m1) {
m2 = m1;
m1 = t;
}
else if(t > m2)
m2 = t;
}
return m1 + m2;
}
int32_t main() {
int n, m=999999;
cin >> n;
n--;
if(n > 1) {
while(n--) {
int a, b;
cin >> a >> b;
vect[a].push_back(b);
vect[b].push_back(a);
if(a < m) m = a;
}
// cout << m;
cout << treeDiameter(m);
} else cout << 0 << endl;
return 0;
}

binary search segmentation fault in c++

This works fine...the size of the array is just 7.
// item = search item
int bin(int arr[], int item, int startIndex, int endIndex)
{
if(startIndex <= endIndex)
{
int middle = 1 + (endIndex - startIndex) / 2;
if(item == arr[middle]) return middle;
if(item < arr[middle])
return bin(arr, item, startIndex, middle-1);
return bin(arr, item, middle + 1, endIndex);
}
return -1;
}
int main()
{
int sample[] = {1,2,3,4,5,6,7};
cout<< bin(sample,5,0,6) <<endl;
system("pause");
}
But after increasing the size of array and searching 19...it says segmentation fault.
int main()
{
int sample[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22};
// size of array is 22
cout<< bin(sample,19,0,21) <<endl;
system("pause");
}
Why is it like that? Do I have a semantic error?
Your middle calculation is wrong:
int middle = 1 + (endIndex - startIndex) / 2;
should be:
int middle = startIndex + (endIndex - startIndex) / 2;
You can use the following code:
#include <iostream>
using namespace std;
void Binary(int arr[], int n, int key)
{
int s = 0;
int e = n - 1;
while (s <= e) {
int mid = (s + e) / 2;
if (arr[mid] == key) {
cout << "Element Found At Index No. " << mid;
} else if (arr[mid] > key) {
e = mid - 1;
} else {
s = mid + 1;
}
}
}
int main()
{
int n;
cin >> n;
int arr[n];
for (int i = 0; i < n; i++) {
cin >> arr[i];
}
int key;
cout << "Enter element to be searched!";
cin >> key;
Binary(arr, n, key);
return 0;
}

Merge Sort C++ Incorrectly Sorting

I'm writing a program that will do 5 different sorting functions and compare times across them. I'm outputting the 1000th element of each array to see if it's sorted correctly, all of my other sorts except merge sort are producing the correct number. Merge sort is close but off, it is within an element or two of getting the correct answer (outputting 25011 rather than 25034 for the 1000th element.) Here is the code for my merge sort:
//Zach Heesaker. CS3. Project 4
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <stdio.h>
#include <ctime>
#include <cstdio>
#include <time.h>
#include <stdint.h>
#include<list>
#include<cmath>
using namespace std;
const int n = 10000;
int numswaps, numcompares;
void swap(int& a, int& b);
void print(int arr[], int n, ofstream& outf, double time);
void read(int arr[], int size);
void mergepass(int arr[], int y[], int& n, int& L);
void mergeSort(int arr[], int n);
void merge(int arr[], int y[], int L, int m, int n);
int main()
{
int numsorts = 5;
string whichsort;
ofstream outf("output.ot");
int arr[n + 1];
clock_t start, end;
double time;
outf << "Sort Name: " << setw(5) << " " << "1000th Element: " << setw(1) << " " << "Number of Moves: " << setw(1) << " " << "Time taken: " << endl;
read(arr, n);
numcompares = 0;
numswaps = 0;
start = clock();
mergeSort(arr, n);
end = clock();
time = double(end - start) / double(CLOCKS_PER_SEC);
}
void mergeSort(int arr[], int size)
{
int L = 1;
int y[n + 1];
while (L < n)
{
mergepass(arr, y, size, L);
L = 2 * L;
mergepass(y, arr, size, L);
L = 2 * L;
}
}
void merge(int arr[], int y[], int L, int m, int n)
{
int i, j, k, t;
i = L;
k = L;
j = m + 1;
while ((i <= m) && (j <= n))
{
numcompares++;
if (arr[i] <= arr[j])
{
numswaps++;
y[k++] = arr[i++];
}
else
{
numswaps++;
y[k++] = arr[j++];
}
}
if (i > m)
{
for (t = j; t <= n; t++)
{
numswaps++;
y[k + t - j] = arr[t];
}
}
else
{
for (t = i; t <= m; t++)
{
numswaps++;
y[k + t - i] = arr[t];
}
}
}
void mergepass(int arr[], int y[], int& n, int& L)
{
int i, t;
i = 1;
while (i <= n - 2 * L + 1)
{
merge(arr, y, i, i + L - 1, i + 2 * L - 1);
i = i + 2 * L;
}
if ((i + L - 1) < n)
{
merge(arr, y, i, i + L - 1, n);
}
else
{
for (t = i; t <= n; t++)
{
numswaps++;
y[t] = arr[t];
}
}
}
void swap(int& a, int& b)
{
int temp;
temp = a;
a = b;
b = temp;
numswaps += 3;
}
void print(int arr[], int n, ofstream& outf, double time)
{
outf << left << setw(6) << " " << left << arr[1000] << setw(12) << " " << left << numswaps << setw(10) << " " << left << "\t" << time << endl;
}
void read(int arr[], int size)
{
ifstream ifs("input.txt");
int i = 0;
while (!ifs.eof())
{
ifs >> arr[i];
i++;
}
}
int merge(int arr[], int left, int right)
{
int pivot = arr[right];
int k = (left - 1);
for (int j = left; j <= right - 1; j++)
{
numcompares++;
if (arr[j] < pivot)
{
k++;
swap(arr[k], arr[j]);
}
}
swap(arr[k + 1], arr[right]);
return (k + 1);
}
Any ideas as to what is going wrong in here? Thank you.

Merge and QuickSort - stack overloaded

Helo everyone. :)
I have to write a program where I have 4 types of sorting: bubble-, insertion-, merge- i quick-sort.
Program has to sort points x,y in array of structures (random) by amount of total of their coordinates //e.g.: (1,3) is less than (0,6) because 1+3<0+6//. It saves sorted ones in this same array and also in txt file with time of sorting by each B,I,M,Q-sort.
Code from Merge and MergeSort:
void Merge(Structure *tab, int A, int sr, int Z)
{
Structure *tmp = new Structure[Z];
int i;
for (i = A; i <= Z; ++i)
{
tmp[i] = tab[i];
}
i = A;
int j = sr + 1;
int q = A;
while (i <= sr && j <= Z)
{
if (Compare(tab, i, j)) //'Compare' tells if total of coordinates from tab[i] is bigger than total from tab[j]
{
tab[q] = tmp[i];
++j;
}
else
{
tab[q] = tmp[j];
++i;
}
++q;
}
if(i <= sr)
{
while (i <= sr)
{
tab[q] = tmp[i];
++i;
++q;
}
}
else
{
while(j <= Z)
{
tab[q] = tmp[j];
++j;
++q;
}
}
delete[] tmp;
}
void MergeSort(Structure *tab, int A, int Z)
{
int sr = (A + Z)/2;
if(A < Z)
{
MergeSort(tab, A, sr);
MergeSort(tab, sr + 1, Z);
Merge(tab, A, sr, Z);
}
}
And to QuickSort:
int DivideQS(Structure *tab, int A, int Z)
{
Structure tmp;
Structure pivot = tab[A]; // first el. for pivot (A=0)
int i = A, j = Z; //indexes in array
while (true)
{
while (Compare(tab, j, A))
j--;
while (!Compare(tab, i, A)) // until elements are lower than pivot, that's this '!' for
i++;
if (i < j) // swap when i < j
{
tmp = tab[i];
tab[i] = tab[j];
tab[j] = tmp;
i++;
j--;
}
else
return j;
}
}
void QuickSort(Structure *tab, int A, int Z)
{
int dziel;
if (A < Z)
{
dziel = DivideQS(tab, A, Z);
QuickSort(tab, A, dziel);
QuickSort(tab, dziel+1, Z);
}
}
My problem is a stack. No matter how big I make this, it still goes overloaded. I can't manage this problem. I don't know if that's because of mistake in code or it's somewhere else. Bubble and Insertion work impeccable.
I was looking for solving on many sites, in my language and foreign ones (I'm Pole), and modificating code in so many ways but still have no clue what to do.
Help me, please.
===================================
How could I be so blind! Thank you #user3187084. :D
But I think I went from bad to worse. Now I've received new error message:
Windows has triggered a breakpoint in Projekt_AiSD.exe.
This may be due to a corruption of the heap, which indicates a bug in Projekt_AiSD.exe or any >of the DLLs it has loaded.
This may also be due to the user pressing F12 while Projekt_AiSD.exe has focus.
The output window may have more diagnostic information.
And after that this showed to me: http://i40.tinypic.com/314qyl5.png
And this is code for checking:
#include <ctime>
#include <cstdlib>
#include <cstdio>
#include <Windows.h>
#include <string>
#include <fstream>
#include <sstream>
using namespace std;
struct Structure
{
int x;
int y;
};
bool Compare(Structure *tab, int i, int j)
{
if ( (tab[i].x + tab[i].y) > (tab[j].x + tab[j].y))
return true;
return false;
}
void LosujWspolrzedne(Structure* tab, int K)
{
srand(time(NULL));
for (int i = 0; i < K; i++)
{
tab[i].x = rand()%21;
tab[i].y = rand()%21;
}
//return;
}
void Save (Structure *tab, int K, string NazwaPliku)
{
ofstream zap(NazwaPliku);
for (int i = 0; i < K; i++)
{
zap << tab[i].x << ' ' << tab[i].y << endl;
}
zap.close();
}
void Load (Structure *tab, int K, string NazwaPliku)
{
ifstream wcz(NazwaPliku);
if (!wcz)
{
cout << "Can't open the file!!!" << endl;
exit(1);
}
for (int i = 0; i < K; ++i)
{
wcz >> tab[i].x >> tab[i].y;
}
wcz.close();
}
void Time(long long a, long long b, string NazwaPliku)
{
ofstream czas(NazwaPliku);
if (!czas)
{
cout << "Can't open the file!!!" << endl;
}
czas << (b - a) << " ms" << endl;
czas.close();
}
void CopyArray(Structure *tab, Structure *tab1, int K)
{
for (int i = 0 ; i < K ; i++)
{
tab1[i].x = tab[i].x;
tab1[i].y = tab[i].y;
}
}
void Call_MS(Structure *tab, int A, int K)
{
Load(tab, K, "1k.txt");
long long startTime = GetTickCount64();
MergeSort(tab, A, K-1);
long long endTime = GetTickCount64();
cout << (endTime - startTime) << "ms dla MergeSort" << endl;
Save(tab, K, "WartLos_MS_1k.txt");
Time(startTime, endTime, "WartLos_MS_1k_czas.txt");
}
void Call_QS(Structure *tab, int A, int K)
{
Load(tab, K, "1k.txt");
long long startTime = GetTickCount64();
QuickSort(tab, A, K-1);
long long endTime = GetTickCount64();
cout << (endTime - startTime) << "ms dla QuickSort" << endl;
Save(tab, K, "WartLos_QS_1k.txt");
Time(startTime, endTime, "WartLos_QS_1k_czas.txt");
}
const int MAX_EL = 30;
int _tmain(int argc, _TCHAR* argv[])
{
Structure *punkt = new Structure[MAX_EL];
void LosujWspolrzedne(Structure *punkt, int MAX_EL);
Structure *punkt1= new Structure[MAX_EL];
void CopyArray(Structure *punkt, Structure *punkt1, int MAX_EL);
delete[] punkt;
Save(punkt1, MAX_EL, "1k.txt");
cout<<"Start:"<<endl;
Call_MS(punkt1, 0, MAX_EL);
Call_QS(punkt1, 0, MAX_EL);
delete[] punkt1;
return 0;
}
You have MergeSort(tab, A, Z) inside MergeSort, so you always call itself with exact arguments
It should be MergeSort(tab, A, st)
You are using MergeSort(tab,A,Z) which call the same function again with same arguments which is will go one for infinite recursion hence error. You should only pass MergeSort(tab,A,sr) which will reduce your problem to half size.