Skip to content

Instantly share code, notes, and snippets.

@JSzitas
Last active April 20, 2023 12:24
Show Gist options
  • Save JSzitas/921726d1a91320991b19331465a1f06e to your computer and use it in GitHub Desktop.
Save JSzitas/921726d1a91320991b19331465a1f06e to your computer and use it in GitHub Desktop.
Count how many people are alive per year, based on their birthyear and deathyear
#include <chrono>
#include <iostream>
#include <vector>
constexpr size_t kPeople = 10000;
constexpr size_t kLowBoundAge = 1;
constexpr size_t kHighBoundAge = 100;
constexpr size_t kAgeLen = kHighBoundAge - kLowBoundAge;
int main()
{
// do not benchmark creation of test data - the other implementation does not do this
// either
static_assert(kAgeLen < RAND_MAX);
// use size_t to avoid annoying signed integer compare warnings
size_t personBirthday[kPeople] = {};
size_t personDeath[kPeople] = {};
// Filling
for (size_t i = 0; i < kPeople; ++i)
{
personBirthday[i] = 1900 + rand() % (1 + 2000 - 1900);
personDeath[i] = personBirthday[i] + kLowBoundAge + rand() % (kAgeLen + 1);
}
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
//mark out the years - which we understand to be a continguous block -
// and we add to the population over those years - addition over a continguous
// vector is much faster than a map - we also know the size ahead of time
// but std::array should not be very different, both offer continguous storage
std::vector<int> population(100,0);
// this makes more sense for the problem at hand, as the years must be,
// by design, a continguous sequence (a person cannot be alive, then dead,
// then alive again...)
constexpr size_t kNumberRepeats = 100;
for (size_t r = 0; r < kNumberRepeats; r++)
{
// reset contents of population vector
std::fill(population.begin(), population.end(), 0);
for (size_t i = 0; i < kPeople; i++)
{
for (size_t year = personBirthday[i]; year < personDeath[i]; year++)
{
population[year] += 1;
}
}
}
// we should not benchmark the time it takes us to print the output - the other benchmarked version is not doing that
// either
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
std::cout << "Time difference = " << std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count() << " [milliseconds]" << std::endl;
return 0;
}
// for this I get a timing of roughly 20 milliseconds, or 0.02 seconds
// again, compile with
// g++ -O3 -DNDEBUG -std=c++17 test.cpp -o my_app
// but using clang++ I get the same timings, so likely leads to same code
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment