-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtriples.cpp
executable file
·78 lines (71 loc) · 2.54 KB
/
triples.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// triples.cpp : calculate all non-multiple Pythagorean Triples up to set hypotenuse length (default 2500)
// to compile use: /std:c++latest (Visual Studio 2022)
// -std=c++20 (g++)
// -std=c++20 -stdlib=libc++ (clang++)
#include <iostream>
#include <cstdlib>
#include <vector>
#include <tuple>
#include <numeric>
#include <chrono>
#if defined(__clang__) && (__clang_major__ < 14) // workaround
#include <experimental/coroutine>
namespace std {
using namespace experimental;
}
#else
#include <coroutine>
#endif
using namespace std::literals::chrono_literals;
using SideT = unsigned;
struct CoroCtx {
struct promise_type {
CoroCtx get_return_object() { return {}; }
std::suspend_never initial_suspend() { return {}; }
std::suspend_never final_suspend() noexcept { return {}; }
void unhandled_exception() {}
void return_void() noexcept {}
};
};
struct AwaitCtx {
std::coroutine_handle<> *hp;
constexpr bool await_ready() const noexcept { return false; }
void await_suspend(std::coroutine_handle<> h) { *hp = h; }
constexpr void await_resume() const noexcept {}
};
CoroCtx progress(std::coroutine_handle<> *continuation_out, auto n, auto delay) {
AwaitCtx a{ continuation_out };
auto t0{ std::chrono::high_resolution_clock::now() };
for (;;) {
co_await a;
if (auto t1{ std::chrono::high_resolution_clock::now() }; (t1 - t0) >= delay) {
std::cout << "Found " << n() << " triples...\n";
t0 = t1;
}
}
}
int main(const int argc, const char *argv[]) {
std::vector<std::tuple<SideT,SideT,SideT>> triples;
std::coroutine_handle<> running_total;
progress(&running_total, [&triples]{ return triples.size(); }, 500ms);
SideT max_hypot = (argc == 2) ? atoi(argv[1]) : 2500;
for (SideT c = 2; c != max_hypot; ++c) {
for (SideT b = 2; b != c; ++b) {
SideT a = 2;
while ((a != b) && ((a * a + b * b) < (c * c))) {
++a;
}
if ((a * a + b * b) == (c * c)) {
if (std::gcd(a, b) == 1) {
triples.push_back({ a, b, c });
running_total();
}
}
}
}
std::cout << "Finished with " << triples.size() << " triples:\n";
for (const auto& t : triples) {
std::cout << "( " << std::get<0>(t) << ' ' << std::get<1>(t) << ' ' << std::get<2>(t) << " ) ";
}
std::cout << '\n';
}