Binary addition algorithm - c++

I am trying to implement a code from a standard quotient and remainder algorithm namely:
function divide(x,y)
if x=0: return (q,r)=(0,0)
(q,r)=divide(floor(x/2),y)
q=2*q, r=2*r
if x is odd: r=r+1
if r>=y: r=r-y, q=q+1
return (q,r)
with a c++ code here is the relavent part of my function
bool compareVector(const vector<int> &A, const vector<int> &B){
if(A.size()<B.size())
return(1==0);
if(A.size()>B.size())
return(1==1);
for(int i=A.size()-1;i>=0;i--){
if (A[i]>B[i])
return(1==1);
if(A[i]<B[i])
return(1==0);
}
return(1==1);
}
struct QandR{
vector<int> r;
vector<int> q;
};
QandR Division(vector<int> BinaryA, const vector<int> & BinaryB, QandR &x){
vector<int> one, zero;
one.clear();
one.push_back(1);
zero.clear();
zero.push_back(0);
if(BinaryA==zero){
return x;
}
else if(BinaryA==one){
BinaryA[0]=0;
}
else if(BinaryA.size()>1)
pop_front(BinaryA);
x=Division(BinaryA,BinaryB,x);
x.q=addBinary(x.q,x.q);
x.r=addBinary(x.r,x.r);
if(BinaryA[0]==1)
x.r=addBinary(x.r,one);
if(compareVector(x.r,BinaryB))
{
x.r=Subtract(x.r,BinaryB);
x.q=addBinary(x.q,one);
}
return x;
}
However this simply does not work for example with BinaryA={1,0,1,1} and BinaryB={0,1}. This is 13/2 so q should be {0,1,1}, and r should be {1}. But my code out puts r={1} and q={0,1}. I don't understand what is going on. All functions that are used above that are not defined work. Also, is there a easier way to return two values in c++ if there is I would be grateful to know. Thank you.
Add is the whole code
#include <iostream>
#include <string> //this is only used for the user to insert a number
#include <stdlib.h> //this is used to convert the user iputed string to a vector
#include <vector>
#include <algorithm>
using namespace std;
void CleanArray(vector<int> & Array){ //CleanArray() is mainly for the Multiply function where we need to keep removing the enteries
for(int i=0;i<Array.size();i++){
Array[i]=0; //of a vector<int> Array. And then I clean some of the other struct vector<int>'s for saft
}
}
vector<int> addBinary(vector<int> A,vector<int> B){ //addBinary() adds two struct vector<int>'s and returns a new struct vector<int>
vector<int> C; // C is our carry array but we take advantage of the fact that after we carry to a new column we nolonger need the old one so we
// can also use C to store our answere.
C.assign(A.size()+1,0);
CleanArray(C);
for(int i=0; i<B.size();i++){ //Case 1 we are adding the first part where we are adding columns and we still have vector<int> A and vector<int> B
if(C[i]+B[i]+A[i]==3){
C[i]=1;
C[i+1]=1;
}
else if(B[i]+A[i]+C[i]==2){
C[i]=0;
C[i+1]=1;
}
else if(B[i]+ A[i]+C[i] ==1){
C[i]=1;
}
}
for(int i=B.size();i<A.size();i++){ //Case 2 we adding where vector<int> B has been exasted and we only have vector<int> A and vector<int> C.
if(C[i]+A[i]==2){
C[i]=0;
C[i+1]=1;
}
else if(A[i]==1){
C[i]=1;
}
} // this is fine but not necessary.
if(C[C.size()-1]==0) // We want to change C's member length_a if the aswere is one bigger then the size of A.size().
C.pop_back();
return C;
}
vector<int> Subtract(vector<int> A, vector<int> B){ // this function is almost exactly the same as Multiply() using a vector<int> C to hold the value of A-B
vector<int> C;
C.assign(A.size(),0);
CleanArray(C);
// reverse(B.begin(), B.end());
for(int i=A.size()-B.size();i>0;i--)
B.push_back(0);
// reverse(B.begin(), B.end());
for(int i=A.size()-1;i>=0;i--){
if((A[i]+B[i])==2)
C[i]=0;
else if(A[i]==1 && B[i]==0)
C[i]=1;
else if(B[i]==1 && A[i]==0){
C[i]=1;
int j=0;
int k=i+1;
while(j==0){ //we need this while loop bc when we have 0-1 this changes all values of
if(C[k]==1){ //C[i+1] to the next C[]==1, changing all of those to 1 so ex 1000-1=0111
C[k]=0;
j++;
}
else if(C[k]==0){
C[k]=1;
k++;
}
// if(i==C.size()-1 && C.size()>1) // this removes the zero's in front of the numberso the answer is not like 001 but 1.
// C.pop_back();
}
}
// else this was the problem with subtraciton
// C[i]=0; "" " " " " "
}
int i=C.size()-1;
while(C[i]==0 && i!=0){
C.pop_back();
i--;
}
return C;
}
vector<int> Multiply(const vector<int> & A, const vector<int> &B){ // This also uses the concept of having a vector<int> C to store the values of the succesive additions of the rows
vector<int> C;
C.assign(A.size(),0);
for(int j=0;j<B.size();j++){
vector<int> D;
D.assign(A.size(),0);
for(int i=0;i<A.size();i++){
if(B[j]==1)
D[i]=A[i];
// this makes a new row if B[j]==1 so if 1110101*1=1110101(0...0) there are j zero's in
}
D.insert(D.begin(),j,0);
C=addBinary(D,C); //this adds the pervious value of C with the next row.
}
return C;
}
void pop_front(vector<int> & A){
reverse(A.begin(),A.end());
A.pop_back();
reverse(A.begin(),A.end());
}
bool compareVector(const vector<int> &A, const vector<int> &B){
if(A.size()<B.size())
return(1==0);
if(A.size()>B.size())
return(1==1);
for(int i=A.size()-1;i>=0;i--){
if (A[i]>B[i])
return(1==1);
if(A[i]<B[i])
return(1==0);
}
return(1==1);
}
struct QandR{
vector<int> r;
vector<int> q;
};
QandR Division(vector<int> BinaryA, const vector<int> & BinaryB, QandR &x){
vector<int> one, zero;
one.clear();
one.push_back(1);
zero.clear();
zero.push_back(0);
if(BinaryA==zero){
return x;
}
else if(BinaryA==one){
BinaryA[0]=0;
}
else if(BinaryA.size()>1)
pop_front(BinaryA);
x=Division(BinaryA,BinaryB,x);
x.q=addBinary(x.q,x.q);
x.r=addBinary(x.r,x.r);
if(BinaryA[0]==1)
x.r=addBinary(x.r,one);
if(compareVector(x.r,BinaryB))
{
x.r=Subtract(x.r,BinaryB);
x.q=addBinary(x.q,one);
}
return x;
}
/*
vector<int> modexp(vector<int> x,vector<int> y, vector<int> N){
vector<int> one;
vector<int> r;
vector<int> q;
one.push_back(0);
if(y.size()==1 && y[1]==0)
return one;
y.pop_back();
vector<int> z=modexp(x,y,N);
if(y[0]==1){
vector<int> D=Multiply(z,z);
Division(D,N,q,r);
z=q;
return z;
}
else{
vector<int> C =Multiply(Multiply(z,z),x);
Division(C,N,q,r);
z=q;
return z;
}
}
*/
int main(){
int arraya[4]={1,1,0,1};
int arrayb[2]={1,1};
vector<int> a(arraya,arraya+4);
vector<int> b(arrayb,arrayb+2);
for(int i=0;i<a.size();i++){
cout<<a[i]<<" ";
}
cout<<endl;
pop_front(a);
for(int i=0;i<a.size();i++)
cout<<a[i]<<" ";
cout<<endl;
QandR x;
x.r.clear();
x.q.clear();
x.r.push_back(0);
x.q.push_back(0);
x=Division(a,b,x);
for(int i=0;i<x.r.size();i++){
cout<<x.r[i]<<" ";
}
cout<<endl;
for(int i=0;i<x.q.size();i++)
cout<<x.q[i]<<" ";
cout<<endl;
return 0;
}

