aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--2016/src/day13.cpp127
1 files changed, 127 insertions, 0 deletions
diff --git a/2016/src/day13.cpp b/2016/src/day13.cpp
new file mode 100644
index 0000000..107bc16
--- /dev/null
+++ b/2016/src/day13.cpp
@@ -0,0 +1,127 @@
1#include <bit>
2#include <iostream>
3#include <queue>
4#include <set>
5
6using namespace std;
7
8namespace {
9
10using pos_type = tuple<long, long>;
11
12bool
13is_wall(long x, long y, long number)
14{
15 auto result = (x * x) + (3 * x) + (2 * x * y) + y + (y * y);
16 result += number;
17 auto num = popcount(static_cast<unsigned long>(result));
18
19 return (num % 2) != 0;
20}
21
22int
23part1(long initial_value, pos_type dest)
24{
25 pos_type start_pos = { 1, 1 };
26
27 set<pos_type> seen;
28 queue<tuple<pos_type, int>> queue; // pos, #steps
29
30 seen.emplace(start_pos);
31 queue.emplace(start_pos, 0);
32
33 while ( !queue.empty() ) {
34 auto [pos, steps] = queue.front();
35 queue.pop();
36
37 if ( pos == dest ) {
38 return steps;
39 }
40
41 static const pos_type dirs[] = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } };
42
43 for ( const auto [dx, dy]: dirs ) {
44 auto [x, y] = pos;
45 x += dx;
46 y += dy;
47
48 if ( x < 0 || y < 0 ) {
49 continue;
50 }
51
52 if ( seen.contains({ x, y }) ) {
53 continue;
54 }
55
56 if ( !is_wall(x, y, initial_value) ) {
57 seen.emplace(x, y);
58 queue.emplace(pos_type{ x, y }, steps + 1);
59 }
60 }
61 }
62 return -1; // Error
63}
64
65int
66part2(long initial_value, int max_steps)
67{
68 pos_type start_pos = { 1, 1 };
69
70 int count = 0;
71
72 set<pos_type> seen;
73 queue<tuple<pos_type, int>> queue; // pos, #steps
74
75 seen.emplace(start_pos);
76 queue.emplace(start_pos, 0);
77
78 while ( !queue.empty() ) {
79 auto [pos, steps] = queue.front();
80 queue.pop();
81
82 if ( steps > max_steps ) {
83 continue;
84 }
85
86 ++count;
87
88 static const pos_type dirs[] = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } };
89
90 for ( const auto [dx, dy]: dirs ) {
91 auto [x, y] = pos;
92 x += dx;
93 y += dy;
94
95 if ( x < 0 || y < 0 ) {
96 continue;
97 }
98
99 if ( seen.contains({ x, y }) ) {
100 continue;
101 }
102
103 if ( !is_wall(x, y, initial_value) ) {
104 seen.emplace(x, y);
105 queue.emplace(pos_type{ x, y }, steps + 1);
106 }
107 }
108 }
109 return count;
110}
111
112} // namespace
113
114int
115main()
116{
117#if 0
118 static const long number = 10;
119 static const pos_type dest = { 7, 4 };
120#else
121 static const long number = 1352;
122 static const pos_type dest = { 31, 39 };
123#endif
124
125 cout << part1(number, dest) << '\n';
126 cout << part2(number, 50) << '\n';
127}