aboutsummaryrefslogtreecommitdiff
path: root/2016/src/day20.cpp
diff options
context:
space:
mode:
Diffstat (limited to '2016/src/day20.cpp')
-rw-r--r--2016/src/day20.cpp128
1 files changed, 128 insertions, 0 deletions
diff --git a/2016/src/day20.cpp b/2016/src/day20.cpp
new file mode 100644
index 0000000..49a9ec1
--- /dev/null
+++ b/2016/src/day20.cpp
@@ -0,0 +1,128 @@
1#include <algorithm>
2#include <filesystem>
3#include <fstream>
4#include <iostream>
5#include <sstream>
6#include <string>
7#include <vector>
8
9using namespace std;
10
11namespace {
12
13struct Range {
14 long long start;
15 long long end;
16};
17
18vector<Range>
19readFile(const filesystem::path& filename)
20{
21 ifstream file{ filename };
22 vector<Range> ranges;
23
24 for ( string line; getline(file, line); ) {
25 stringstream stream{ line };
26 char dash{};
27 long long start{};
28 long long end{};
29
30 stream >> start >> dash >> end;
31
32 ranges.emplace_back(start, end);
33 }
34
35 return ranges;
36}
37
38void
39sortRanges(vector<Range>& ranges)
40{
41 ranges::sort(ranges, [](const auto& lhs, const auto& rhs) {
42 if ( lhs.start != rhs.start ) {
43 return lhs.start < rhs.start;
44 }
45 return lhs.end < rhs.end;
46 });
47}
48
49void
50mergeRanges(vector<Range>& ranges)
51{
52 if ( ranges.empty() ) {
53 return;
54 }
55
56 vector<Range> mergedRanges;
57
58 auto current = ranges[0];
59 for ( size_t i = 1; i != ranges.size(); ++i ) {
60 if ( ranges[i].start <= current.end + 1 ) {
61 current.end = max(current.end, ranges[i].end);
62 }
63 else {
64 mergedRanges.emplace_back(current);
65 current = ranges[i];
66 }
67 }
68 mergedRanges.emplace_back(current);
69
70 ranges.swap(mergedRanges);
71}
72
73long long
74findLowestAllowedIP(const vector<Range>& ranges)
75{
76 if ( ranges.empty() || ranges[0].start > 0 ) {
77 return 0;
78 }
79 return ranges[0].end + 1;
80}
81
82long long
83countAllowedIPs(const vector<Range>& ranges, long long max_ip)
84{
85 long long allowed_count = 0;
86
87 for ( size_t i = 0; i < ranges.size() - 1; ++i ) {
88 allowed_count += ranges[i + 1].start - ranges[i].end - 1;
89 }
90
91 if ( !ranges.empty() && ranges.back().end < max_ip ) {
92 allowed_count += max_ip - ranges.back().end;
93 }
94
95 if ( ranges.empty() ) {
96 allowed_count = max_ip + 1;
97 }
98
99 return allowed_count;
100}
101
102void
103part1(vector<Range> ranges)
104{
105 sortRanges(ranges);
106 mergeRanges(ranges);
107
108 cout << findLowestAllowedIP(ranges) << '\n';
109}
110
111void
112part2(vector<Range> ranges, long long max_ip = 4294967295)
113{
114 sortRanges(ranges);
115 mergeRanges(ranges);
116
117 cout << countAllowedIPs(ranges, max_ip) << '\n';
118}
119
120} // namespace
121
122int
123main()
124{
125 auto ranges = readFile("data/day20.txt");
126 part1(ranges);
127 part2(ranges);
128}