Vector arrays, calculation dot product - c++

I am trying write C++ programs that compute the dot product of two given vectors. In vectors a and b only nonzero elements will be stored into array of structures. Each time I am getting irrelevant results. The corrrect result is 50. I think i am not able to read the vectors properly into array of structures. Please advice. Thank you in advance
#include <iostream>
#include <vector>
using namespace std;
const int n=10; /* vector size limit */
struct element {
int x; /* original index of non-zero array element */
int val ; /* integer non-zero value at index x */
};
element row[n];
element col[n];
int i;
vector<int> a={0,0,7,0,5,0,0,8,0,4,-1};
vector<int> b={0,0,0,5,6,0,0,0,0,5,-1};
void generate_row_and_col()
{
for (i=0; i<=n; i++)
{
if(a[i]=!0)
{
row[i].x=i;
row[i].val=a[i];
}
}
for (i=0; i<=n; i++)
{
if(b[i]!=0)
{
col[i].x=i;
col[i].val=b[i];
}
}
}
int dotproduct()
{
/* calculate the dot product of row and col output the result*/
int i=0;
int j=0;
int product=0;
while(row[i].x!=-1 && col[j].x!=-1)
{
if(row[i].x == col[j].x)
{
product=product+row[i].val*col[j].val;
i++;
j++;
}
else if(row[i].x<col[j].x)
{
i++;
}
else
{
j++;
}
}
return product;
}
int main()
{
generate_row_and_col() ;
int r;
r=dotproduct();
cout<<"result="<<r<<endl;
return 0;
}

The standard library has std::inner_product for exactly this purpose. Using it reduces your code to something like this:
#include <numeric>
#include <iostream>
#include <vector>
int main() {
std::vector<int> a = { 0,0,7,0,5,0,0,8,0,4 };
std::vector<int> b = { 0,0,0,5,6,0,0,0,0,5 };
std::cout << std::inner_product(a.begin(), a.end(), b.begin(), 0);
}

Using = !0 is a bug. That was supposed to be != 0.
I'm still guessing at the goal, but perhaps another cleaned version helps:
Live On Coliru
#include <iostream>
#include <vector>
#include <map>
using namespace std;
using Ints = vector<int>;
using Vec = map<int, int>;
Vec row, col;
Vec to_sparse_vec(Ints const& a) {
Vec v;
for (size_t i = 0; i < a.size(); ++i) {
if (a[i] != 0) v[i] = a[i];
}
return v;
}
int dotproduct(Vec row, Vec col) {
size_t n = max(row.rbegin()->first, col.rbegin()->first);
int product = 0;
for (size_t i = 0; i <= n; ++i) {
if (row[i] && col[i])
product += row[i] * col[i];
}
return product;
}
int main() {
auto row = to_sparse_vec({ 0, 0, 7, 0, 5, 0, 0, 8, 0, 4 });
auto col = to_sparse_vec({ 0, 0, 0, 5, 6, 0, 0, 0, 0, 5 });
cout << "result=" << dotproduct(row, col) << endl;
}
This assumes the Vec representation is intended as a "sparse vector".
Result is 50 (dropped the -1 elements)

You can simplify your code
#include <iostream>
#include <vector>
using namespace std;
template<class InputIt1, class InputIt2, class T>
T dot_product(InputIt1 first1, InputIt1 last1,
InputIt2 first2, T value)
{
while ((first1 != last1)&&(*first1!=-1) && (*first2 !=-1)) {
value = value + *first1 * *first2;
++first1;
++first2;
}
return value;
}
const int n=10; /* vector size limit */
struct element {
int x; /* original index of non-zero array element */
int val ; /* integer non-zero value at index x */
};
element row[n];
element col[n];
int i;
vector<int> a={0,0,7,0,5,0,0,8,0,4,-1};
vector<int> b={0,0,0,5,6,0,0,0,0,5,-1};
int main()
{
int r;
r=dot_product(a.begin(), a.end(), b.begin(), 0);
cout<<"result="<<r<<endl;
return 0;
}
Output
50
Demo

