To get started with C++11/14/17, I decided to write a program that brute forces the problem described in this video (and gives a progress update every few seconds):
Divide the numbers [0, 31] into two sets A and B such that
- \$\sum_A {a} = \sum_B{b}\$
- \$\sum_A {a^2} = \sum_B{b^2}\$
- \$\sum_A {a^3} = \sum_B{b^3}\$
- \$\sum_A {a^4} = \sum_B{b^4}\$
How can I make this code more C++14-ish? My goal is not to make the code more mathematically clever, or necessarily faster. I mainly wanted to use a reasonable to high number of modern C++ standard features to brute-force-solve this problem.
#include <vector>
#include <iostream>
#include <numeric>
#include <chrono>
#include <iomanip>
#include <cstdlib>
int main() {
uint32_t split {0};
uint32_t print_mask { 2048 };
auto lastPrintTime = std::chrono::system_clock::now();
auto const SLOWER_THRESHOLD = std::chrono::seconds(5) ;
auto const FASTER_THRESHOLD = std::chrono::seconds(10) ;
while (split < std::numeric_limits<uint32_t>::max()) {
if (split % print_mask == 0) {
double progress_percentage { (split/(double)std::numeric_limits<uint32_t>::max()) * 100.0 };
std::cout << "Currently checking " << std::setw(20) << std::setfill(' ') << split << ", " << std::fixed << progress_percentage << '%' << std::endl;
auto now = std::chrono::system_clock::now();
auto diff = std::chrono::duration_cast<std::chrono::seconds>(now - lastPrintTime);
lastPrintTime = now;
if (diff < SLOWER_THRESHOLD) print_mask *= 2;
if (diff > FASTER_THRESHOLD && print_mask > 10) print_mask /= 2;
}
std::vector<int> va;
std::vector<int> vb;
uint32_t mask {1};
for (int i=0; i<32; i++) {
((mask & split) != 0 ? va : vb).push_back(i);
mask = mask << 1;
}
int sum_a;
int sum_b;
sum_a = std::accumulate(va.begin(), va.end(), 0, [](auto x, auto y){return x + y;});
sum_b = std::accumulate(vb.begin(), vb.end(), 0, [](auto x, auto y){return x + y;});
if (sum_a != sum_b) goto next;
sum_a = std::accumulate(va.begin(), va.end(), 0, [](auto x, auto y){return x + y*y;});
sum_b = std::accumulate(vb.begin(), vb.end(), 0, [](auto x, auto y){return x + y*y;});
if (sum_a != sum_b) goto next;
sum_a = std::accumulate(va.begin(), va.end(), 0, [](auto x, auto y){return x + y*y*y;});
sum_b = std::accumulate(vb.begin(), vb.end(), 0, [](auto x, auto y){return x + y*y*y;});
if (sum_a != sum_b) goto next;
sum_a = std::accumulate(va.begin(), va.end(), 0, [](auto x, auto y){return x + y*y*y*y;});
sum_b = std::accumulate(vb.begin(), vb.end(), 0, [](auto x, auto y){return x + y*y*y*y;});
if (sum_a != sum_b) goto next;
std::cout << "A = " << sum_a << " = [";
for (auto v: va) {
std::cout << v << ", ";
}
std::cout << ']' << std::endl << "B = " << sum_b << " = [";
for (auto v: vb) {
std::cout << v << ", ";
}
std::cout << ']' << std::endl;
break;
next:
split++;
}
puts("Win");
return EXIT_SUCCESS;
}
I am especially unhappy with the way I print the vectors. I have seen some code examples about ostream_iterators
, but these looked even worse to me.
goto next;
Convertwhile
tofor(;<STUFF>;++split)
Then usecontinue
. \$\endgroup\$std::ostream& operator<<(std::ostream&, TypeToPrint const&)
\$\endgroup\$