When you divide BinaryA by 2, and try to call Division again, you have to return BinaryA to its original state so that you can verify if it was odd or not.
So, in these two cases:
else if(BinaryA==one){
BinaryA[0]=0;
}
else if(BinaryA.size()>1)
pop_front(BinaryA);'
you have to keep the bit that is lost and restore it after the recursive Division has returned.

Related

code for finding the number of occurrences of the largest element in an array giving segmentation error

I am writing a function in c++ which takes a vector array as a parameter and then finds the number of occurrences of the largest value in it.
I have written function birthdaycakecandles and main function as below.
#include <iostream>
using namespace std;
int birthdaycakecandles(vector<int> a)
{
int largest=a[0];
int pos;
for(int i=1;i<a.size();++i)
{
if(largest<a[i])
{
largest=a[i];
pos=i;
}
}
int count=1;
for(int i=0;i<a.size();++i)
{
if(a[i]==largest&&i!=pos)
count++;
}
return count;
}
int main()
{
double n;
cin>>n;
vector<int> a;
for(double i=0;i<n;++i)
cin>>a[i];
int val=birthdaycakecandles(a);
cout<<val;
return 0;
}
Please review the code and suggest me the reason(s) for the error.
The compiler is giving me segmentation error.
Thanks.
Given the code
vector<int> a;
for(double i=0;i<n;++i)
cin>>a[i];
a is empty; access to nonexistent elements as a[i] leads to UB, anything is possible.
You can initialize a containing n elements from the beginning.
size_t n;
cin>>n;
vector<int> a(n);
for(size_t i=0;i<n;++i)
cin>>a[i];
Or use push_back to insert elements into a.
size_t n;
cin>>n;
vector<int> a;
for(size_t i=0;i<n;++i) {
int x;
cin>>x;
a.push_back(x);
}
PS: Using double as the index of vector seems meaningless.
When using vector, we have to add elements using push_back or emplace_back. In order to traverse the vector, make use of vector iterators for exception safety due to out of bound access.
for (vector<int>::iterator it = a.begin() ; it != a.end(); ++it)
{
//your implementation goes here.
cout << *it << endl; //access each element like this
}
Also note that a.end() is in fact the last_element + 1
vector<int> a;
for(double i=0;i<n;++i)
cin>>a[i];
This is not the way to input in vector use a.push_back(i); instead;
and use auto to traverse till a.begin() till a.end()

