aboutsummaryrefslogtreecommitdiff
path: root/2016/src/day14.cpp
blob: a9be56cbc4bee2635a8eb38cc60255586c4f62db (plain)
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Standard C++
#include <array>
#include <iostream>
#include <map>
#include <optional>
#include <string>

// Standard C
#include <cstring>

// System
#include <md5.h>

using namespace std;

namespace {

optional<char>
contains_repeating_chars(string_view str)
{
	for ( size_t i = 2; i < str.size(); ++i ) {
		if ( str[i] == str[i - 1] && str[i] == str[i - 2] ) {
			return str[i];
		}
	}

	return {};
}

string
md5(const string& input)
{
	array<char, MD5_DIGEST_STRING_LENGTH> digest{};
	MD5Data(input.data(), input.size(), digest.data());
	return digest.data();
}

int
solve(const function<string(int)>& get_hash)
{
	int keys = 0;

	for ( int index = 0;; ++index ) {
		auto hash = get_hash(index);

		auto repeat = contains_repeating_chars(hash);

		if ( !repeat.has_value() ) {
			continue;
		}

		const string pattern(5, repeat.value());

		for ( auto index2 = index + 1; index2 != index + 1000; ++index2 ) {
			hash = get_hash(index2);
			if ( hash.find(pattern) != string::npos ) {
				++keys;
				break;
			}
		}

		if ( keys == 64 ) {
			return index;
		}
	}
}

void
part1(const string& input)
{
	map<int, string> cache;

	auto get_hash = [&](int index) {
		if ( cache.contains(index) ) {
			return cache.at(index);
		}

		auto hash = md5(input + to_string(index));

		cache.emplace(index, hash);

		return hash;
	};

	cout << solve(get_hash) << '\n';
}

void
part2(const string& input)
{
	map<int, string> cache;

	auto get_hash = [&](int index) {
		if ( cache.contains(index) ) {
			return cache.at(index);
		}

		auto hash = input + to_string(index);

		for ( int i = 0; i != 2017; ++i ) {
			hash = md5(hash);
		}

		cache.emplace(index, hash);

		return hash;
	};

	cout << solve(get_hash) << '\n';
}

} // namespace

int
main()
{
	// part1("abc");
	// part2("abc");
	part1("qzyelonm");
	part2("qzyelonm");
}