Created
March 9, 2017 20:56
-
-
Save anonymous/e12bdda4299814180cafffa341fdf9ca to your computer and use it in GitHub Desktop.
The Pi Day Challenge 02/2017
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <cmath> | |
#include <vector> | |
#include <algorithm> | |
#include <utility> | |
constexpr double PI = 3.14159265359; | |
template<typename T> | |
class RandomPointGenerator | |
{ | |
public: | |
RandomPointGenerator(std::mt19937& engine, T inf, T sup) : m_engine(engine), m_dist(inf, sup) { } | |
std::pair<T, T> operator()() | |
{ | |
return std::make_pair(m_dist(m_engine), m_dist(m_engine)); | |
} | |
private: | |
std::mt19937& m_engine; | |
std::uniform_int_distribution<T> m_dist; | |
}; | |
template<typename T> | |
std::vector<std::pair<T, T>> generateListOfPoints(unsigned long count, RandomPointGenerator<T> gen) | |
{ | |
std::vector<std::pair<T, T>> points; | |
points.reserve(count); | |
std::generate_n(std::back_inserter(points), count, gen); | |
return points; | |
} | |
auto inCircle(long radius) | |
{ | |
return [&radius](const auto& p) { | |
long x = std::get<0>(p); | |
long y = std::get<1>(p); | |
return x * x + y * y < radius * radius; | |
}; | |
} | |
class PiEstimator | |
{ | |
public: | |
PiEstimator() : m_engine(m_random_device()) {} | |
double operator()(long radius, unsigned long points_count) | |
{ | |
auto points = generateListOfPoints(points_count, RandomPointGenerator<long>{m_engine, -radius, radius}); | |
unsigned long points_count_in_circle = std::count_if(points.begin(), points.end(), inCircle(radius)); | |
return 4.0 * points_count_in_circle / points_count; | |
} | |
private: | |
std::random_device m_random_device; | |
std::mt19937 m_engine; | |
}; | |
template<long base> | |
std::vector<long> listOfPow(std::size_t count) | |
{ | |
std::vector<long> values; | |
values.reserve(count); | |
for (long exponent = 0; exponent < count; ++exponent) { | |
values.push_back(std::pow(base, exponent)); | |
} | |
return values; | |
} | |
double pi_error(double estimated_pi) | |
{ | |
return std::abs(PI-estimated_pi); | |
} | |
int main() | |
{ | |
PiEstimator pi_estimator; | |
for (long radius: listOfPow<10>(10)) { | |
for (long points_count: listOfPow<10>(7)) { | |
std::cout << pi_error(pi_estimator(radius, points_count)) << ' '; | |
} | |
std::cout << '\n'; | |
} | |
std::cout << std::endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment