Last active
March 11, 2017 12:47
-
-
Save FredTingaud/5c6c7890f11abc07b9ad44dd68970150 to your computer and use it in GitHub Desktop.
FredTingaud's proposal for Pi Day Challenge
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 <range/v3/all.hpp> | |
#include <iostream> | |
#include <iterator> | |
#include <random> | |
#include <iomanip> | |
using namespace ranges::v3; | |
std::random_device random_device; | |
std::mt19937 engine{random_device()}; | |
static const double REF_PI = 3.14159265359; | |
struct Point | |
{ | |
Point(int x1, int y1) : x(x1), y(y1) {} | |
int x, y; | |
}; | |
auto randomPoint(int max) | |
{ | |
std::uniform_int_distribution<int> dist(0, max); | |
return Point(dist(engine), dist(engine)); | |
} | |
bool inCircle(const Point& p, int radius) | |
{ | |
return p.x * p.x + p.y * p.y < radius * radius; | |
} | |
bool randomSample(int radius) | |
{ | |
return inCircle(randomPoint(radius), radius); | |
} | |
int power10(int n) | |
{ | |
return std::pow(10, n); | |
} | |
auto monteCarloEntries(int radius, int repeat) | |
{ | |
return view::repeat_n(radius, repeat); | |
} | |
double monteCarloSampling(int radius, int repeat) | |
{ | |
return 4. * distance(monteCarloEntries(radius, repeat) | view::filter(randomSample)) / repeat; | |
} | |
std::string formatResult(double result) | |
{ | |
std::ostringstream os; | |
os << std::fixed << std::setfill(' ') << std::setw(15) << result; | |
return os.str(); | |
} | |
auto resultPrinter(int radius) | |
{ | |
return view::transform([=] (int repeat) {return std::abs(REF_PI - monteCarloSampling(radius, repeat));}) | view::transform(formatResult); | |
} | |
std::string printResultBySizeForRadius(int radius, int maxRepeats) | |
{ | |
return view::iota(1, maxRepeats + 1) | view::transform(power10) | resultPrinter(radius) | action::join; | |
} | |
auto printResultBySize(int maxRepeats) | |
{ | |
return view::transform([=] (int radius){return printResultBySizeForRadius(radius, maxRepeats); }); | |
} | |
auto radiuses(int n) | |
{ | |
return view::iota(1, n + 1) | view::transform(power10); | |
} | |
void runSampling(int n, int m) | |
{ | |
copy(radiuses(n) | printResultBySize(m), ostream_iterator<>(std::cout, "\n")); | |
} | |
int main(int argc, char** argv) | |
{ | |
if (argc == 3) | |
{ | |
int radius; | |
int size; | |
std::istringstream isRad(argv[1]); | |
isRad >> radius; | |
std::istringstream isSize(argv[2]); | |
isSize >> size; | |
runSampling(radius, size); | |
} | |
else | |
std::cerr << "Usage: ./" << argv[0] << " radiusCount sizeCount" << std::endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment