We have a problem (stated to be NP Hard) as follows:
Given a connected undirected unweighted graph G = (V, E) and a set of routes (a sequence of vertices) from homes to offices (there can be multiple routes starting from homes, and multiple routes ending at offices), we want to place minimum electric charging stations such that all routes are covered at least once. We cannot place stations at homes or offices.
The below image shows a possible input (please ignore the weights):
Where the house icons are homes and brick wall icons are offices.
The optimal above is placing stations at vertices R and D.
Finding the optimal solution is said to be an NP Hard problem.
I have an approach, which goes something like this:
Let S be empty set of charging stations (vertices)
Let R be set of all given routes, r_i = <v_0, v_1 ... v_j> where v_0 is of type "home" and v_j is of type "office"
Let Vdeg be array of integers of size |V| intially set to 0
For r in R:
Increment Vdeg of every vertex v in r
while R is not empty:
Sort vertices by decreasing Vdeg
Let maxDeg be maximum degree vertex in V
Add maxDeg to S
for all routes r in R which contains maxDeg
R = R\{r}
Decrement Vdeg for maxDeg
The above algorithm runs in (I believe) polynomial time, and also (I believe) gives the optimal solution.
The full implementation is given below:
#include <iostream>
#include <vector>
// A Graph Vertice
struct node {
int id;
std::string type;
std::string name;
};
std::ostream& operator <<(std::ostream& out, const node& n) {
return out << "{ " << n.type << ", " << n.name << " }";
}
// A Graph Edge
struct edge {
node * from;
node * to;
int weight;
};
std::ostream& operator <<(std::ostream& out, const edge& e) {
return out << "{ " << *e.from << ", " << *e.to << ", " << e.weight << " }";
}
std::ostream& operator <<(std::ostream& out, const std::vector<edge>& graph) {
out << "{ ";
for(int i = 0; i < graph.size(); ++i) {
out << graph[i] << ", ";
}
return out << "\b\b }";
}
std::ostream& operator <<(std::ostream& out, const std::vector<node*>& vertices) {
out << "{ ";
for(int i = 0; i < vertices.size(); ++i) {
out << "\n " << *vertices[i] << ", ";
}
return out << "\b\b \n}";
}
std::ostream& operator <<(std::ostream& out, const std::vector<edge*>& graph) {
out << "{ ";
for(int i = 0; i < graph.size(); ++i) {
out << "\n " << *graph[i] << ", ";
}
return out << "\b\b \n}";
}
std::ostream& operator <<(std::ostream& out, const std::vector<std::vector<edge*>>& graph) {
out << "{";
for(int i = 0; i < graph.size(); ++i) {
out << "\n " << graph[i] << ", ";
}
return out << "\b\b \n}";
}
// A Vdeg which also stores id and routes intersecting on it
struct vertice_degrees {
int id;
int degree;
std::vector<int> intersecting;
};
// Greater than operator overloaded for sorting Vdegs by degree
bool operator >(const vertice_degrees& vd1, const vertice_degrees& vd2) {
return vd1.degree > vd2.degree;
}
std::ostream& operator <<(std::ostream& out, const std::vector<vertice_degrees>& vd) {
out << "{ ";
for(int i = 0; i < vd.size(); ++i) {
out << "{ " << vd[i].id << ", " << vd[i].degree << ", { ";
for(int j = 0; j < vd[i].intersecting.size(); ++j) {
out << vd[i].intersecting[j] << ", ";
}
out << "\b\b }, ";
}
return out << "\b\b }";
}
void print_routes(const std::string label, const std::vector<int> routes_to_cover, const std::vector<std::vector<edge*>> routes, const std::string label_after) {
std::cout << label << "{ ";
for(int i = 0; i < routes_to_cover.size(); ++i) {
std::cout << routes[routes_to_cover[i]] << ", ";
}
std::cout << "\b\b }" << label_after;
}
int main() {
// List of vertices in graph
node vertices[] = {
node{ 0, "House", "A" },
node{ 1, "House", "B" },
node{ 2, "House", "F" },
node{ 3, "House", "N" },
node{ 4, "House", "S" },
node{ 5, "Office", "H" },
node{ 6, "Office", "K" },
node{ 7, "Office", "L" },
node{ 8, "Office", "P" },
node{ 9, "Office", "T" },
node{ 10, "None", "C" },
node{ 11, "None", "D" },
node{ 12, "None", "E" },
node{ 13, "None", "G" },
node{ 14, "None", "I" },
node{ 15, "None", "J" },
node{ 16, "None", "M" },
node{ 17, "None", "O" },
node{ 18, "None", "Q" },
node{ 19, "None", "R" },
node{ 20, "None", "U" }
};
// Length of vertices array
const int vertice_count = sizeof(vertices)/sizeof(node);
// List of edges in graph
std::vector<edge> graph = {
edge{ &vertices[0], &vertices[12], 3 },
edge{ &vertices[12], &vertices[15], 3 },
edge{ &vertices[15], &vertices[19], 4 },
edge{ &vertices[19], &vertices[20], 5 },
edge{ &vertices[20], &vertices[9], 5 },
edge{ &vertices[1], &vertices[10], 4 },
edge{ &vertices[10], &vertices[11], 2 },
edge{ &vertices[11], &vertices[5], 2 },
edge{ &vertices[2], &vertices[12], 4 },
edge{ &vertices[12], &vertices[14], 4 },
edge{ &vertices[14], &vertices[11], 3 },
edge{ &vertices[11], &vertices[13], 7 },
edge{ &vertices[13], &vertices[6], 2 },
edge{ &vertices[3], &vertices[19], 3 },
edge{ &vertices[19], &vertices[16], 5 },
edge{ &vertices[16], &vertices[17], 2 },
edge{ &vertices[17], &vertices[7], 2 },
edge{ &vertices[4], &vertices[19], 4 },
edge{ &vertices[19], &vertices[17], 6 },
edge{ &vertices[17], &vertices[18], 4 },
edge{ &vertices[18], &vertices[8], 3 }
// Remaining edges are not on routes, and hence are inconsequential and can be omitted
};
// List of routes
std::vector<std::vector<edge*>> routes_arr = {
std::vector<edge*>{ &graph[0], &graph[1], &graph[2], &graph[3], &graph[4] },
std::vector<edge*>{ &graph[5], &graph[6], &graph[7] },
std::vector<edge*>{ &graph[8], &graph[9], &graph[10], &graph[11], &graph[12] },
std::vector<edge*>{ &graph[13], &graph[14], &graph[15], &graph[16] },
std::vector<edge*>{ &graph[17], &graph[18], &graph[19], &graph[20] }
};
std::cout << routes_arr;
// Vdeg list of size V, and initialised
std::vector<vertice_degrees> vertice_degrees_arr;
for(int i = 0; i < vertice_count; ++i) {
vertice_degrees_arr.push_back(vertice_degrees{ i, 0 });
}
// Add all the routes the vertice is part of for each vertice in Vdeg
for(int i = 0; i < routes_arr.size(); ++i) {
for(int j = 0, k; j < routes_arr[i].size(); ++j) {
vertice_degrees& vd = vertice_degrees_arr[routes_arr[i][j]->from->id];
vd.degree += 1;
for(k = 0; k < vd.intersecting.size(); ++k) {
if(vd.intersecting[k] == i) {
continue;
}
}
vd.intersecting.push_back(i);
}
}
// routes_to_cover is remaining routes left to cover, list of route indexes
std::cout << "\nFilled: \n" << vertice_degrees_arr;
std::vector<int> routes_to_cover;
for(int i = 0; i < routes_arr.size(); ++i) {
routes_to_cover.push_back(i);
}
// Final resulting S
std::vector<node*> stations_placed_at;
// While there are routes still to cover
while(routes_to_cover.size() > 0) {
// Insertion Sort the Vdeg by degree
for(int i = 1, j; i < vertice_degrees_arr.size(); ++i) {
const vertice_degrees vd = vertice_degrees_arr[i];
for(j = i; j > 0 && vertice_degrees_arr[j-1] > vd; --j) {
vertice_degrees_arr[j] = vertice_degrees_arr[j-1];
}
vertice_degrees_arr[j] = vd;
}
// Get all the routes intersecting at v, add v to S
std::vector<int> covered_routes = vertice_degrees_arr[vertice_degrees_arr.size()-1].intersecting;
stations_placed_at.push_back(&vertices[ vertice_degrees_arr[vertice_degrees_arr.size()-1].id ]);
std::cout << "\nSorted: \n" << vertice_degrees_arr;
// Remove routes intersecting at v from all Vdeg, decrease degree for next iteration
for(int i = 0; i < vertice_degrees_arr.size(); ++i) {
for(int j = 0; j < vertice_degrees_arr[i].intersecting.size(); ++j) {
for(int k = 0; k < covered_routes.size(); ++k)
if(vertice_degrees_arr[i].intersecting[j] == covered_routes[k]) {
vertice_degrees_arr[i].intersecting.erase(vertice_degrees_arr[i].intersecting.begin() + j--);
vertice_degrees_arr[i].degree -= 1;
break;
}
}
}
std::cout << "\nCleaned:\n" << vertice_degrees_arr;
// Remove covered routes this iteration from routes_to_cover
for(int i = 0; i < routes_to_cover.size(); ++i) {
for(int j = 0; j < covered_routes.size(); ++j) {
if(routes_to_cover[i] == covered_routes[j]) {
routes_to_cover.erase(routes_to_cover.begin() + i--);
break;
}
}
}
print_routes("\nRemaining routes: ", routes_to_cover, routes_arr, "\n");
}
std::cout << "\nFinal Nodes: " << stations_placed_at;
return 0;
}
So what's wrong with this solution?
Is it:
Not polynomial? or
Not optimal?
If the former, can you explain how?
If the latter, can you provide a counter?
Your algorithm is not optimal, as can be seen by reduction from the exact 3-cover problem.
To see that, let's start with a number of homes that is a multiple of 3. Add a single office. And for each 3-set in our cover we add one vertex with routes from the 3 homes in the 3-set to this vertex, then to the office. It is easy to verify that if an exact 3-cover exists, the set of vertices associated with that exact 3-cover is an optimal arrangement of gas stations. So your problem requires being able to find exact 3-covers.
But your algorithm is greedy and its very first choice is a random guess with no way to decide that any vertex is better than any other. If it first guesses a 3-set that is not in any exact 3-cover, then you won't find the optimal solution.
Okay, after reading up on Exact 3 set cover problem and the helpful answer by #btilly, I have finally been able to come up with a counter to my algorithm.
The intuition is that the algorithm works for inputs which don't have the same degree. Hence, try making the same degree.
The counter is as follows.
Given below graph:
With the following routes:
R1: A, C, F, J, L
R2: B, C, D
R3: E, F, H, K
R4: I, J, H, G
The optimal is selecting the vertices C and H like so:
But if our algorithm picks F first (as degrees are same) like so:
Then we are forced to pick C and one of H or J as follows:
Which is obviously not the optimal solution.
Related
I tried to get first a greedy solution for me handling reservation buy getting 2 days (start, end) and getting the maximum days that can be reserved without the interval being overlap
#include <algorithm>
#include <iostream>
using namespace std;
struct Interval {
int start, end;
};
// Compares two intervals
// according to starting times.
bool comparesorting(Interval i1, Interval i2)//sorting
{
return (i1.end < i2.end);
}
bool compareoverlap(Interval i1, Interval i2)//overlap
{
return (i1.start < i2.start) ? true : false;
}
bool isIntersect(Interval arr[], int n)
{
// Sort intervals in increasing order of start time
sort(arr, arr + n, compareoverlap);
// In the sorted array, if start time of an interval
// is less than end of previous interval, then there
// is an overlap
for (int i = 1; i < n; i++)
if (arr[i - 1].end > arr[i].start)
//return true;
if (true) {
for (int i = 0; i < n; i++)
cout << "mmmm" << endl;
cout << "[" << arr[i].start << "," << arr[i].end
<< "] ";
}
// If we reach here, then no overlap
return false;
}
int main()
{
Interval arr[]
= { { 6, 8 }, { 7, 9 }, { 2, 4 }, { 4, 7 } , { 1,9 } , {6,9} ,{2,6} , {1,10} };
int n = sizeof(arr) / sizeof(arr[0]);
// sort the intervals in increasing order of
// start time
sort(arr, arr + n, comparesorting);
cout << "Intervals sorted : \n";
for (int i = 0; i < n; i++)
cout << "[" << arr[i].start << "," << arr[i].end
<< "] ";
int n1 = sizeof(arr) / sizeof(arr[0]);
isIntersect(arr, n1) ? cout << "Yes\n" : cout << "No\n";
return 0;
}
the output should be {2,4} {4,7} (that does not overlap)
I'm trying to make an optimal solution to solve this problem. I'm thinking to subtract the end - start and compare it to the addition of this greedy solution
please help I'm stuck!!!!
I'm doing a C++ program, in which I want to shuffle an array (or part of an array). Here is the array:
string colorTheme[8][8] = {
{"blue", "blue", "green", "green", "violet", "violet", "teal", "teal"},
{"beige", "beige", "red", "red", "indigo", "indigo", "pink", "pink"},
{"cyan", "cyan", "yellow", "yellow", "orange", "orange", "azure", "azure"},
{"purple", "purple", "lime", "lime", "tangerine", "tangerine", "fuschia", "fuschia"},
{"brown", "brown", "gray", "gray", "black", "black", "white", "white"},
{"olive", "olive", "crimson", "crimson", "silver", "silver", "gold", "gold"},
{"maroon", "maroon", "coral", "coral", "plum", "plum", "ivory", "ivory"},
{"aqua", "aqua", "jade", "jade", "amber", "amber", "ruby", "ruby"}
};
If I wanted to shuffle the first n rows and n columns, how would I do it? Ideally, I would run
shuffle(n);
because colorTheme is in the same class as shuffle().
You can't shuffle const array, but you can do it by changing it, I will post an example of shuffling a 2d array, you can refer that if you want to:
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <string>
#include <algorithm>
#include <iterator>
int main()
{
// the hard, inefficient way
{
enum { N = 7, M = 13 } ;
char dest[N][M] = { "zero", "one", "two", "three", "four", "five", "six" } ;
std::srand( std::time(nullptr) ) ;
for( int i = N-1 ; i > 0 ; --i ) // fisher yates shuffle
{
const int pos = std::rand() % (i+1) ;
char temp[M] ;
std::strcpy( temp, dest[pos] ) ;
std::strcpy( dest[pos], dest[i] ) ;
std::strcpy( dest[i], temp ) ;
}
for( const char* cstr : dest ) std::cout << cstr << ' ' ;
std::cout << '\n' ;
}
// the simple, efficient way
{
enum { N = 7 } ;
std::string dest[N] = { "zero", "one", "two", "three", "four", "five", "six" } ;
std::srand( std::time(nullptr) ) ; // if it has not already been done
std::random_shuffle( std::begin(dest), std::end(dest) ) ;
for( const std::string& str : dest ) std::cout << str << ' ' ;
std::cout << '\n' ;
}
}
The best way to tackle this problem is to convert the 2D array into 1D, as shuffling a 1D array is a lot simpler. Under the covers, create an int array shuffler; fill an int array with values from 0 - n^2 and shuffle them using something like rand. From there, use the values in the int array as new positions for your string array. Once you have shuffled your string array, convert it back into a 1D array. Here is a simple c++ source file I created (feel free to use).
#include <iostream>
#include <string>
using namespace std;
void shufflePos(int n, int arr[]);
void printArray(int *a, int length) {
cout << "[ ";
for (int i = 0; i < length; i ++) {
cout << a[i];
if (i != length - 1) {
cout << ", ";
}
}
cout << " ]\n";
}
void shufflePos(int n, int arr[]) {
for(int i = 0; i < n; i++) {
arr[i] = i;
}
// shuffle positions
srand(time(0));
for(int i = 0; i < (n - 2); i++) {
/*if(arr[i] != i) // i has already been swapped
continue;
*/
int tmp = arr[i];
// cout << "i = " << i << ", n - i = " << (n - i) << ", ";
int random = rand();
// cout << "random = " << random << ", ";
int nextPos = i + random % (n - i);
// cout << "nextPosition = " << nextPos << endl;
arr[i] = arr[nextPos]; // swap
arr[nextPos] = tmp;
}
//printArray(arr, n);
/* bool chck = check(arr, n);
if(chck == false)
cout << "FALSE" << endl;
else
cout << "TRUE" << endl; */
}
void swapString(string arr[], int pos1, int pos2) {
string tmp = arr[pos1];
arr[pos1] = arr[pos2];
arr[pos2] = tmp;
return;
}
void shuffleString(string strs[], int len) {
int valArr[len];
shufflePos(len, valArr);
string to[len];
// copying values into another array
for(int i = 0; i < len; i++) {
to[i] = strs[valArr[i]];
}
// copying to[] into strs[]
for(int i = 0; i < len; i++) {
strs[i] = to[i];
}
}
int main() {
string colorTheme[8][8] = {
{"blue", "blue", "green", "green", "violet", "violet", "teal", "teal"},
{"beige", "beige", "red", "red", "indigo", "indigo", "pink", "pink"},
{"cyan", "cyan", "yellow", "yellow", "orange", "orange", "azure", "azure"},
{"purple", "purple", "lime", "lime", "tangerine", "tangerine", "fuschia", "fuschia"},
{"brown", "brown", "gray", "gray", "black", "black", "white", "white"},
{"olive", "olive", "crimson", "crimson", "silver", "silver", "gold", "gold"},
{"maroon", "maroon", "coral", "coral", "plum", "plum", "ivory", "ivory"},
{"aqua", "aqua", "jade", "jade", "amber", "amber", "ruby", "ruby"}
};
cout << "What size of array do you want?" << endl;
int i;
cin >> i;
int n = i * i; // length of 1D array
string darr[n]; // 1D array
for(int r = 0; r < i; r++) { // fill values of 1D array // rows
for(int c = 0; c < i; c++) { // columns
darr[(i * r + c)] = colorTheme[c][r];
}
}
cout << 1 << endl;
shuffleString(darr, n);
cout << 2 << endl;
// convert 1D array back into 2D array
for(int r = 0; r < i; r++) {
for(int c = 0; c < i; c++) {
colorTheme[c][r] = darr[(i * r) + c];
}
}
for(int r = 0; r < i; r++) { // rows
for(int c = 0; c < i; c++) { // columns
cout << ": " << colorTheme[c][r] << " ";
}
cout << endl;
}
}
Getting error or garbage while Sorting members of structure in cplusplus.
I want to sort the array based on first value of 2d array using structure in c/c++. I'm getting garbage or runtime error. I can't sort the array using bubble sort, I don't know how to handle it.
Here is my code
#include <bits/stdc++.h>
using namespace std;
struct x {
int l[100][3];
};
int main()
{
int n, k, i, j;
cin>>n>>k;
struct x o[n], p;
for(i=0;i<n;++i) {
cin>>o[i].l[i][0]>>o[i].l[i][1];
}
for(i=0;i<n;++i) {
for(j=0;j<n-i-1;++j) {
if((o[j].l[j][0])>(o[j+1].l[j+1][0])) {
//cout<<o[j].l[j][0]<<" "<<o[j+1].l[j+1][0]<<"\n";
p = o[j];
o[j] = o[j+1];
o[j+1] = p;
}
}
}
for(i=0;i<n;++i) {
for(j=0;j<2;++j) {
cout<<o[i].l[i][j]<<" ";
}
cout<<"\n";
}
return 0;
}
I will give you a trial version according my understanding. Please do pronounce if I took your logic wrongly.
First I build a struct of `int3` to contain 3 integers with some utilities to simplify the coding, then a array of `int3` size 100 in the structure `xxx` (your `x`). Note that the `operator[i]` returns the `xxx[i].p[0]` of ith element, and `operator(i)` returns the `int3 p[3]` for exchange purpose. Both operators have `rvalue` and `lvalue` versions.
The structures: `int3` and `xxx`
#include <iostream>
struct int3
{ int p[3];
int3() = default;
int3(const int3&a) {for (int i=0; i<3; i++) p[i]=a.p[i]; }
int3& operator=(const int3&a) = default;
void print() { std::cout <<"("<< p[0] <<", "<<p[1] <<") "; }
};
struct xxx {
int3 s[100];
int operator[](const int i) const {return s[i].p[0];}
int3 operator()(const int i) const {return s[i];}
int&operator[](const int i) {return s[i].p[0];}
int3&operator()(const int i) {return s[i];}
void print(const int n) {
for(int i=0; i<n; i++) {
std::cout << "No " << i << " = ";
s[i].print();
std::cout << std::endl;
}
}
};
In the test `main()`, I removed the input of `k`. It is not used.
int main()
{
int n, k, i, j;
xxx ox;
int3 q;
std::cout << "input n = ";
std::cin >> n;
while (n>100) {
std::cerr << "Array out of range!\n";
std::cout << "input n = ";
std::cin >> n;
}
for(i=0;i<n;++i) {
std::cout << "a[" << i << "].p[0] ,p[1] = ";
std::cin >> ox.s[i].p[0] >> ox.s[i].p[1];
}
std::cout << "****input list:\n"; ox.print(n);
for(i=0;i<n;++i) {
for(j=0;j<n-i-1;++j) {
if( ox[j] > ox[j+1] ) {
q = ox(j);
ox(j) = ox(j+1);
ox(j+1) = q;
}
}
}
std::cout << "****sorted list:\n"; ox.print(n);
return 0;
}
A test run with `n = 5` in my MSYS2 system
$ ./a.exe
input n = 5
a[0].p[0] ,p[1] = 5 5
a[1].p[0] ,p[1] = 7 7
a[2].p[0] ,p[1] = 3 3
a[3].p[0] ,p[1] = 8 8
a[4].p[0] ,p[1] = 4 4
****input list:
No 0 = (5, 5)
No 1 = (7, 7)
No 2 = (3, 3)
No 3 = (8, 8)
No 4 = (4, 4)
****sorted list:
No 0 = (3, 3)
No 1 = (4, 4)
No 2 = (5, 5)
No 3 = (7, 7)
No 4 = (8, 8)
Good luck!
I have 2 arrays : a [ ] = {1,2,3,4,5,6} and b [ ] = {1,2,6}. How can I compare all elements from array a with all from array b. For example, I compare the first element from a with all elements from b, and if they are not equal, it's displayed and continue to check. So after all I need to get c [ ] = {3,4,5}.
Please help me.
for(i=0;i<n;i++)
{
for(j=0;j<k;j++)
{
if(sf[i].r != temp[j].r)
{
cout<<sf[i].r<<" ";
}
}
}
Where sf[ ] .r = {1,2,2,2,3,5,6,6,7,8,8} and temp[ ].r = { 1,3,5,7} . Output must be {2,2,2,6,6,8,8}.
Just use a std::vector<int> to build up your results, something like:
std::vector<int> set_difference;
for (int elem_a : a)
{
if (std::find(std::begin(b), std::end(b), elem_a) == std::end(b))
{
set_difference.push_back(elem_a);
}
}
int a[] = { 1, 2, 3, 4, 5, 6 };
int b[] = { 1, 3, 6, 2, 5, 9 };
std::vector<int> c;
for (int i = 0; i < sizeof(a); i++)
{
for(int j = 0; j < sizeof(b); j++)
{
if (a[i] == b[j])
std::cout << a[i] << " equals " << b[j] << std::endl;
else
{
std::cout << a[i] << "not equals " << b[j] << std::endl;
c.push_back(a[i]);
}
}
}
I'm trying to create a code that counts the number of positive and negative numbers from a given array using a function. For example in the array {-1, 2, -3, 4.5 , 0, .3, -999.99} it's supposed to show 2 positive numbers, and 4 negative numbers and excludes the number 0.
I'm using two counters to keep track of how many negative and positive numbers, a for loop to cycle through the array, but I don't know how to incorporate the boolean parameter when true or false is called on to display the right counter.
My code isn't outputting the right information and any tips would be help on how to improve my code.
#include <iostream>
using namespace std;
int countingArray(float list[], int size, bool)
{
int NumberOfPositives = 0;
int NumberOfNegatives = 0;
for (int index = 0; index < size; index++) {
if (list[index] > 0) {
if (true) {
NumberOfPositives++;
}
}
else if (list[index] < 0) {
if (false) {
NumberOfNegatives++;
}
}
else if (list[index] == 0)
continue;
}
return NumberOfPositives;
return NumberOfNegatives;
}
int main()
{
float list[] = { -1, 2, -3, 4.5, 0, -3, -999.99 };
cout << "# of Pos. = " << countingArray(list, 7, true) << endl;
cout << "# of Pos. = " << countingArray(list, 7, false) << endl;
system("PAUSE");
return 0;
}
You cannot return 2 values. Once you return, that function immediately ends.
Therefore, countingArray will only return the number of positive numbers you have, as return NumberOfPositives occurs before return NumberOfNegatives.
I would have wrote it this way:
void countingArray(float list[], int size, int& positive, int& negative) {
for (int index = 0; index < size; index++)
if (list[index] > 0)
++positive;
else if (list[index] < 0)
++negative;
}
int main() {
float list[] = { -1, 2, -3, 4.5, 0, -3, -999.99 };
int positive = 0;
int negative = 0;
countingArray(list, 7, positive, negative);
cout << "# of Pos. = " << positive << endl;
cout << "# of Pos. = " << negative << endl;
system("PAUSE");
return 0;
}
Pass the counters by reference so you don't loop array twice.
And your problem is you return twice from your function if doing it your way you need to check the boolean flag before returning and return positive or negative counter based on your flag.
Also, you can use std::array instead c type array, that way you can loop through array using iterator and you won't need to pass array size.
Something like this would do it:
#include <iostream>
struct PosNeg
{
void reset()
{
p = n = z = 0;
}
int p; // Positive.
int n; // Negative.
int z; // Zero.
};
void pos_neg(float* arr, int sz, PosNeg& count)
{
for (int i = 0; i < sz; ++i)
{
if (arr[i] < 0)
{
count.n++;
}
else if (arr[i] == 0)
{
count.z++;
}
else
{
count.p++;
}
}
}
int main()
{
float arr[] = { 1.0f, 2.0f, 3.0f, 0.0f, -1.0f, -2.0f, -3.0f };
PosNeg pn;
pn.reset();
pos_neg(arr, 7, pn);
std::cout << "Pos: " << pn.p << " Neg: " << pn.n << " Zero: " << pn.z << "\n";
std::cin.get();
return 0;
}
Encompass everything into a struct and count positive, negative number and eventually 0.
Remember that you have to set each member of the struct to zero before using it (random by default when initialized).
You might do, with std:
std::pair<std::size_t, std::size_t> countingNegPos(const float* v, std::size_t size)
{
return { std::count_if(v, v + size, [](auto f){ return f < 0; }),
std::count_if(v, v + size, [](auto f){ return f > 0; })};
}
int main()
{
const float list[] = { -1, 2, -3, 4.5, 0, -3, -999.99 };
auto [neg, pos] = countingArray(list, 7);
std::cout << "# of Neg. = " << neg << std::endl;
std::cout << "# of Pos. = " << pos << std::endl;
}