Step 4 of 6
accumulate and transform
Two more workhorses:
std::accumulate(from<numeric>, not<algorithm>) folds a range into one value: start with an initial value, then combine it with each element in turn. By default "combine" means+.std::transformapplies a function to each element and writes the results to another place.
#include <algorithm>
#include <iostream>
#include <numeric>
#include <cctype>
#include <string>
#include <vector>
int main() {
std::vector<int> v = {3, 1, 4, 1, 5};
int sum = std::accumulate(v.begin(), v.end(), 0);
int product = std::accumulate(v.begin(), v.end(), 1, [](int acc, int x) { return acc * x; });
double avg = std::accumulate(v.begin(), v.end(), 0.0) / v.size();
std::cout << sum << " " << product << " " << avg << "\n";
std::vector<int> cubes(v.size());
std::transform(v.begin(), v.end(), cubes.begin(), [](int x) { return x * x * x; });
for (int c : cubes) std::cout << c << " ";
std::cout << "\n";
std::string shout = "quiet please";
std::transform(shout.begin(), shout.end(), shout.begin(), [](char c) { return (char)std::toupper(c); });
std::cout << shout << "\n";
}
14 60 2.8
27 1 64 1 125
QUIET PLEASE
The initial value decides the type
accumulate does its arithmetic in the type of the initial value. std::accumulate(v.begin(), v.end(), 0) adds ints and returns an int. For an average you want 0.0, so the sum is a double. Writing 0 there and then dividing is a classic bug: the sum is fine, but a range of doubles would be truncated to ints at every step.
transform needs room
std::transform writes to the output iterator you give it, but it doesn't create elements. That's why the example sizes cubes first with cubes(v.size()). The output can also be the input itself, as with shout, which changes the string in place.
Edge case: empty ranges
Averaging an empty vector divides by zero. Check v.empty() first and return the agreed default.
Your turn: write double average_damage(const std::vector<int>& hits) (0 for an empty vector) and std::vector<int> with_armor(const std::vector<int>& hits) that halves every hit (integer division). Use accumulate and transform.