Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions M1/clicker.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include "clicker.hpp"

mas::Clicker::Clicker():
start_(std::chrono::high_resolution_clock::now())
{}

double mas::Clicker::millisec() const
{
auto t = std::chrono::high_resolution_clock::now();
std::chrono::duration< double, std::milli > f = t - start_;

return f.count();
}
19 changes: 19 additions & 0 deletions M1/clicker.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#ifndef M1_CLICKER_HPP
#define M1_CLICKER_HPP

#include <chrono>

namespace mas {
class Clicker
{
public:
Clicker();

double millisec() const;

private:
std::chrono::time_point< std::chrono::high_resolution_clock > start_;
};
}

#endif
47 changes: 47 additions & 0 deletions M1/geometry_utils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include "geometry_utils.hpp"

#include <algorithm>
#include <functional>
#include <random>
#include <stdexcept>

namespace {
bool isPointInCircle(mas::Point pnt, unsigned radius) noexcept
{
double dx = pnt.x - radius;
double dy = pnt.y - radius;

return dx * dx + dy * dy <= radius * radius;
}
}

int mas::getPointsNumInCircle(unsigned radius, points_c_it_t begin, points_c_it_t end) noexcept
{
auto pntsInPred = std::bind(isPointInCircle, std::placeholders::_1, radius);
int pntsInCircle = std::count_if(begin, end, pntsInPred);

return pntsInCircle;
}

void mas::generatePointsInSquare(unsigned radius, unsigned tries, unsigned seed, std::vector< Point >& points)
{
if (radius == 0 || tries == 0 || !points.empty()) {
throw std::invalid_argument("generatePointsInSquare: invalid arguments");

return;
}

double minX = 0.0, maxX = 2.0 * radius;
double minY = 0.0, maxY = 2.0 * radius;

std::mt19937 gen(seed);
std::uniform_real_distribution< double > distX(minX, maxX);
std::uniform_real_distribution< double > distY(minY, maxY);

for (unsigned long i = 0ul; i != tries; ++i) {
double x = distX(gen);
double y = distY(gen);

points.push_back({x, y});
}
}
19 changes: 19 additions & 0 deletions M1/geometry_utils.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#ifndef M1_GEOMETRY_UTILS_HPP
#define M1_GEOMETRY_UTILS_HPP

#include <vector>

namespace mas {
struct Point
{
double x, y;
};

using points_c_it_t = std::vector< Point >::const_iterator;

int getPointsNumInCircle(unsigned radius, points_c_it_t begin, points_c_it_t end) noexcept;
void generatePointsInSquare(unsigned radius, unsigned tries, unsigned seed, std::vector< Point >& points);

}

#endif
106 changes: 106 additions & 0 deletions M1/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#include <numeric>
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <thread>

#include "clicker.hpp"
#include "geometry_utils.hpp"

namespace {
using seg_it_t = std::vector< double >::iterator;

void getPointsNumInCircleSegment(unsigned radius, mas::points_c_it_t begin, mas::points_c_it_t end, seg_it_t result)
{
*result = mas::getPointsNumInCircle(radius, begin, end);
}
}

int main(int argc, char* argv[])
{
if (argc < 2 || argc > 3) {
std::cerr << "Invalid command line parameters number\n";

return 1;
}
if (std::strtol(argv[1], nullptr, 10) == 0 || argv[1][0] == '-') {
std::cerr << "Invalid tries value\n";

return 1;
}
if (argc == 3 && (std::strtol(argv[2], nullptr, 10) == 0 || argv[2][0] == '-')) {
std::cerr << "Invalid seeed value\n";

return 1;
}

using namespace mas;

int tries = std::strtol(argv[1], nullptr, 10);
int seed = argc == 3 ? std::strtol(argv[2], nullptr, 10) : 0;
int radius = 0;
int threadNum = 0;

while ((std::cin >> radius >> threadNum) && !std::cin.eof()) {
if (radius <= 0 || threadNum <= 0) {
std::cerr << "Radius or thread number is not a positive number\n";

return 2;
}

std::vector< mas::Point > points;
try {
mas::generatePointsInSquare(radius, tries, seed, points);
} catch (const std::exception& e) {
std::cerr << e.what() << '\n';

return 2;
}

double duration_ms = 0.0;
int pointsNumInCircle = 0;
{
try {
std::vector< std::thread > threads;
threads.reserve(threadNum);
std::vector< double > results(threadNum, 0);
mas::Clicker cl;

size_t per_th = points.size() / threadNum;
int i = 0;
auto it = points.cbegin();
for (; i < threadNum - 1; ++i) {
auto end = it + per_th;
threads.emplace_back(getPointsNumInCircleSegment, radius, it, end, results.begin() + i);
it = end;
}
getPointsNumInCircleSegment(radius, it, it + per_th + points.size() % threadNum, results.begin() + i);
for (auto&& thread: threads) {
thread.join();
}

pointsNumInCircle = std::accumulate(results.cbegin(), results.cend(), 0);
duration_ms = cl.millisec();
} catch (std::bad_alloc& e) {
std::cerr << e.what() << '\n';

return 2;
}
}

std::cout << std::fixed << std::setprecision(3);
std::cout << duration_ms << ' ';

double circleArea =
(4.0 * radius * radius) * (static_cast< double >(pointsNumInCircle) / static_cast< double >(points.size()));
std::cout << circleArea << '\n';
}

if (!std::cin.eof()) {
std::cerr << "Invalid input\n";

return 2;
}
}