aboutsummaryrefslogtreecommitdiff
path: root/src/day25.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/day25.cpp')
-rw-r--r--src/day25.cpp159
1 files changed, 35 insertions, 124 deletions
diff --git a/src/day25.cpp b/src/day25.cpp
index b566725..aaad9e9 100644
--- a/src/day25.cpp
+++ b/src/day25.cpp
@@ -1,11 +1,10 @@
1#include <algorithm> 1#include <algorithm>
2#include <cstdlib> 2#include <array>
3#include <fstream> 3#include <fstream>
4#include <iostream> 4#include <iostream>
5#include <iterator>
6#include <list>
7#include <map> 5#include <map>
8#include <queue> 6#include <queue>
7#include <random>
9#include <set> 8#include <set>
10#include <sstream> 9#include <sstream>
11#include <string> 10#include <string>
@@ -47,48 +46,7 @@ read_file(string_view filename)
47} 46}
48 47
49bool 48bool
50bfs(const graph_type& graph, const string& source, const string& dest, map<string, string>& parents) // NOLINT 49bfs(graph_type graph, const string& source, const string& dest, function<void(const string&, const string&)> visit) // NOLINT
51{
52 set<string> visited;
53
54 parents.clear();
55
56 queue<string> queue;
57 queue.emplace(source);
58
59 while ( !queue.empty() ) {
60 auto candidate = queue.front();
61 queue.pop();
62
63 if ( candidate == dest ) {
64 return true;
65 }
66
67 for ( const auto& neighbour: graph.at(candidate) ) {
68 if ( !visited.contains(neighbour) ) {
69 queue.emplace(neighbour);
70 parents[neighbour] = candidate;
71 visited.emplace(neighbour);
72 }
73 }
74 }
75
76 return false;
77}
78
79void
80dfs(const graph_type& graph, const string& source, set<string>& visited) // NOLINT
81{
82 visited.emplace(source);
83 for ( const auto& node: graph.at(source) ) {
84 if ( !visited.contains(node) ) {
85 dfs(graph, node, visited);
86 }
87 }
88}
89
90bool
91bfs1(graph_type graph, const string& source, const string& dest, function<void(const string&, const string&)> visit) // NOLINT
92{ 50{
93 set<string> visited; 51 set<string> visited;
94 52
@@ -115,115 +73,68 @@ bfs1(graph_type graph, const string& source, const string& dest, function<void(c
115 return false; 73 return false;
116} 74}
117 75
118void 76auto
119print_graph_stats(const graph_type& graph) 77random_node(const graph_type& graph)
120{ 78{
121 size_t nodes = 0; 79 static random_device dev;
122 size_t edges = 0; 80 static mt19937 generator(dev());
123 for ( const auto& link: graph ) { 81
124 nodes++; 82 uniform_int_distribution<graph_type::size_type> distribute(0, graph.size());
125 edges += link.second.size(); 83
126 } 84 auto iter = graph.begin();
127 cout << nodes << ", " << edges / 2 << endl; 85 advance(iter, distribute(generator));
86 return iter->first;
128} 87}
129 88
130void 89void
131part1(graph_type graph) 90part1(graph_type graph)
132{ 91{
133 srand(unsigned(time(nullptr))); 92 map<tuple<string, string>, int> frequencies;
134
135 vector<string> nodes(graph.size());
136 for ( const auto& foo: graph ) {
137 nodes.emplace_back(foo.first);
138 }
139
140 map<tuple<string, string>, int> counter;
141 for ( size_t idx = 0; idx != 2; ++idx ) { 93 for ( size_t idx = 0; idx != 2; ++idx ) {
142 for ( const auto& second: graph ) { 94 for ( const auto& second: graph ) {
143 bfs1(graph, nodes[size_t(rand()) % nodes.size()], second.first, [&](const string& candidate, const string& neighbour) { 95 bfs(graph, random_node(graph), second.first, [&](const string& candidate, const string& neighbour) {
144 if ( candidate < neighbour ) { 96 if ( candidate < neighbour ) {
145 counter[make_tuple(candidate, neighbour)]++; 97 frequencies[make_tuple(candidate, neighbour)]++;
146 } 98 }
147 else { 99 else {
148 counter[make_tuple(neighbour, candidate)]++; 100 frequencies[make_tuple(neighbour, candidate)]++;
149 } 101 }
150 }); 102 });
151 } 103 }
152 } 104 }
153 105
154 vector<tuple<tuple<string, string>, int>> all_links{ counter.begin(), counter.end() }; 106 vector<tuple<tuple<string, string>, int>> sorted_frequencies{ frequencies.begin(), frequencies.end() };
155 107
156 sort(all_links.begin(), all_links.end(), [](const auto& lhs, const auto& rhs) { 108 sort(sorted_frequencies.begin(), sorted_frequencies.end(), [](const auto& lhs, const auto& rhs) {
157 return get<1>(lhs) > get<1>(rhs); 109 return get<1>(lhs) > get<1>(rhs);
158 }); 110 });
159 111
160 for ( size_t i = 0; i != 3; ++i ) { 112 sorted_frequencies.erase(sorted_frequencies.begin() + 3, sorted_frequencies.end());
161 const auto [links, num] = all_links[i];
162 const auto [lhs, rhs] = links;
163 113
164 graph[lhs].erase(rhs); 114 for ( const auto& link: sorted_frequencies ) {
165 graph[rhs].erase(lhs); 115 const auto [left, right] = get<0>(link);
116
117 graph[left].erase(right);
118 graph[right].erase(left);
166 } 119 }
167 120
168 set<string> reachable; 121 auto reachable = [&graph](const string& start_node) {
169 const auto start_from_a = get<0>(get<0>(all_links[0])); 122 set<string> nodes;
170 bfs1(graph, start_from_a, "--not there--", [&](const string& candidate, const string& neighbour) { 123 bfs(graph, start_node, "", [&nodes](const string& candidate, const string& neighbour) {
171 reachable.insert(candidate); 124 nodes.insert(candidate);
172 reachable.insert(neighbour); 125 nodes.insert(neighbour);
173 }); 126 });
127 return nodes.size();
128 };
174 129
175 set<string> reachable2; 130 const auto [left, right] = get<0>(sorted_frequencies[0]);
176 const auto start_from_b = get<1>(get<0>(all_links[0]));
177 bfs1(graph, start_from_b, "--not there--", [&](const string& candidate, const string& neighbour) {
178 reachable2.insert(candidate);
179 reachable2.insert(neighbour);
180 });
181 131
182 cout << reachable.size() * reachable2.size() << endl; 132 cout << reachable(left) * reachable(right) << endl;
183}
184
185void
186print_graph(const graph_type& graph)
187{
188 for ( const auto& node: graph ) {
189 cout << node.first << ": ";
190 copy(node.second.begin(), node.second.end(), ostream_iterator<string>(cout, ", "));
191 cout << endl;
192 }
193}
194
195graph_type
196get_rgraph(const graph_type& graph)
197{
198 graph_type rgraph;
199 for ( const auto& node: graph ) {
200 for ( const auto& link: node.second ) {
201 rgraph[link].insert(node.first);
202 }
203 }
204 return rgraph;
205} 133}
206 134
207int 135int
208main() 136main()
209{ 137{
210 auto graph = read_file("data/day25.txt"); 138 auto graph = read_file("data/day25.txt");
211
212 // print_graph(graph);
213
214 part1(graph); 139 part1(graph);
215
216 // print_graph(graph);
217 // cout << " ------------ " << endl;
218 // print_graph(get_rgraph(graph));
219 // cout << " ------------ " << endl;
220 // print_graph(get_rgraph(get_rgraph(graph)));
221
222 // map<string, string> parents;
223
224 // if ( bfs(graph, "jqt", "bvb", parents) ) {
225 // for ( const auto& [lhs, rhs]: parents ) {
226 // cout << lhs << ": " << rhs << endl;
227 // }
228 // }
229} 140}