I have done some changes on the code, it works fine now. But, during initialization row and col arrays on generate_row_and_col function , I only initialize indexes with non zero elements, rest of them are not initialized. This is not causing any error in this program, but in terms of good programming practice,those indexes with 0 values are not initiated and the arrays will look like(garbage, garbage,7, garbage, 5, garbage, garbage....). Can we just limit the generate_row_and_col function, so We can only store non zero value indexes.
Thank you
#include <iostream>
#include <vector>
using namespace std;
const int n=11; /* vector size */
struct element {
int index; /* original index of non-zero array element */
int value ; /* integer non-zero value at index x */
};
element row[n];
element col[n];
vector<int> a={0,0,7,0,5,0,0,8,0,4,-1};
vector<int> b={0,0,0,5,6,0,0,0,0,5,-1};
void generate_row_and_col()
{
for (int i=0; i<n; i++)
{
if(a[i]!=0)
{
row[i].index=i;
row[i].value=a[i];
}
}
for (int j=0; j<n; j++)
{
if(b[j]!=0)
{
col[j].index=j;
col[j].value=b[j];
}
}
}
int dotproduct()
{
/* calculate the dot product of row and col output the result*/
int i=0;
int j=0;
int product=0;
while(row[i].value!=-1 && col[j].value!=-1)
{
if(row[i].index == col[j].index)
{
product=product+row[i].value*col[j].value;
i++;
j++;
}
else if(row[i].index<col[j].index)
{
i++;
}
else
{
j++;
}
}
return product;
}
int main()
{
generate_row_and_col() ;
int r;
r=dotproduct();
cout<<"Dot Product = "<<r<<endl;
return 0;
}

Related

Finding repeated points in 2D plane

