Line data Source code
1 : #include "PuzzleImpl.h"
2 :
3 : #include <libassert/assert.hpp>
4 : #include <md5.h>
5 :
6 : #include <algorithm>
7 : #include <array>
8 : #include <charconv>
9 : #include <string_view>
10 : #include <system_error>
11 :
12 : namespace {
13 :
14 : using Hash = std::array<unsigned char, 16>;
15 :
16 2 : size_t findHash(std::string_view const key, auto &&stopCriterion) {
17 2 : std::array<char, 64> buffer{};
18 2 : Hash hash{};
19 2 : std::ranges::copy(key, buffer.begin());
20 :
21 2 : MD5 md5;
22 :
23 4055986 : for (size_t i = 0;; ++i) {
24 4055986 : md5.reset();
25 4055986 : auto const [ptr, ec] = std::to_chars(buffer.begin() + key.size(), buffer.end(), i);
26 4055986 : ASSUME(ec == std::errc{}, "Char conversion failed!", i);
27 4055986 : md5.add(buffer.begin(), std::distance(buffer.begin(), ptr));
28 4055986 : md5.getHash(hash.begin());
29 4055986 : if (stopCriterion(hash))
30 2 : return i;
31 4055986 : }
32 2 : }
33 :
34 : } // namespace
35 :
36 1 : template <> size_t part1<2015, 4>(std::string_view const input) {
37 :
38 117947 : return findHash(input, [](Hash const &hash) {
39 117947 : return hash[0] == 0u && hash[1] == 0u && (hash[2] & 0xF0) == 0u;
40 117947 : });
41 1 : }
42 :
43 1 : template <> size_t part2<2015, 4>(std::string_view const input) {
44 1 : return findHash(input,
45 3938039 : [](Hash const &hash) { return hash[0] == 0u && hash[1] == 0u && hash[2] == 0u; });
46 1 : }
|