C++ arrays sort

I have to solve a problem that consist of sorting a list of number in c++.
The condition is :
the positive, and 0 must be sorted ascending
negative numbers- descending
if A = {4,-8,7,-6,0,-7,5} the at the final B = {0,4,5,7,-6,-7,-8 }
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
int i,j,n,A[100],B[100],A_nenegative[100],A_negative[100],aux,m=0,k=0;
cout<<"max elements"; cin>>n;
cout<<"elements are"<<endl;
for(i=0;i<n;i++)
{
cin>>A[i];
}
for(i=0;i<n;i++)
for(j=i+1;j<n;j++)
if(A[i]>A[j])
{
aux=A[i];
A[i]=A[j];
A[j]=aux;
}
for(i = 0; i< n; i++)
if(A[i]>=0) {
A_nenegative[i]=A[i];
B[i]=A_nenegative[i];
k++;
}
for(i=0;i<n;i++)
for(j=i+1;j<n;j++)
if(A[i]<A[j])
{
aux=A[i];
A[i]=A[j];
A[j]=aux;
}
for(i=0;i<n;i++)
if(A[i]<0)
{
A_negative[i]=A[i];
m++;
}
}
here is where i stopped. I sort positive numbers in A_nenegative and negative numbers in A_negative. So the question is how can attribute to B first- A_nenegative and then A_negative.
I try after sorting positive numbers immediate to attribute to B , something like that:
for(i = 0; i< n; i++)
if(A[i]>=0) {
A_nenegative[i]=A[i];
B[i]=A_nenegative[i];
k++;
}
But i don't know what to do next
Just use predicate.
std::sort(std::begin(a), std::end(a), [](int a, int b) {
if(a >= 0) {
if(b >= 0) return a < b;
else return true;
}
else {
if(b >= 0) return false;
else return a > b;
}
});
Predicate returns true if a needs to go before b in array, false - otherwise.
So, if a >= 0 and b >= 0 --- we check whether a < b (sort non-negative values in ascending order).
if a >= 0 and b < 0 --- then b needs to go after a, because all negative values go after non-negative.
if a < 0 and b >= 0 --- then b needs to go before a.
if a < 0 and b < 0 --- check whether a > b (to sort in descending order).
Use appropriate predicate with std::sort:
std::sort(std::begin(A), std::end(A), [](int lhs, int rhs) {
auto score = [](int n){ return std::make_tuple(n < 0, std::abs(n)); }
return score(lhs) < score(rhs);
});
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
int n,A[100],B[100],Merge_Array[200],aux;
cout<<"max elements"; cin>>n;
cout<<"elements are"<<endl;
int temp,index_A=0,index_B=0;
for(int i=0;i<n;i++)
{
cin>>temp;
if(temp>=0){
A[index_A++]=temp; //One array for positive
}
else{
B[index_B++]=temp; //Another one for negative
}
}
//Sort positive in ascending
for(int i=0;i<index_A;i++)
{
for(int j=i+1;j<index_A;j++)
if(A[i]>A[j])
{
aux=A[i];
A[i]=A[j];
A[j]=aux;
}
}
//Sort negative in descending
for(int i=0;i<index_B;i++)
for(int j=i+1;j<index_B;j++)
if(B[i]<B[j])
{
aux=B[i];
B[i]=B[j];
B[j]=aux;
}
//Merge A and B
for(int i=0;i<index_A;i++){
Merge_Array[i]=A[i];
}
for(int i=index_A,k=0;i<n;i++,k++){
Merge_Array[i]=B[k];
}
//Print the Merged Array
for(int i=0;i<n;i++){
cout<<Merge_Array[i];
}
}
Hi Cristyan. All others have answered your question. But I still see you are following C type coding for C++. In C++ you are free to declare your variables anywhere not necessarily at the start of the function.
Eg:- for(int i=0;;) is feasible.
Moreover, you have not used dynamic arrays. I know for starters using new and delete can be intimidating. But instead, you can use vectors which offers various functionalities, so pointing you to that vectors.
I like expressive C++:
#include <array>
#include <iostream>
int main() {
auto a = std::array<int, 7>{4, -8, 7, -6, 0, -7, 5};
auto it = std::partition(std::begin(a), std::end(a),
[](const int val) noexcept { return val >= 0; });
std::sort(begin(a), it);
std::sort(it, std::end(a), std::greater<int>());
for(const auto& elem : a) {
std::cout << elem << "\n";
}
}
I would iterate over your input and put every value >= 0 into an array POS and any value < 0 into an array NEG.
Then sort both array ascending and separately and use the absolute value to compare the elements (no effect in POS but required for NEG).
For last push NEG to POS and you have it.
Think thats simple and straight forward.

