Files
AdventOfCode2025/Day8/Question1/main.cpp
2025-12-10 03:13:16 +02:00

155 lines
4.6 KiB
C++

#include <algorithm>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <fstream>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <set>
#include <string>
#include <utility>
#include <vector>
constexpr std::size_t STEP_COUNT = 1000;
constexpr std::size_t TOP_N_COUNT = 3;
// Just for clean code sake, This is doable without structs or classes
typedef double Distance;
struct Junction;
struct Cluster {
std::vector<Junction *> members{};
};
struct Junction {
int64_t x, y, z;
Cluster *parentCluster = nullptr;
};
Distance distanceBetween(Junction first, Junction second) {
return std::sqrt(std::pow(second.x - first.x, 2) +
std::pow(second.y - first.y, 2) +
std::pow(second.z - first.z, 2));
}
int main() {
std::fstream input("input");
std::string currentLine = "";
std::vector<Junction> junctionList{};
std::list<Cluster> clusterList{};
std::multimap<Distance, std::pair<Junction *, Junction *>>
junctionDistanceMap{};
uint64_t junctionListSize = 0;
// I do think we could process text and do the necessary calculations for the
// solution, but once again, code should be preferably legiable
while (std::getline(input, currentLine, '\n')) {
uint16_t positionOfFirstComma, positionOfSecondComma;
positionOfFirstComma = currentLine.find(',');
positionOfSecondComma = currentLine.find(',', positionOfFirstComma + 1);
int64_t x, y, z;
x = std::stoll(currentLine.substr(0, positionOfFirstComma));
y = std::stoll(
currentLine.substr(positionOfFirstComma + 1,
positionOfSecondComma - positionOfFirstComma));
z = std::stoll(currentLine.substr(positionOfSecondComma + 1));
junctionList.push_back({x, y, z});
}
// This is O(n²), ouch. It can be estimated with T_n, So idk maybe O(T_n)
uint64_t count = 0;
junctionListSize = junctionList.size();
for (Junction &junction : junctionList) {
for (uint64_t index = ++count; index < junctionListSize; index++) {
junctionDistanceMap.insert(
{distanceBetween(junction, junctionList[index]),
{&junction, &junctionList[index]}});
}
}
// Ordered by smallest to largest key
count = std::min(STEP_COUNT, junctionDistanceMap.size());
for (const auto &Key : junctionDistanceMap) {
if (count == 0) {
break;
}
count--;
Junction *first = Key.second.first, *second = Key.second.second;
Cluster *firstCluster = first->parentCluster,
*secondCluster = second->parentCluster;
// 4 real possibilities
bool firstHasACluster = firstCluster != nullptr,
secondHasACluster = secondCluster != nullptr;
// Both have clusters, merge clusters
if (firstHasACluster && secondHasACluster) {
// Since both are already connected
if (firstCluster == secondCluster) {
continue;
}
// This bad boy merges the clusters and updates the pointers
firstCluster->members.insert(firstCluster->members.end(),
secondCluster->members.begin(),
secondCluster->members.end());
for (Junction *clusterJunction : secondCluster->members) {
clusterJunction->parentCluster = firstCluster;
}
// Temp fix
secondCluster->members.clear();
second->parentCluster = firstCluster;
continue;
}
// Both don't have clusters, pair up
if (!firstHasACluster && !secondHasACluster) {
clusterList.push_back({{first, second}});
// Directly writing, can't use the variable here
first->parentCluster = &clusterList.back();
second->parentCluster = &clusterList.back();
continue;
}
// Only first doesn't have it, append to second
if (!firstHasACluster) {
first->parentCluster = secondCluster;
secondCluster->members.push_back(first);
continue;
}
// Only second doesn't have it, append to first
if (!secondHasACluster) {
second->parentCluster = firstCluster;
firstCluster->members.push_back(second);
continue;
}
}
// Multiset is preferable
std::multiset<uint64_t, std::greater<uint64_t>> clusterSize{};
for (const Cluster &cluster : clusterList) {
uint64_t size = cluster.members.size();
if (size == 0) {
continue;
}
clusterSize.insert(size);
}
// I'm so tired of this question
auto iterator = clusterSize.begin();
uint64_t password = *iterator;
for (uint16_t index = 0; index < TOP_N_COUNT - 1; index++) {
iterator++;
password *= *iterator;
}
std::cout << password << "\n";
}