First of all, I don't want to use sort. This is just an illustration example. The main purpose of this question is that I want to:
find all possible combinations of m numbers out of n numbers and
process them, then return the unique processed result (since the
processed results of all possible combinations will be compared).
Question start at here
The following code get all possible combinations M numbers out of N numbers. Sum the M numbers and find the largest sum. In doing this I used a recursion function.
However, it seems that I must define a global variable to store the temporary largest sum. Is there any way to get rid of this global variable? For example, define the recursion function to return the largest sum... I don't want the global variable just become an argument &max_sum in the find_sum, since find_sum already have too many arguments.
#include <iostream>
#include <vector>
void find_sum(const std::vector<int>& ar, std::vector<int>& combine,
int index, int start);
int max_sum =0;
int main() {
int N = 10;
int M = 3;
std::vector<int> ar(N);
ar = {0,9,2,3,7,6,1,4,5,8};
int index = 0, start =0;
std::vector<int> combine(M);
find_sum(ar, combine, index, start);
std::cout << max_sum <<std::endl;
return 0;
}
void find_sum(const std::vector<int>& ar, std::vector<int>& combine,
int index, int start) {
if(index == combine.size()) {
int sum =0;
for(int i=0; i<index; ++i) {
sum += combine[i];
}
if(max_sum < sum) {
max_sum = sum;
}
return ;
}
for(int i = start;
i < ar.size() && ar.size()-i > combine.size()-index;
++i) {
combine[index] = ar[i];
find_sum(ar, combine, index+1, start+1);
}
}
An approach that scales well is to turn find_sum into a function object. The trick is to define a struct with an overloaded () operator that takes a certain set of parameters:
struct FindSum
{
void operator()(const std::vector<int>& ar, std::vector<int>& combine,
int index, int start){
/*ToDo - write the function here, a very explicit way of
/*engineering the recursion is to use this->operator()(...)*/
}
int max_sum; // I am now a member variable
};
Then instantiate FindSum find_sum;, set find_sum.max_sum if needed (perhaps even do that in a constructor), then call the overloaded () operator using find_sum(...).
This technique allows you to pass state into what essentially is a function.
From find_sum, return the so-far maximum sum (instead of void). That means that the recursion-terminating code would be:
if(index == combine.size()) {
int sum =0;
for(int i=0; i<index; ++i) {
sum += combine[i];
}
return sum;
}
and the recursive part would be
int max_sum = 0;
for(int i = start;
i < ar.size() && ar.size()-i > combine.size()-index;
++i) {
combine[index] = ar[i];
int thismaxsum = find_sum(ar, combine, index+1, start+1);
if(thismaxssum > max_sum)
max_sum = thismaxsum;
}
return max_sum;
So, the overall solution is:
#include <iostream>
#include <vector>
int find_sum(const std::vector<int>& ar, std::vector<int>& combine,
int index, int start);
int main() {
int N = 10;
int M = 3;
std::vector<int> ar(N);
ar = { 0,9,2,3,7,6,1,4,5,8 };
int index = 0, start = 0;
std::vector<int> combine(M);
int max_sum = find_sum(ar, combine, index, start);
std::cout << max_sum << std::endl;
return 0;
}
int find_sum(const std::vector<int>& ar, std::vector<int>& combine,
int index, int start)
{
if (index == combine.size())
{
int sum = 0;
for (int i = 0; i<index; ++i)
{
sum += combine[i];
}
return sum;
}
int max_sum = 0;
for (int i = start;
i < ar.size() && ar.size() - i > combine.size() - index;
++i)
{
combine[index] = ar[i];
int thismaxsum = find_sum(ar, combine, index + 1, start + 1);
if (thismaxsum > max_sum)
max_sum = thismaxsum;
}
return max_sum;
}
Global variables are much better then adding operands and variables to recursion functions because each operand and variable causes heap/stack trashing negatively impact performance and space usage risking stack overflow for higher recursions.
To avoid global variables (for code cosmetics and multi threading/instancing purposes) I usually use context or temp struct. For example like this:
// context type
struct f1_context
{
// here goes any former global variables and stuff you need
int n;
};
// recursive sub function
int f1_recursive(f1_context &ctx)
{
if (ctx.n==0) return 0;
if (ctx.n==1) return 1;
ctx.n--;
return (ctx.n+1)*f1_recursive(ctx.n);
}
// main API function call
int f1(int n)
{
// init context
f1_context ctx;
ctx.n=n;
// start recursion
return f1_recursion(ctx);
}
the f1(n) is factorial example. This way the operands are limited to single pointer to structure. Of coarse you can add any recursion tail operands after the context... the context is just for global and persistent stuff (even if I did use it for the recursion tail instead but that is not always possible).
Related
Solution is probably pretty easy but I can't figure it out. How do I make a permanent change to the vector and not only a change that takes effect inside the function? I debugged it and I can see that "numbers" is updated with the value I want it to have but it disappears as soon as it is executed.
using namespace std;
bool checkVal();
vector<int> getNumbers();
void setPowerball(vector<int> numbers);
int main()
{
srand(time(0));
vector<int> numbers = getNumbers();
setPowerball(numbers);
for (int i = 0; i < 5; i++)
{
cout << numbers[i];
cout << " ";
}
}
bool checkVal(vector<int> numbers, int size, int value)
{
for (int i = 0; i < size; ++i)
{
if (numbers[i] == value)
{
return true;
}
}
return false;
}
void setPowerball(vector<int> numbers)
{
for (int i = 4; i < 5; i++)
{
int last = rand() % 26 + 1;
if (checkVal(numbers, i, last))
{
i--;
}
else
{
numbers.push_back(last);
}
}
}
vector<int> getNumbers()
{
vector<int> numbers;
for (int i = 0; i < 4; i++)
{
int num = rand() % 69 + 1;
if (checkVal(numbers, i, num))
{
i--;
}
else
{
numbers.push_back(num);
}
}
sort(numbers.begin(), numbers.end());
return numbers;
}
You are passing arguments to setPowerBall function by value. So whenever it's called, it gets its private copy of the vector, which gets destructed at the end of function scope.
Instead you should be passing the arguments by reference in this case.
void setPowerball(vector<int>& numbers)
{
// do stuff
}
MAIN POINTS :-
Notice the & in function declaration. It implies taking a lvalue reference.
References allow you to modify the original variable without making a copy.
References are also cheaper to pass in case of objects like std::string or std::vector. But for primitive types like int or float, pass by value is faster.
Note : You could also have used pointers to do the same but using References is recommended and safer way. Rule of the thumb is Use references when you can, and pointers when you must
I'm currently trying to program a function that would find the average of elements in an array of integers in C++.
I've looked at new c++11 for loop causes: "error: ‘begin’ was not declared in this scope" but I don't quite understand the problem and how to fix it.
double avg(int arr[]) {
double sum = 0;
int size = 0;
for (int i : arr) {
sum += i;
size += 1;
}
return sum / size;
}
It gives me errors that "'begin' was not declared in this scope" and "'end' was not declared in this scope".
Could somebody explain why the error is occurring and possible ways to fix it?
The type int arr[] decays into a raw pointer, and as a result there's no way to get the size of the array it refers to.
Instead of using raw arrays, it'd be better just to use either std::vector:
double avg(std::vector<int> const& v) {
double sum = 0;
for(int i : v)
sum += i;
return sum / v.size();
}
Or std::array, which acts like a C-array but is copyable and doesn't decay into a pointer:
template<size_t N>
double avg(std::array<int, N> const& arr) {
double sum = 0;
for(int i : arr) {
sum += i;
return sum / N;
}
Or, if you really have to use arrays, pass the size as a parameter:
double avg(int arr[], size_t size) {
double sum = 0;
for(int i = 0; i < size; i++) {
sum += arr[i];
}
return sum / size;
}
Leveraging the C++ standard library
The C++ standard library has a lot of useful functions, and one of them, accumulate, does the job perfectly. It takes a begin and end iterator, as well as the initial value, and computes the sum over the range:
#include <numeric>
double avg(std::vector<int> const& v) {
return std::accumulate(v.begin(), v.end(), 0.0) / v.size();
}
double avg(int[] arr, size_t size) {
return std::accumulate(arr + 0, arr + size, 0.0) / size;
}
Functions may not take arrays as parameters. You get a pointer there. Though you can pass a reference to an array to a function as a parameter. Here is an example:
#include <iostream>
template <typename T, auto n>
void print(const T(&arr)[n]) {
for (auto&& t : arr) {
std::cout << t << ' ';
}
std::cout << '\n';
}
int main() {
int arr[]{ 1, 2, 3, 4, 5 };
print(arr);
}
Output:
1 2 3 4 5
If you want to actually pass an array, not switch to using a vector you can do it with a template function parametrized on the size of the array i.e.
template <int N>
double avg(int (&arr)[N] ) {
double sum = 0;
int size = 0;
for (int i : arr) {
sum += i;
size += 1;
}
return sum / size;
}
int main()
{
int ary[] = { 1,2,3,4,5,6 };
std::cout << avg(ary);
}
I am new to functions. I don't know how can I output numbers of ints less than or equal to average and number of ints greater than average. How I need to call my function so that it output both results ?
int compareAverage(int numbers[], int count, double average)
{
int lessEqualCount = 0;
int greaterCount = 0;
for (int i = 0; i < count; i ++)
{
if (numbers[i] <= average){
lessEqualCount++;
return lessEqualCount;}
else{
greaterCount++;
return greaterCount;}
}
There are several solutions.
The first ones that come to my mind:
accept to pointers to int in which to write the results
return a std::pair of ints instead of a single value
return a struct having two properties for the two values
return an array (either a naked one or a std::array) containing the two values
...
It follows an example:
std::pair<int, int> compareAverage(int numbers[], int count, double average) {
std::pair<int, int> ret = std::make_pair<int, int>(0, 0);
for (int i = 0; i < count; i ++) {
if (numbers[i] <= average) {
ret.first++;
} else {
ret.second++;
}
}
return ret;
}
#include <iostream>
#include <cstdlib>
using std:: cin;
using std:: cout;
using std:: endl;
const int N=10;
void readarray(int array[], int N);
int bubble_sort (int array[], int size, int round,
int place);
int main ()
{
int array[N];
readarray( array, N );
int round, place;
cout << bubble_sort(array, N, place, round);
return EXIT_SUCCESS;
}
void readarray(int array[], int N)
{
int i=0;
if (i < N)
{
cin >> array[i];
readarray(array+1, N-1);
}
}
int bubble_sort (int array[], int size, int round,
int place)
{
round =0;
place =0;
if (round < N-1) // this goes over the array again making sure it has
// sorted from lowest to highest
{
if (place < N - round -1) // this sorts the array only 2 cells at a
// time
if (array[0] > array[1])
{
int temp = array[1];
array[1]=array[0];
array[0]=temp;
return (array+1, size-1, place+1, round);
}
return (array+1, size-1, place, round+1);
}
}
I know how to do a bubble sort using two for loops and I want to do it using recursion. Using loops you require two for loops and I figured for recursion it might also need two recursive functions/calls. This is what I have so far. The problem is that its outputting only one number, which is either 1 or 0. I'm not sure if my returns are correct.
In c++11, you can do this:
#include <iostream>
#include <vector>
void swap(std::vector<int &numbers, size_t i, size_t j)
{
int t = numbers[i];
numbers[i] = numbers[j];
numbers[j] = t;
}
bool bubble_once(std::vector<int> &numbers, size_t at)
{
if (at >= numbers.size() - 1)
return false;
bool bubbled = numbers[at] > numbers[at+1];
if (bubbled)
swap(numbers, at, at+1);
return bubbled or bubble_once(numbers, at + 1);
}
void bubble_sort(std::vector<int> &numbers)
{
if ( bubble_once(numbers, 0) )
bubble_sort(numbers);
}
int main() {
std::vector<int> numbers = {1,4,3,6,2,3,7,8,3};
bubble_sort(numbers);
for (size_t i=0; i != numbers.size(); ++i)
std::cout << numbers[i] << ' ';
}
In general you can replace each loop by a recursive function which:
check the guard -> if fail return.
else execute body
recursively call function, typically with an incremented counter or something.
However, to prevent a(n actual) stack overflow, avoiding recursion where loops are equally adequate is good practice. Moreover, a loop has a very canonical form and hence is easy to read for many programmers, whereas recursion can be done in many, and hence is harder to read, test and verify. Oh, and recursion is typically slower as it needs to create a new stackframe (citation needed, not too sure).
EDIT
Using a plain array:
#include <iostream>
#include <vector>
#define N 10
void swap(int *numbers, size_t i, size_t j)
{
int t = numbers[i];
numbers[i] = numbers[j];
numbers[j] = t;
}
bool bubble_once(int *numbers, size_t at)
{
if (at >= N - 1)
return false;
bool bubbled = numbers[at] > numbers[at+1];
if (bubbled)
swap(numbers, at, at+1);
return bubbled or bubble_once(numbers, at + 1);
}
void bubble_sort(int *numbers)
{
if ( bubble_once(numbers, 0) )
bubble_sort(numbers);
}
int main() {
int numbers[N] = {1,4,3,6,2,3,7,8,3,5};
bubble_sort(numbers);
for (size_t i=0; i != N; ++i)
std::cout << numbers[i] << ' ';
}
Please read this post
function pass(i,j,n,arr)
{
if(arr[i]>arr(j))
swap(arr[i],arr[j]);
if(j==n)
{
j=0;
i=i+1;
}
if(i==n+1)
return arr;
return pass(i,j+1,n,arr);
}
I've been used to using Python or Matlab where I could create a list like:
min = 5;
step = 2;
max = 16;
Range = min:step:max;
and Range would be the list [5,7,9,11,13,15].
Is there an equivalently simple way to generate a list like "Range" in C++? So far the simplest thing I can think of is using a for loop but that is comparatively quite tedious.
C++ doesn't supply such a thing, either in the language or the standard library. I'd write a function template to look (roughly) like something from the standard library, something on this order:
namespace stdx {
template <class FwdIt, class T>
void iota_n(FwdIt b, size_t count, T val = T(), T step = T(1)) {
for (; count; --count, ++b, val += step)
*b = val;
}
}
From there it would look something like this:
std::vector<int> numbers;
stdx::iota_n(std::back_inserter(numbers), 6, 5, 2);
You'll have to implement that yourself, something like this:
std::vector<int> createArray( int min, int max, int step )
{
std::vector<int> array;
for( int i = min; i < max; i += step )
{
array.push_back( i );
}
return array;
}
There is no such predefine method in C++ for this purpose.
Below code may help you.
std::vector<int> createArrayRange( int min, int max, int step )
{
std::vector<int> array;
for( int i = min; i < max; i += step )
{
array.push_back(i);
}
return array
}
Or This would be comparatively faster.
void createArrayRange( std::vector<int>& array, int min, int max, int step )
{
for( int i = min; i < max; i += step )
{
array.push_back(i);
}
}
int main()
{
std::vector<int> array;
createArrayRange(array, min, max, step);
return 0;
}
You can use std::generate for this.
std::vector< int > createArray( int min, int max, int step )
{
std::vector< int > array((max-min)/step);
int n = min;
std::generate(array.begin(), array.end(),
[&]()
{
int res = n;
n+=step;
return res;
});
return array;
}
No explicit loops needed:
vector<int> data(6,2);
data[0] = 5;
std::partial_sum(data.begin(),data.end(),data.begin());