Segmentation fault in merge sort code

I have written this merge sort program in c++ but I am getting "Segmentation fault (core dumped)" error after running the code. Even though there is no compilation error. Can you please tell me what's the mistake I am doing? While taking input in the array it is showing that error. If I change it to push_back, the input is fine but later in merge function, it is showing the same error.
//merging 2 sorted subarrays.
#include <iostream>
#include <vector>
using namespace std;
void merge(vector <int> &a,vector <int> &b,vector <int> &c)
{
int i=0,j=0,k=0,bL=b.size(),cL=c.size();
while(i<bL && j<cL)
{
if(b[i]<c[j])
{
a[k]=b[i];
i++;k++;
}
else
{
a[k]=c[j];
j++;k++;
}
}
while(i<bL)
{
a[k]=b[i];
i++;k++;
}
while(j<cL)
{
a[k]=c[j];
j++;k++;
}
cout<<"array a inside merge is: "<<endl;
for(int p=0;p<a.size();p++)
{
cout<<a[p]<<endl;
}
}
void mergeSort(vector <int> &a)
{
vector <int> l, r;
int mid;
if(a.size()<2) return;
mid = a.size()/2;
for(int i=0;i<mid;i++)
{
l[i]=a[i];
}
for(int i=mid;i<a.size();i++)
{
r[i-mid]=a[i];
}
mergeSort(l);
mergeSort(r);
merge(a, l, r);
}
int main()
{
int n;
vector <int> a;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
mergeSort(a);
for(int p=0;p<n;p++)
{
cout<<a[p]<<endl;
}
return 0;
}
Whever you access an element in a vector using [] you might get a seg fault.
This code,
vector <int> a;
gives you an empty vector.
Asking for a[0] won't work if there's nothing in a yet.
Trying to set a[0] to a value won't work either.
It doesn't exist.
Yet.
You have a similar problem in mergeSort when you use
vector <int> l, r;
These are also empty vectors.
You can use push_back (or even emplace_back) to add new elements.
Or use a constructor overload to state how many elements you want.
For example,
vector <int> a(10);
gives you a vector of ten ints, so a[0] is fine to read from or write to.
a[11] isn't.
Practise using a vector first then try your merge sort.
The reason for getting a segmentation fault is you access the location of the memory which does not exist (more accurate to say as not allocated). Say you have a vector of length 3 and you try to access 4th position, you get a segmentation fault.
As opposed to #doctorlove's answer, I would say it is possible to use []. However, you need the following implementation (only shown for main(), please implement with the same logic in the other functions). See the documentation of std::vector for more info.
int main()
{
size_t n;
std::cin >> n;
std::vector <int> a(n);
for(int i=0;i<n;++i)
{
std::cin >> a[i];
}
// mergeSort(a);
for(int i=0;i<n;++i)
{
std::cout << a[i] << "\n";
}
return 0;
}
Hope this helps. Cheers.
here is the final code after changes:
//merging 2 sorted subarrays.
#include <iostream>
#include <vector>
using namespace std;
void merge(vector <int> &a,vector <int> &b,vector <int> &c)
{
int i=0,j=0,k=0,bL=b.size(),cL=c.size();
while(i<bL && j<cL)
{
if(b[i]<c[j])
{
a[k]=b[i];
i++;k++;
}
else
{
a[k]=c[j];
j++;k++;
}
}
while(i<bL)
{
a[k]=b[i];
i++;k++;
}
while(j<cL)
{
a[k]=c[j];
j++;k++;
}
cout<<"array a inside merge is: "<<endl;
for(int p=0;p<a.size();p++)
{
cout<<a[p]<<endl;
}
}
void mergeSort(vector <int> &a)
{
vector <int> l, r;
int mid;
if(a.size()<2) return;
mid = a.size()/2;
for(int i=0;i<mid;i++)
{
l.push_back(a[i]);
}
//change2
for(int i=0;i<a.size()-mid;i++)
{
r.push_back(a[mid+i]);
}
mergeSort(l);
mergeSort(r);
merge(a, l, r);
}
int main()
{
int n;
cin>>n;
//change1
vector <int> a(n);
for(int i=0;i<n;i++)
{
cin>>a[i];
}
mergeSort(a);
cout<<"Final array is:"<<endl;
for(int p=0;p<n;p++)
{
cout<<a[p]<<endl;
}
return 0;
}