I am trying to find repeated points from a given 10 points, where each points has x and y values. I have written the below code but can not get correct results. The output should be {3,5},{4,2},{2,4},{7,8}
#include <iostream>
#include<stdlib.h>
using namespace std;
struct point
{
int x;
int y;
};
void distinctPoints(point arr[], int size)
{
cout<<"Repeated Points"<<endl;
cout<<"x, y"<<endl;
for(int i = 0; i< size; i++)
for(int j = i+1; j< size; j++)
{
if ((arr[i].x==arr[j].x) && (arr[i].y==arr[j].y))
{
cout<<arr[j].x <<", "<<arr[j].y<<endl;
break;
}
}
}
int main()
{ int size=10;
point points[size]={{3,5},{4,2},{2,4},{3,5},{7,8},{7,8},{4,2},{7,8},{3,5},{2,4}};
distinctPoints(points, size);
return 0;
}
Your approach (once corrected, as VHS's answer did) could be fine for a small number of points, but, with a bigger set of data, an O(N2) algorithm could be too inefficient.
You can take advantage of the average costant time that takes inserting an element in a std::unordered_set, even if you are required to write a comparison function and an hash function for your class.
The algorithm presented below uses two unordered_set's:
uniques ends up storing all the elements that are present in the source container, without repetitions.
repeated stores a unique instance of only the elements that are present multiple times.
An element is copied to the output only if it's already present in uniques, but not in repeated.
#include <iostream>
#include <vector>
#include <unordered_set>
#include <algorithm>
#include <iterator>
struct point
{
int x, y;
bool operator== (point const& b) const
{
return x == b.x && y == b.y;
}
};
namespace std {
template<> struct hash<point>
{
std::size_t operator() (point const& p) const
{
return (std::hash<int>{}(p.x) << 1) ^ std::hash<int>{}(p.y);
}
};
}
std::ostream& operator<< (std::ostream& os, point const& pt)
{
return os << '(' << pt.x << ", " << pt.y << ')';
}
template<class InputIt, class OutputIt>
OutputIt copy_repeated_values(InputIt first, InputIt last, OutputIt dest)
{
using value_type = typename InputIt::value_type;
std::unordered_set<value_type> uniques, repeated;
return std::copy_if(
first, last, dest, [&] (value_type const& value) {
return
not uniques.insert(value).second &&
repeated.insert(value).second;
}
);
}
int main()
{
std::vector<point> points {
{3,5}, {4,2}, {2,4}, {3,5}, {7,8}, {7,8}, {4,2}, {7,8}, {3,5}, {2,4}
};
copy_repeated_values(
std::begin(points), std::end(points),
std::ostream_iterator<point>(std::cout, " ")
);
std::cout << '\n';
}
The output is:
(3, 5) (7, 8) (4, 2) (2, 4)
I have tweaked your distinctPoints method so that it doesn't print the duplicates multiple times even if the dups appear more than twice. See the following edits:
void distinctPoints(point arr[], int size)
{
point dups[size];
cout<<"Distinct Points"<<endl;
cout<<"x, y"<<endl;
for(int i = 0; i < size; i++)
for(int j = 0; j < size; j++) {
if ((arr[i].x==arr[j].x) && (arr[i].y==arr[j].y)) {
if(j < i) {
break;
}
else if( j == i) {
continue;
}
else {
cout<<arr[i].x <<", "<<arr[i].y<<endl;
break;
}
}
}
}
This should do what you are trying to achieve, I am making use of set and maps in c++ which takes care of unique entries.
The map keeps track of already visited points.
#include <iostream>
#include<stdlib.h>
#include <set>
#include <map>
using namespace std;
struct point
{
int x;
int y;
};
map<pair<int, int>, int> mapCountOfPoints;
set<pair<int, int> > disPoints;
void distinctPoints(point arr[], int size)
{
for(int i=0; i<size; i++) {
pair<int, int> temp = make_pair(arr[i].x, arr[i].y);
if(mapCountOfPoints.find(temp) != mapCountOfPoints.end()) {
disPoints.insert(temp);
} else {
mapCountOfPoints[temp] = 1;
}
}
// Now we will iterate over the set to get the distinct set of points
for(set<pair<int, int>>::iterator it=disPoints.begin(); it!=disPoints.end(); it++) {
cout<<it->first<<" "<<it->second<<endl;
}
}
int main()
{ int size=10;
point points[size]={{3,5},{4,2},{2,4},{3,5},{7,8},{7,8},{4,2},{7,8},{3,5},{2,4}};
distinctPoints(points, size);
return 0;
}
Hope this helps!

reading nonzero vector members into array and output dot product

I am trying write C++ programs that compute the dot product of two given vectors. In vectors a and b only nonzero elements will be stored into array of structures. I think i am not able to read the vectors properly into array of structures.
Please advice.
Thank you in advance
#include <iostream>
#include <vector>
using namespace std;
const int n=10; /* vector size limit */
struct element {
int x; /* original index of non-zero array element */
int val ; /* integer non-zero value at index x */
};
element row[n];
element col[n];
int i;
vector<int> a={0,0,7,0,5,0,0,8,0,4,-1};
vector<int> b={0,0,0,5,6,0,0,0,0,5,-1};
void generate_row_and_col()
{
for (i=0; i<=n; i++)
{
if(a[i]=!0)
{
row[i].x=i;
row[i].val=a[i];
}
}
for (i=0; i<=n; i++)
{
if(b[i]!=0)
{
col[i].x=i;
col[i].val=b[i];
}
}
}
int dotproduct()
{
/* calculate the dot product of row and col output the result*/
int i=0;
int j=0;
int product=0;
while(row[i].x!=-1 && col[j].x!=-1)
{
if(row[i].x == col[j].x)
{
product=product+row[i].val*col[j].val;
i++;
j++;
}
else if(row[i].x<col[j].x)
{
i++;
}
else
{
j++;
}
}
return product;
}
int main()
{
generate_row_and_col() ;
int r;
r=dotproduct();
cout<<"result="<<r<<endl;
return 0;
}
Your dotproduct() must be like
int dotproduct()
{
/* calculate the dot product of row and col output the result*/
int i=0;
int j=0;
int product=0;
while(row[i].val != -1 )
{
j = 0;
while( col[j].val != -1)
{
if(row[i].x == col[j].x)
{
product=product+row[i].val*col[j].val;
break;
}
j++;
}
i++;
}
return product;
}

C++ Segmentation fault with same array index

I have the following piece of code:
bool *pho=new bool[n];
memset(pho, 0, sizeof(bool) * n);
for (int i = 0; i < m; i++) {
int d=2;
cout << "i=" << i << ", d="<<d<< endl;
pho[d] = true;
}
Running with input n=8 results in the following output:
i=0, d=2
i=1, d=2
[Segfault]
I don't understand why this is happening! Setting the same location in the array results in a segfault for some reason. I have run the program several times and it always produces the same output.
Stepping through the code with a debugger, I can see that the value of d (the index) is 2 when the array gets accessed.
I have tried using global arrays and also static global arrays, both of which result in the same error.
Is there something wrong with my IDE and compiler? I am using MinGW with Eclipse CDT, running with std/c++11 option enabled.
Here is the whole source file, in case any other part of the program is causing problems:
#include <iostream>
#include <queue>
#include <vector>
#include <unordered_set>
#include <utility>
#include <algorithm>
#include <cstring>
using namespace std;
vector<unordered_set<int>> adj;
static bool *visited;
pair<int, int> dfs(int node) {
if (visited[node])
return make_pair(0, node);
pair<int, int> best = make_pair(0, node);
for (int neigh : adj[node]) {
pair<int, int> alt = dfs(node);
alt.second++;
best = max(best, alt);
}
return best;
}
int main(int argc, char** argv) {
int n, m, def;
cin >> n ;
cin >> m;
bool *pho=new bool[n];
memset(pho, 0, sizeof(bool) * n);
int *degrees=new int[n];
memset(degrees, 0, sizeof(int) * n);
cout << "n="<<n<<", m="<<m<<endl;
for (int i = 0; i < m; i++) {
int d=2;
cout << "i=" << i << ", d="<<d<< endl;
pho[d] = true;
}
for (int i = 0; i < n - 1; i++) {
int a, b;
cin >> a >> b;
adj[a].insert(b);
adj[b].insert(a);
degrees[a]++;
degrees[b]++;
}
queue<int> next;
for (int i = 0; i < n; i++) {
if (degrees[i] == 0) {
next.push(i);
}
}
while (!next.empty()) {
int node = next.front();
next.pop();
if (pho[node])
continue;
for (int neigh : adj[node]) {
adj[node].erase(neigh);
adj[neigh].erase(node);
degrees[node]--;
degrees[neigh]--;
if (degrees[neigh] == 1)
next.push(neigh);
}
}
visited=new bool[n];
memset(visited, 0, sizeof(bool) * n);
pair<int, int> pivot = dfs(def);
memset(visited, 0, sizeof(bool) * n);
pair<int, int> end = dfs(pivot.second);
int dist = end.first; //number of edges she only has to walk once
int tree = n - 1; //number of edges in tree
int otherdist = tree - dist; //number of edges she has to walk twice
int total = dist + otherdist * 2;
cout << total << endl;
return 0;
}
These lines are wrong :
adj[a].insert(b);
adj[b].insert(a);
You need to create unordered_map instance with a and b as keys, then respectively insert b and a as value. You don't need to have a vector of sets if you need key-value pairs.

Function returning the index of largest value, skipping previously returned values

I need to make a function in c++ that returns the index of the largest value. Whenever it is called it should skip the index it returned previously and return the index storing the next largest value.
for eg if : -
int a[8] = {2,6,4,12,5,7,12,8}
the function should return 3 then 6 then 7, 5,1,4,2,0
Edit :-
#include <iostream>
#include <vector>
using std::vector;
int return_max_index(vector<int> valuebyweight, int n)
{
int max_index = 0;
for(int i=0; i<n; i++)
{
if(valuebyweight[i] >= valuebyweight[max_index])
{
max_index = i;
}
}
return max_index;
}
double get_optimal_value(int capacity, vector<int> weights, vector<int> values,int n) {
double value = 0.0;
vector<int> valuebyweight(n);
for(int i=0; i<n; i++)
{
valuebyweight[i] = values[i] / weights[i];
}
while(capacity!=0)
{
int max_index = return_max_index(valuebyweight, n);
if(weights[max_index] <= capacity)
{
capacity -= weights[max_index];
value += values[max_index];
}
else
{
value += (valuebyweight[max_index] * capacity);
capacity = 0;
}
}
return value;
}
int main() {
int n;
int capacity;
std::cin >> n >> capacity;
vector<int> values(n);
vector<int> weights(n);
for (int i = 0; i < n; i++) {
std::cin >> values[i] >> weights[i];
}
double optimal_value = get_optimal_value(capacity, weights, values,n);
std::cout.precision(10);
std::cout << optimal_value << std::endl;
return 0;
}
Trying to implement Fractional Knapsack algorithm. If I run the code on input
3 50
60 20
100 50
120 30
it should give the answer 180 but it returns 200 instead because my 'return_max_index' function is returning the same index again (2) but I somehow want it to skip the index it returned previously (2) and return the index that has the next highest 'valuebyweight' i.e 0.
Try this code.I made some minor changes.
#include <iostream>
#include <vector>
using std::vector;
int return_max_index(vector<int> valuebyweight, int n)
{
int max_index = 0;
for(int i=0; i<n; i++)
{
if(valuebyweight[i] >= valuebyweight[max_index])
{
max_index = i;
}
}
//if all the values in valuebyweight are 0
if(valuebyweight[max_index]==0)
{
return -1;
}
else
return max_index;
}
double get_optimal_value(int capacity, vector<int> weights, vector<int> values,int n) {
double value = 0.0;
vector<int> valuebyweight(n);
for(int i=0; i<n; i++)
{
valuebyweight[i] = values[i] / weights[i];
}
while(capacity!=0)
{
int max_index = return_max_index(valuebyweight, n);
if(max_index==-1)
{
break;
}
if(weights[max_index] <= capacity)
{
capacity -= weights[max_index];
value += values[max_index];
// assign valuebyweight[max_index] to 0 as it already participated in optimal solution and need no longer to participate.
valuebyweight[max_index]=0;
}
else
{
value += (valuebyweight[max_index] * capacity);
capacity = 0;
}
}
return value;
}
int main() {
int n;
int capacity;
std::cin >> n >> capacity;
vector<int> values(n);
vector<int> weights(n);
for (int i = 0; i < n; i++) {
std::cin >> values[i] >> weights[i];
}
double optimal_value = get_optimal_value(capacity, weights, values,n);
std::cout.precision(10);
std::cout << optimal_value << std::endl;
return 0;
}
One way to do this is to just keep the list of found indices in a static local. But then, how do you know you haven't already seen this one before? So better to make it a class. Then you can also do some optimization: sort the array once, then just pop the next highest index from the result whenever it's called:
struct mysort{
const std::vector<int>& _tosort;
mysort(const std::vector<int> tosort) : _tosort(tosort) {}
bool operator()(int a, int b){ return _tosort[a] < _tosort[b]; }
}
class IndexFinder{
private:
std::vector<int> sorted_indices;
int invoked;
public:
IndexFinder(const std::vector<int>& tosort) :
sorted_indices(tosort.size()) {
invoked = 0;
for(size_t i=0; i<tosort.size(); ++i)
sorted_indices[i] = i;
std::stable_sort(sorted_indices.begin(), sorted_indices.end(),
mysort(tosort));
}
int IndexFinder::operator()(){
return sorted_indices[invoked++];
}
};
You should put in protections to IndexFinder::operator()() to handle what happens if the user calls it more times than there are indices in the vector. As a bonus you should be pretty easily able to change it into a template class to sort things other than ints.
This is not pretty (it modifies the array), but gives an idea:
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
int index_of_largest(int array[], size_t len) {
int r = INT_MIN;
int d = 0;
for (int i = 0; i < len; i++) {
if (array[i] > r) {
d = i;
r = array[i];
}
}
if (r != INT_MIN) {
array[d] = INT_MIN;
}
return d;
}
int main(){
int a[8] = {2, 6, 4, 12, 5, 7, 12, 8};
int len = (int)(sizeof(a) / sizeof(a[0]));
for (int i = 0; i < len; i++) {
printf("%d\n", index_of_largest(a, len));
}
}
OUTPUT
3
6
7
5
1
4
2
0
This is a little different than the previous answer #bloer gave, but shows somewhat of a shorter method (it still uses a class) by using C++ 11 (std::iota and usage if lambda in std::sort).
#include <algorithm>
#include <iostream>
#include <vector>
class MaxIndex
{
private:
std::vector<int> index;
public:
MaxIndex(const std::vector<int>& tosort) : index(tosort.size())
{
// initialize the indices
std::iota(index.begin(), index.end(), 0);
// sort the indices based on passed-in vector
std::sort(index.begin(), index.end(), [&](int n1, int n2)
{ return tosort[n1] > tosort[n2];});
}
// return the nth highest index
int getNthMaxIndex(int n) const { return index[n]; }
};
using namespace std;
int main()
{
std::vector<int> a = {2,6,4,12,5,7,12,8};
MaxIndex mi(a);
for (size_t i = 0; i < a.size(); ++i)
cout << mi.getNthMaxIndex(i) << endl;
}
Live Example
Second, is there a reason to consistently use n if you're going to use std::vector? A std::vector knows its own size, so passing (and using) extraneous variables denoting the number of elements in a vector is inviting a bug to be introduced somewhere. Just use the std::vector::size() function if you want to get the number of elements, or just pass the vector by itself.
In addition, you should be passing things like std::vector by either reference or const reference, depending on whether the passed-in vector will be changed or not. Passing std::vector by value (as you're doing now) incurs an (unnecessary) copy.

Can't understand why my program throws error

My code is in
#include <iostream>
#include <string>
#include <algorithm>
#include <climits>
#include <vector>
#include <cmath>
using namespace std;
struct State {
int v;
const State *rest;
void dump() const {
if(rest) {
cout << ' ' << v;
rest->dump();
} else {
cout << endl;
}
}
State() : v(0), rest(0) {}
State(int _v, const State &_rest) : v(_v), rest(&_rest) {}
};
void ss(int *ip, int *end, int target, const State &state) {
if(target < 0) return; // assuming we don't allow any negatives
if(ip==end && target==0) {
state.dump();
return;
}
if(ip==end)
return;
{ // without the first one
ss(ip+1, end, target, state);
}
{ // with the first one
int first = *ip;
ss(ip+1, end, target-first, State(first, state));
}
}
vector<int> get_primes(int N) {
int size = floor(0.5 * (N - 3)) + 1;
vector<int> primes;
primes.push_back(2);
vector<bool> is_prime(size, true);
for(long i = 0; i < size; ++i) {
if(is_prime[i]) {
int p = (i << 1) + 3;
primes.push_back(p);
// sieving from p^2, whose index is 2i^2 + 6i + 3
for (long j = ((i * i) << 1) + 6 * i + 3; j < size; j += p) {
is_prime[j] = false;
}
}
}
}
int main() {
int N;
cin >> N;
vector<int> primes = get_primes(N);
int a[primes.size()];
for (int i = 0; i < primes.size(); ++i) {
a[i] = primes[i];
}
int * start = &a[0];
int * end = start + sizeof(a) / sizeof(a[0]);
ss(start, end, N, State());
}
It takes one input N (int), and gets the vector of all prime numbers smaller than N.
Then, it finds the number of unique sets from the vector that adds up to N.
The get_primes(N) works, but the other one doesn't.
I borrowed the other code from
How to find all matching numbers, that sums to 'N' in a given array
Please help me.. I just want the number of unique sets.
You've forgotten to return primes; at the end of your get_primes() function.
I'm guessing the problem is:
vector<int> get_primes(int N) {
// ...
return primes; // missing this line
}
As-is, you're just writing some junk here:
vector<int> primes = get_primes(N);
it's undefined behavior - which in this case manifests itself as crashing.