diff options
| author | Thomas Schmucker <ts@its1.de> | 2024-12-23 12:02:40 +0100 |
|---|---|---|
| committer | Thomas Schmucker <ts@its1.de> | 2024-12-23 12:02:40 +0100 |
| commit | e87bceffc3a19c0dd8acbcbc1b1195c60797ea5f (patch) | |
| tree | 197ca43081ed6faaea6ddfcf8cdb097d20665a4a | |
| parent | 12ba4504a7bbf3449552e37e8f28920e95b890c0 (diff) | |
| download | advent-of-code-e87bceffc3a19c0dd8acbcbc1b1195c60797ea5f.tar.gz advent-of-code-e87bceffc3a19c0dd8acbcbc1b1195c60797ea5f.tar.bz2 advent-of-code-e87bceffc3a19c0dd8acbcbc1b1195c60797ea5f.zip | |
aoc 2024, day 23, part 2
| -rw-r--r-- | 2024/src/day23.cpp | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/2024/src/day23.cpp b/2024/src/day23.cpp index 45d6d28..36f40e6 100644 --- a/2024/src/day23.cpp +++ b/2024/src/day23.cpp | |||
| @@ -20,6 +20,23 @@ split(const string& line, char sep = ' ') | |||
| 20 | return parts; | 20 | return parts; |
| 21 | } | 21 | } |
| 22 | 22 | ||
| 23 | template<typename Container> | ||
| 24 | string | ||
| 25 | join(const Container& container, const string& delimiter) | ||
| 26 | { | ||
| 27 | ostringstream oss; | ||
| 28 | auto it = container.begin(); | ||
| 29 | if ( it != container.end() ) { | ||
| 30 | oss << *it; | ||
| 31 | ++it; | ||
| 32 | } | ||
| 33 | while ( it != container.end() ) { | ||
| 34 | oss << delimiter << *it; | ||
| 35 | ++it; | ||
| 36 | } | ||
| 37 | return oss.str(); | ||
| 38 | } | ||
| 39 | |||
| 23 | map<string, set<string>> | 40 | map<string, set<string>> |
| 24 | read_file(string_view filename) | 41 | read_file(string_view filename) |
| 25 | { | 42 | { |
| @@ -57,9 +74,82 @@ part1(const map<string, set<string>>& nodes) | |||
| 57 | cout << connected.size() << endl; | 74 | cout << connected.size() << endl; |
| 58 | } | 75 | } |
| 59 | 76 | ||
| 77 | void | ||
| 78 | bronKerbosch(set<string> R, set<string> P, set<string> X, const map<string, set<string>>& graph, set<set<string>>& maxCliques) | ||
| 79 | { | ||
| 80 | if ( P.empty() && X.empty() ) { | ||
| 81 | // Found a maximal clique | ||
| 82 | maxCliques.insert(R); | ||
| 83 | return; | ||
| 84 | } | ||
| 85 | |||
| 86 | // Choose a pivot (heuristic: choose a vertex with maximum connections in P union X) | ||
| 87 | string pivot; | ||
| 88 | set<string> unionPX; | ||
| 89 | set_union(P.begin(), P.end(), X.begin(), X.end(), inserter(unionPX, unionPX.begin())); | ||
| 90 | |||
| 91 | if ( !unionPX.empty() ) { | ||
| 92 | pivot = *unionPX.begin(); // Choose the first vertex as pivot (simple heuristic) | ||
| 93 | } | ||
| 94 | |||
| 95 | set<string> candidates; | ||
| 96 | set_difference(P.begin(), P.end(), graph.at(pivot).begin(), graph.at(pivot).end(), inserter(candidates, candidates.begin())); | ||
| 97 | |||
| 98 | for ( const string& candidate: candidates ) { | ||
| 99 | set<string> newR = R; | ||
| 100 | newR.insert(candidate); | ||
| 101 | |||
| 102 | set<string> newP; | ||
| 103 | set<string> newX; | ||
| 104 | for ( const string& neighbor: graph.at(candidate) ) { | ||
| 105 | if ( P.find(neighbor) != P.end() ) { | ||
| 106 | newP.insert(neighbor); | ||
| 107 | } | ||
| 108 | if ( X.find(neighbor) != X.end() ) { | ||
| 109 | newX.insert(neighbor); | ||
| 110 | } | ||
| 111 | } | ||
| 112 | |||
| 113 | bronKerbosch(newR, newP, newX, graph, maxCliques); | ||
| 114 | |||
| 115 | P.erase(candidate); | ||
| 116 | X.insert(candidate); | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | set<string> | ||
| 121 | findLargestSet(const set<set<string>>& sets) | ||
| 122 | { | ||
| 123 | set<string> largest; | ||
| 124 | for ( const auto& sub: sets ) { | ||
| 125 | if ( sub.size() > largest.size() ) { | ||
| 126 | largest = sub; | ||
| 127 | } | ||
| 128 | } | ||
| 129 | return largest; | ||
| 130 | } | ||
| 131 | |||
| 132 | void | ||
| 133 | part2(const map<string, set<string>>& nodes) | ||
| 134 | { | ||
| 135 | set<string> R; // Initially empty | ||
| 136 | set<string> P; // All vertices are potential candidates | ||
| 137 | set<string> X; // Initially empty | ||
| 138 | |||
| 139 | for ( const auto& [vertex, _]: nodes ) { | ||
| 140 | P.insert(vertex); | ||
| 141 | } | ||
| 142 | |||
| 143 | set<set<string>> max_cliques; | ||
| 144 | bronKerbosch(R, P, X, nodes, max_cliques); | ||
| 145 | |||
| 146 | cout << join(findLargestSet(max_cliques), ",") << endl; | ||
| 147 | } | ||
| 148 | |||
| 60 | int | 149 | int |
| 61 | main() | 150 | main() |
| 62 | { | 151 | { |
| 63 | auto data = read_file("data/day23.txt"); | 152 | auto data = read_file("data/day23.txt"); |
| 64 | part1(data); | 153 | part1(data); |
| 154 | part2(data); | ||
| 65 | } | 155 | } |