Overloading operators for STL Vector

I know that it is usually not the best idea, but i decided to give it a try. I'm trying to overload + operator to make element wise addition of two vectors. For some reason it correctly returns only the first value in the vector.
I cant figure out what is going wrong ? It also wont work if i'll use push_back instead resizing when calculating elements of sum array. Here is the code :
#include "stdafx.h"
#include <iostream>
#include "conio.h"
#include <vector>
using namespace std;
class dvector{
public:
vector<double> q;
dvector(vector<double>);
dvector();
};
dvector::dvector(vector<double> a) {
q=a;
};
dvector::dvector() {
vector<double> q;
};
dvector operator+(dvector c1, dvector c2)
{
int sz=c1.q.size();
dvector sum;
sum.q.resize(sz);
double temp;
for (int i=0; i<sz; i++){
sum.q[i]=c1.q[i]+c2.q[i];
return sum;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
vector<double> test1;
test1.resize(10);
for (int i=0; i<10;i++){
test1[i]=i;
}
vector<double> test2;
test2.resize(10);
for (int i=0; i<10;i++){
test2[i]=2;
}
dvector dtest1(test1);
dvector dtest2(test2);
dvector sum=dtest1+dtest2;
for (int i =0;i<10;i++)
{
cout<<sum.q[i]<<' ';
}
getch();
return 0;
}
You return in your for-loop right after the first iteration. You should move return sum; to the last line of operator+.
Because you return out too quickly. return statement will not only break out of for loop but also return out of function.
dvector operator+(dvector c1, dvector c2)
{
int sz=c1.q.size();
dvector sum;
sum.q.resize(sz);
double temp;
for (int i=0; i<sz; i++){
sum.q[i]=c1.q[i]+c2.q[i];
//return sum; // don't return until you finish calculating
}
return sum; // move to here
}

Fine tune without using pointers

** To print repeated elements from an user defined array
//print repeated elements from an array
#include<iostream>
using namespace std;
int main()
{
int p,n;
cout<<"enter no. of elements in array: "<<endl;
cin>>n;
int a[n],b[n];
int z=0;
cout<<"enter elements of array:"<<endl;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
for(int j=0;j<n;j++)
{
for(int k=j;k<=n;k++)
{
if(j==k)
{
continue;
}
else if(a[j]==a[k])
{
b[z]=a[j];
++z;
a[k]=a[k+1]; //deleting the array element which repeats
a[n-1]=0; //settng last element as 0
--n; //reducing the size of array
break;
}
int d=z;
if(b[j]==b[k])
{
b[j]=b[j+1];
b[n-1]=0;
n--;
}
}
}
if(z==0)
{
cout<<"No Elemnts in the array is repeated"<<endl;
}
else
{
cout<<"repeated elements are: "<<endl;
for(p=0;p<z;p++)
{
cout<<b[p]<<" ";
}
}
return 0;
}
How to fine tune this program so as it displays correct output? When we enter 3 similar elements it repeats itself twice and also has problem reading the last element.
Thanks
You should rewrite your algorithm. Something like that should work:
std::vector<int> a;
/* fill a */
std::sort(a.begin(), a.end());
std::vector<int> unique_elements;
std::unique_copy(a.begin(), a.end(), std::back_inserter(unique_elements));
std::vector<int> b;
std::copy_if(unique_elements.begin(), unique_elements.end(), std::back_inserter(b), [&](int n)
{
return std::count(a.begin(), a.end(), n) >= 2;
});