i'm new to c++, recently I discovered a function called accumulate(). I searched over internet about what it is, and read the C++ Reference tutorial, but couldn't understand what it does
#include <iostream>
#include <numeric>
using namespace std;
int main ()
{
int init = 100;
int numbers[] = {10,20,30};
cout << accumulate(numbers,numbers+3,init) << "\n";
}
Why is the output of the above program 160? I would like to know what the function does and how it works. Any types help appreciated.
accumulate without a special function takes two iterators and returns the sum, your init specifies the starting variable. It's like fold or a functional "reduce." The code above gives 160 because it's calculating
100 + 10 + 20 + 30
numbers will be a pointer to the beginning of the array, numbers+3 is "one-past-end" a typical c++ iterator idiom. It might be clearer if it was written out as
#include <iostream>
#include <iterator>
#include <numeric>
int main ()
{
int init = 100;
int numbers[] = {10,20,30};
std::cout << std::accumulate(std::begin(numbers), std::end(numbers), init) << "\n";
}
It should be clearer in this example what the range is, the beginning of numbers to the end of numbers. The init variable becomes vital in different cases such as an empty sequence.
You could also specify a different function to use instead of addition, the following will result in init * 10 * 20 * 30
int mul(int a, int b) {
return a * b;
}
int main ()
{
int init = 100;
int numbers[] = {10,20,30};
std::cout << std::accumulate(std::begin(numbers), std::end(numbers), 1, mul) << "\n";
}
Though such simple functions are often written as lambdas
We can represent the function like this :
accumulate(first, last, init)
Here accumulate() function sums up all the values in the range [first,last) that is between first and (last-1) index
And here init is the initial value of the sum.
The function is similar to the following c++ code :
#include <iostream>
#include <numeric>
using namespace std;
int main ()
{
int init = 100;
int numbers[] = {10,20,30};
int first = 0, last = 3;
int sum = init;
for(int i = first ;i < last ;i++)
sum = sum + numbers[i];
cout << sum << "\n";
}
So in your example : init + number[0] + number[1] + number[2] = 100 + 10 + 20 +30 = 160
One more thing :
accumulate(numbers, numbers + 3, init)
You may ask, why we are passing numbers in the first parameter rather than 0 ?
The answer is :
Here accumulate() function does not know which array you are willing to sum up.
So you need to inform the starting address that is address of numbers[0] to the function.
And if you want to sum up element between x position to y-1 position. You have to write this :
accumulate(numbers + x, numbers + y, init)
std::accumulate
is what it's name suggests. It just sums up the whole sequence. In addition you can provide an initial value. In your case initial value is 100.
Well, if you read the documentation it says
Returns the result of accumulating all the values in the range
[first,last) to init.
So...
numbers = 10 + 20 + 30 = 60 , init = 100 => 100+60 => 160.
std::accumulate is taking as first iterator, number, and last iterator number+3.
Related
I am writing a simple C++ program that should combine all elements of an integer array to form one number. Eg. {4,5,6} --> should be 456. But my output is one less than the original number. i.e instead of 456, I am getting 455. Sometimes my program works fine and sometimes not. Can someone please explain to me what is causing this unpredictible behaviour? Thank You!!
Please take a look at my code:
#include <bits/stdc++.h>
#include <cmath>
using namespace std;
int main()
{
int A[5] = {4,5,6,7,8};
int lengthA = 5;
int num = 0;
for(int x = 0; x < lengthA; x++)
{
num = A[x]*pow(10,lengthA-1-x) + num;
}
printf("%d\n", num ); // My O/P is 45677
}
As mentioned by Bob__, pow is a function for doubles and other floating-point types. For this specific algorithm, instead, we can do this:
int A[5] = {4,5,6,7,8};
int lengthA = 5;
int num = 0;
for(int x = 0; x < lengthA; x++)
{
num = num*10 + A[x];
}
At each step, this multiplies the previous number by 10, and makes the digit correct at that place.
E.g.
Step 1: num = 0*10 + 4 == 4
Step 2: num = 4 * 10 + 5 == 40 + 5 == 45
Step 3: num = 45 * 10 + 6 == 450 + 6 == 456
Step 4: num = 456 * 10 + 7 == 4560 + 7 == 4567
Step 5: num == 4567 * 10 + 8 == 45670 + 8 == 45678
From this simple problem you can already learn quite a bit to improve your C++ code.
Example :
// #include <bits/stdc++.h> // NO : https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h
// using namespace std // NO : https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice
#include <iostream> // include only what you need for std::cout
int main()
{
int values[]{ 4,5,6,7,8 }; // no need for an =
int num{ 0 };
// prefer range based for loops
// they will not run out of bounds
// https://en.cppreference.com/w/cpp/language/range-for
for (const int value : values)
{
num *= 10;
num += value;
}
// avoid printf, use std::cout with C++20 std::format for formatting
// https://stackoverflow.com/questions/64042652/is-printf-unsafe-to-use-in-c
// https://en.cppreference.com/w/cpp/utility/format/format
std::cout << "num = " << num << "\n";
return 0;
}
Here is another way for this problem. You can use string to convert this numbers as you need.
With this loop, we convert each number to string and pase it to end of the num string. At the end, you have the number as you need as string. If you need that number as integer, you can conver it back at the end of the loop. To conver string to int you can check this :Converting String to Numbers
#include <iostream> //include to use cout
#include <string> // include to use string
using namespace std;
int main() {
int A[5] = {4,5,6,7,8}; // input array
int lengthA = sizeof(A) / sizeof(A[0]); // size of array
std::string num = "";
for(int i=0; i<lengthA; i++){
num += std::to_string(A[i]);
}
std::cout << "Number : " << num;
}
In addition to jh316's solution;
#include <iostream>
using namespace std;
int A[] = {4,5,6,7,8};
int num = 0;
int main()
{
for(int i: A){
num = num * 10 + i;
}
cout << num;
}
Description of the code:
Initial state of the variable: num = 0
For each iteration the num variable is:
1. num = 0 * 10 + 4 = 4
2. num = 4 * 10 + 5 = 45
3. num = 45 * 10 + 6 = 456
4. num = 456 * 10 + 7 = 4567
5. num = 4567 * 10 + 8 = 45678
Here when you call pow;
pow(10,lengthA-1-x)
your code is probably calling the following overload of std::pow:
double pow ( double base, int iexp );
And as can be seen, it returns a floating-point value which might have a rounding error. I ran your code on my system and the results were correct. However, your code might generate different results on different platforms. And it seems that this is the case in your system.
Instead, you can do this:
#include <cstdio>
#include <array>
#include <span>
constexpr int convertDigitsToNumber( const std::span<const int> digits )
{
int resultNum { };
for ( const auto digit : digits )
{
resultNum = resultNum * 10 + digit;
}
return resultNum;
}
int main( )
{
constexpr std::size_t arraySize { 5 };
// use std::array instead of raw arrays
constexpr std::array<int, arraySize> arrayOfDigits { 4, 5, 6, 7, 8 };
constexpr int num { convertDigitsToNumber( arrayOfDigits ) };
std::printf( "%d\n", num );
return 0;
}
As a result of using constexpr keyword, the above function will be evaluated at compile-time (whenever possible, which is the case in the above code).
Note regarding constexpr: Use const and constexpr keywords wherever possible. It's a very good practice. Read about it here constexpr (C++).
Note: If you are not familiar with std::span then check it out here.
I have to code a program in which a user input some number and the program have to swap the first digit form last number.
For Example user inputs: 12345
The expected output would then be: 52341
But I am getting an error and getting output like: 4465
This is my Code:
#include <iostream>
#include <cmath>
using namespace std;
void main()
{ int num,ln,fn,pw,dg,swap;
cin >> num;
ln = num%10 ;
dg = log10(num);
pw = pow(10,dg);
fn = num%pw;
swap = ln*pw;
swap = swap+num/pw;
swap = swap-ln;
swap = swap+fn;
cout << swap << endl;
system ("pause");
}
Help me to solve this.
Ok I'll do it.
0. Design choice(s)
The operation you want to do is not on the value of the input number but rather on its representation, specifically in base 10. We'd better go for a string manipulation then.
1. Integer to string
With C++11 and following, we do have std::to_string: takes an integer, returns a string, done.
2. Accessing characters from a string
If the string is not empty, std::string::front() and std::string::back() return a reference to the first and last characters of that string, easy.
3. Swapping characters
We have the utility std::swap and the swap idiom
using std::swap;
swap(lhs, rhs);
lhs and rhs being what needs to be swapped (see step 2.).
4. Back to integer
We have std::stoi doing what std::to_string does but in reverse, done. But what if the new integer has become too big to be held by an integer type?
5. Putting all together
Let's define a (free) function!
int reverse_border_digits(int value)
{
// steps 1 through 4
return result;
}
Here's an answer fulfilling the OP requirements
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int num;
cin >> num;
int dg = (int)(log10(num + 0.000001)); // add small delta to avoid any possible rounding error on an exact power of ten
int pw = (int)round(pow(10.0, dg));
int swap = (num % 10) * pw + (num - num % 10 - (num / pw) * pw) + num / pw;
cout << swap << '\n';
}
I want to write a program where input are x and y integer values
and then:
Let s be the set { x0, 𝑥1, …, 𝑥y}; store it in array.
Repeat:
Partition the set s into two subsets: s1 and s2.
Find the sum of each of the two subset and store them in variables like sum1, sum2.
Calculate the product of sum1 * sum2.
The program ends after passing all over the partial groups that could be formed and then prints the max value of the product sum1 * sum2.
example: suppose x=2 , y=3 s= {1,2,4,8} one of the divisions is to take s1 ={1,4} , s2={2,8} sum1=5 , sum2= 10 the product is 50 and that will be compared to other productd that were calculated in the same way like s1 ={1} , s2={2,4,8} sum1=1 , sum2=14 and the product is 14 and so on.
My code so far:
#include <iostream>
using namespace std;
int main ()
{
int a[10000]; // Max value expected.
int x;
int y;
cin >> x;
cin >> y;
int xexpy = 1;
int k;
for (int i = 0; i <= y; i++)
{
xexpy = 1;
k = i;
while(k > 0)
{
xexpy = xexpy * x;
k--;
}
cout << "\n" << xexpy;
a[i] = xexpy;
}
return 0;
}
This is not a programming problem, it is a combinatorics problem with a theoretical rather than an empirical approach to its solution. You can simply print the correct solution and not bother iterating over any partitions.
Why is that?
Let
i.e. z is the fraction of the sum of all s elements that's in s1. It holds that
and thus, the product of both sets satisfies:
As a function of z (not of x and y), this is a parabola that takes its maximum at z = 1/2; and there are no other local maximum points, i.e. getting closer to 1/2 necessarily increases that product. Thus what you want to do is partition the full set so that each of s1 and s2 are as close as possible to have half the sum of elements.
In general, you might have had to use programming to consider multiple subsets, but since your elements are given by a formula - and it's the formula of a geometric sequence.
First, let's assume x >= 2 and y >= 2, otherwise this is not an interesting problem.
Now, for x >= 2, we know that
(the sum of a geometric sequence), and thus
i.e. the last element always outweighs all other elements put together. That's why you always want to choose {xy} as s1 and as all other elements as s2. No need to run any program. You can then also easily calculate the optimum product-of-sums.
Note: If we don't make assumptions about the elements of s, except that they're non-negative integers, finding the optimum solution is an optimization version of the Partition problem - which is NP-complete. That means, very roughly, that there is no solution is fundamentally much more efficient than just trying all possible combinations.
Here's a cheesy all-combinations-of-supplied-arguments generator, provided without comment or explanation because I think this is homework, and the exercise of understanding how and why this does what it does is the point here.
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main(int c, const char **v)
{
basic_string<const char *> options(v);
auto N(options.length());
for (auto n = 1u; n < N; ++n) {
vector<char> pick(N);
fill_n(pick.rbegin(), n, 1);
do for (auto j=1u; j<N; ++j)
if (pick[j])
cout << options[j]<<' ';
while (cout<<'\n', next_permutation(begin(pick)+1, end(pick)));
}
}
I'm a programming student, and for a project I'm working on, on of the things I have to do is compute the median value of a vector of int values and must be done by passing it through functions. Also the vector is initially generated randomly using the C++ random generator mt19937 which i have already written down in my code.I'm to do this using the sort function and vector member functions such as .begin(), .end(), and .size().
I'm supposed to make sure I find the median value of the vector and then output it
And I'm Stuck, below I have included my attempt. So where am I going wrong? I would appreciate if you would be willing to give me some pointers or resources to get going in the right direction.
Code:
#include<iostream>
#include<vector>
#include<cstdlib>
#include<ctime>
#include<random>
#include<vector>
#include<cstdlib>
#include<ctime>
#include<random>
using namespace std;
double find_median(vector<double>);
double find_median(vector<double> len)
{
{
int i;
double temp;
int n=len.size();
int mid;
double median;
bool swap;
do
{
swap = false;
for (i = 0; i< len.size()-1; i++)
{
if (len[i] > len[i + 1])
{
temp = len[i];
len[i] = len[i + 1];
len[i + 1] = temp;
swap = true;
}
}
}
while (swap);
for (i=0; i<len.size(); i++)
{
if (len[i]>len[i+1])
{
temp=len[i];
len[i]=len[i+1];
len[i+1]=temp;
}
mid=len.size()/2;
if (mid%2==0)
{
median= len[i]+len[i+1];
}
else
{
median= (len[i]+0.5);
}
}
return median;
}
}
int main()
{
int n,i;
cout<<"Input the vector size: "<<endl;
cin>>n;
vector <double> foo(n);
mt19937 rand_generator;
rand_generator.seed(time(0));
uniform_real_distribution<double> rand_distribution(0,0.8);
cout<<"original vector: "<<" ";
for (i=0; i<n; i++)
{
double rand_num=rand_distribution(rand_generator);
foo[i]=rand_num;
cout<<foo[i]<<" ";
}
double median;
median=find_median(foo);
cout<<endl;
cout<<"The median of the vector is: "<<" ";
cout<<median<<endl;
}
The median is given by
const auto median_it = len.begin() + len.size() / 2;
std::nth_element(len.begin(), median_it , len.end());
auto median = *median_it;
For even numbers (size of vector) you need to be a bit more precise. E.g., you can use
assert(!len.empty());
if (len.size() % 2 == 0) {
const auto median_it1 = len.begin() + len.size() / 2 - 1;
const auto median_it2 = len.begin() + len.size() / 2;
std::nth_element(len.begin(), median_it1 , len.end());
const auto e1 = *median_it1;
std::nth_element(len.begin(), median_it2 , len.end());
const auto e2 = *median_it2;
return (e1 + e2) / 2;
} else {
const auto median_it = len.begin() + len.size() / 2;
std::nth_element(len.begin(), median_it , len.end());
return *median_it;
}
There are of course many different ways how we can get element e1. We could also use max or whatever we want. But this line is important because nth_element only places the nth element correctly, the remaining elements are ordered before or after this element, depending on whether they are larger or smaller. This range is unsorted.
This code is guaranteed to have linear complexity on average, i.e., O(N), therefore it is asymptotically better than sort, which is O(N log N).
Regarding your code:
for (i=0; i<len.size(); i++){
if (len[i]>len[i+1])
This will not work, as you access len[len.size()] in the last iteration which does not exist.
std::sort(len.begin(), len.end());
double median = len[len.size() / 2];
will do it. You might need to take the average of the middle two elements if size() is even, depending on your requirements:
0.5 * (len[len.size() / 2 - 1] + len[len.size() / 2]);
Instead of trying to do everything at once, you should start with simple test cases and work upwards:
#include<vector>
double find_median(std::vector<double> len);
// Return the number of failures - shell interprets 0 as 'success',
// which suits us perfectly.
int main()
{
return find_median({0, 1, 1, 2}) != 1;
}
This already fails with your code (even after fixing i to be an unsigned type), so you could start debugging (even 'dry' debugging, where you trace the code through on paper; that's probably enough here).
I do note that with a smaller test case, such as {0, 1, 2}, I get a crash rather than merely failing the test, so there's something that really needs to be fixed.
Let's replace the implementation with one based on overseas's answer:
#include <algorithm>
#include <limits>
#include <vector>
double find_median(std::vector<double> len)
{
if (len.size() < 1)
return std::numeric_limits<double>::signaling_NaN();
const auto alpha = len.begin();
const auto omega = len.end();
// Find the two middle positions (they will be the same if size is odd)
const auto i1 = alpha + (len.size()-1) / 2;
const auto i2 = alpha + len.size() / 2;
// Partial sort to place the correct elements at those indexes (it's okay to modify the vector,
// as we've been given a copy; otherwise, we could use std::partial_sort_copy to populate a
// temporary vector).
std::nth_element(alpha, i1, omega);
std::nth_element(i1, i2, omega);
return 0.5 * (*i1 + *i2);
}
Now, our test passes. We can write a helper method to allow us to create more tests:
#include <iostream>
bool test_median(const std::vector<double>& v, double expected)
{
auto actual = find_median(v);
if (abs(expected - actual) > 0.01) {
std::cerr << actual << " - expected " << expected << std::endl;
return true;
} else {
std::cout << actual << std::endl;
return false;
}
}
int main()
{
return test_median({0, 1, 1, 2}, 1)
+ test_median({5}, 5)
+ test_median({5, 5, 5, 0, 0, 0, 1, 2}, 1.5);
}
Once you have the simple test cases working, you can manage more complex ones. Only then is it time to create a large array of random values to see how well it scales:
#include <ctime>
#include <functional>
#include <random>
int main(int argc, char **argv)
{
std::vector<double> foo;
const int n = argc > 1 ? std::stoi(argv[1]) : 10;
foo.reserve(n);
std::mt19937 rand_generator(std::time(0));
std::uniform_real_distribution<double> rand_distribution(0,0.8);
std::generate_n(std::back_inserter(foo), n, std::bind(rand_distribution, rand_generator));
std::cout << "Vector:";
for (auto v: foo)
std::cout << ' ' << v;
std::cout << "\nMedian = " << find_median(foo) << std::endl;
}
(I've taken the number of elements as a command-line argument; that's more convenient in my build than reading it from cin). Notice that instead of allocating n doubles in the vector, we simply reserve capacity for them, but don't create any until needed.
For fun and kicks, we can now make find_median() generic. I'll leave that as an exercise; I suggest you start with:
typename<class Iterator>
auto find_median(Iterator alpha, Iterator omega)
{
using value_type = typename Iterator::value_type;
if (alpha == omega)
return std::numeric_limits<value_type>::signaling_NaN();
}
I want to print the amount of numbers that are within the range of two numbers (those two numbers included).
I have created this simple code:
#include <iostream>
int main(int argc, char *argv[]) {
int one = -5;
int two = 5;
unsigned int count = 0;
int min = std::min(one, two);
int max = std::max(one, two);
while (min <= max) {
count++;
min++;
}
std::cout << count << std::endl;
return 0;
}
In this example I use -5 to 5 and it correctly prints 11.
How can I improve this algorithm so that it works without problem with numbers ranging from for example -1 billion to 1 billion?
Or is the code fine as it stands?
The number of numbers in that range is simply their difference + 1:
count = max - min + 1;
Or, without evaluating which is the max and which the min, use the absolute value of the difference
count = std::abs(one - two) + 1;
Maybe I missed something, but
#include <iostream>
int main(int argc, char *argv[]) {
int one = -5;
int two = 5;
unsigned int count = std::abs(one-two)+1;
std::cout << count << std::endl;
return 0;
}
should do exactly what you want?
This will give 11 for -5 and 5, which is in fact the count of numbers betweeen -5 and 5, including both. If you want it to print 10, as you said in your quetion you have to remove the +1.
You need to use an integral type that can contain such range of numbers. At present the greatest fundamental signed integral type in C++ is long long int You can get the range of numbers it can store by using expressions
std::numeric_limits<long long int>::min() and std::numeric_limits<long long int>::max()
structure std::numeric_limits is defined in header <limits>
For example
#include <iostream>
#include <limits>
int main()
{
std::cout << std::numeric_limits<long long int>::min() << " - "
<< std::numeric_limits<long long int>::max() << std::endl;
}
Also it would be better if the program would ask the user to enter the two numbers. For big ranges it is better to use a simple arithmetic expression to get the counter instead of using the loop.