This commit is contained in:
zv0n 2021-12-18 11:32:27 +01:00
parent ac58465ce2
commit 0f2ef15f94
3 changed files with 421 additions and 0 deletions

22
18/CMakeLists.txt Normal file
View File

@ -0,0 +1,22 @@
cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
enable_language(CXX)
project(AoC18)
if(APPLE)
include_directories(/usr/local/include)
link_directories(/usr/local/lib)
endif()
if(WIN32)
add_executable(${CMAKE_PROJECT_NAME} WIN32)
else()
add_executable(${CMAKE_PROJECT_NAME})
endif()
target_sources(${CMAKE_PROJECT_NAME}
PRIVATE main.cpp
)

100
18/input Normal file
View File

@ -0,0 +1,100 @@
[1,[[9,[5,8]],[[2,0],0]]]
[[[6,4],6],[[1,[7,3]],[[0,1],[4,9]]]]
[[[7,3],[8,6]],[[4,[1,2]],7]]
[[[2,[4,5]],[[7,1],2]],1]
[[[[4,4],[4,6]],9],[[4,2],6]]
[[[9,8],[[4,0],0]],[[2,[5,1]],[[9,6],[9,2]]]]
[[[6,[9,0]],0],[6,[[5,8],3]]]
[[[[7,3],[5,4]],0],[3,[[0,6],3]]]
[5,[[0,0],[[4,8],[8,6]]]]
[[[3,[9,2]],9],[5,[0,6]]]
[[[[6,3],[3,2]],[5,9]],2]
[[[0,4],7],[8,[8,[4,2]]]]
[[[8,[8,0]],9],[[1,[6,3]],[4,2]]]
[[[[5,4],[1,5]],[1,3]],[[[9,0],[7,4]],9]]
[[[5,[4,2]],[[9,2],3]],[[[6,2],[6,8]],[[2,4],[9,4]]]]
[[9,6],[0,[[1,1],9]]]
[[[8,[5,9]],[2,9]],[0,[[7,6],[7,6]]]]
[[[5,[4,8]],[[7,7],[2,2]]],[[[2,6],[5,7]],[0,[6,2]]]]
[[[[9,3],5],3],[[[1,5],2],[3,3]]]
[[[2,[1,1]],[[5,8],[7,1]]],[[9,7],5]]
[[9,9],3]
[[[5,[6,1]],9],[1,[9,3]]]
[[[[1,2],7],[[6,8],[4,1]]],[[2,3],[6,3]]]
[[[[9,3],[7,9]],2],[[9,[3,4]],[[2,6],[7,0]]]]
[[8,[4,9]],[[2,[5,6]],6]]
[3,[[[9,7],7],[[2,6],4]]]
[[[[3,4],[0,8]],[[6,4],[2,6]]],[[[1,4],[5,4]],8]]
[8,[[0,[5,5]],[[1,2],1]]]
[[[5,[8,1]],[[1,8],[4,0]]],[8,8]]
[[[9,5],3],[[7,9],[1,6]]]
[[[[1,1],1],[[2,0],[2,5]]],5]
[[3,[[5,4],[7,4]]],[[4,4],[1,9]]]
[[0,[[7,4],[7,2]]],[[8,0],[5,9]]]
[0,[[[1,2],4],[[1,0],[6,4]]]]
[[[[6,6],[9,8]],3],[[[5,5],[1,6]],[8,[5,3]]]]
[[7,[[5,6],0]],[5,[[9,2],4]]]
[[[4,[4,5]],[7,[4,5]]],[[[9,8],8],[[8,2],[3,0]]]]
[[[8,[0,5]],[[0,4],[8,9]]],[8,[4,6]]]
[[[4,[9,7]],[[7,4],[7,1]]],[[[8,4],0],[[6,9],[9,0]]]]
[[3,6],[[3,[4,6]],[[6,0],0]]]
[3,[1,[[4,0],1]]]
[[[9,9],[0,[6,3]]],[3,2]]
[7,4]
[2,6]
[[[3,[7,8]],7],[[0,[2,5]],[1,1]]]
[0,5]
[8,[8,[[2,4],5]]]
[[[[8,2],1],[9,0]],[[[0,8],[3,0]],9]]
[[[[7,0],1],[[0,1],[6,7]]],[[[3,1],[8,3]],7]]
[8,0]
[[[7,[1,3]],[7,[7,2]]],[[9,0],4]]
[[[[0,3],5],[[1,0],8]],[[0,2],9]]
[[5,[[7,6],[7,2]]],5]
[[[[2,8],[5,4]],[1,6]],[[8,8],[[5,2],4]]]
[[[[1,5],[1,8]],1],[[6,[2,4]],5]]
[[[[9,7],[6,3]],2],[[3,[4,4]],[3,4]]]
[[[9,2],[2,9]],[[[0,7],[0,8]],[[0,2],[6,7]]]]
[[[[1,1],3],[[1,4],[8,9]]],[[8,[8,6]],[7,7]]]
[5,[[1,[8,8]],[6,3]]]
[[[1,4],3],7]
[[[[0,1],[2,0]],2],[[8,8],7]]
[[[[2,8],[4,4]],[[5,6],8]],[[[5,3],1],7]]
[[9,[0,[8,3]]],[5,6]]
[[[0,[8,9]],[6,[8,1]]],[[[2,3],8],[[4,0],8]]]
[[2,[5,4]],[[7,4],[[5,0],3]]]
[[[[1,1],2],[[3,0],[7,7]]],[[1,[3,8]],2]]
[[[1,4],[6,[2,4]]],[[5,5],0]]
[[[[4,4],8],[[4,3],[3,5]]],[[7,1],2]]
[[[4,[0,8]],9],[[[6,9],2],8]]
[[[[0,0],1],[1,1]],[2,[[0,0],[7,7]]]]
[[2,[5,5]],9]
[[[[5,8],[7,7]],[[9,8],5]],[[3,5],[8,8]]]
[[5,[3,[3,9]]],[3,[9,8]]]
[[8,[4,6]],[[5,0],[9,2]]]
[[[3,[1,8]],[4,5]],[[0,[5,9]],6]]
[9,[[1,1],0]]
[[[[6,1],[9,2]],4],[5,3]]
[[[[3,0],[0,5]],[1,[5,2]]],[[[2,0],[0,2]],[[6,4],4]]]
[[[[1,1],[4,6]],[[3,8],[3,2]]],[[[4,3],7],[2,[7,8]]]]
[4,[[1,5],5]]
[8,[[1,1],0]]
[[[[8,4],[9,9]],[3,[6,6]]],[[[7,9],[9,7]],7]]
[[2,5],[8,[3,8]]]
[[[6,1],[7,[3,5]]],9]
[[1,[[3,6],[1,0]]],[[[2,8],8],[4,[2,7]]]]
[[[3,[6,9]],[[9,6],[0,8]]],[[5,[6,4]],[[3,4],1]]]
[[[[7,7],1],[5,[2,5]]],[[3,7],[[4,7],3]]]
[[4,[3,[7,2]]],[[[8,8],[5,8]],8]]
[[3,[[9,9],6]],6]
[[6,7],[2,9]]
[[[9,7],[1,[4,0]]],[[[3,4],0],[1,2]]]
[9,[[8,[8,4]],3]]
[[[4,[4,1]],[[4,7],[2,3]]],[8,[5,[1,5]]]]
[7,[2,[4,1]]]
[[[[1,5],7],[5,9]],8]
[[[[1,5],[0,4]],8],[[[7,0],6],[8,3]]]
[[[7,[3,5]],0],[8,[9,[5,6]]]]
[[1,[[5,1],5]],[[5,1],[9,[3,0]]]]
[3,[[[8,5],[7,5]],[9,4]]]
[[[3,3],[2,[5,9]]],7]

299
18/main.cpp Normal file
View File

@ -0,0 +1,299 @@
#include <algorithm>
#include <deque>
#include <fstream>
#include <iostream>
#include <memory>
#include <sstream>
#include <unordered_map>
#include <unordered_set>
#include <vector>
class SnailFishNumber {
public:
SnailFishNumber() {}
void setParent(std::shared_ptr<SnailFishNumber> &parent) {
_parent = parent;
}
void setValue(uint64_t value) {
_simple = true;
_simple_value = value;
}
void setLeft(std::shared_ptr<SnailFishNumber> &left) {
_simple = false;
_left = left;
}
void setRight(std::shared_ptr<SnailFishNumber> &right) {
_simple = false;
_right = right;
}
void printNumber() {
if (_simple) {
std::cout << _simple_value;
} else {
std::cout << "[";
_left->printNumber();
std::cout << ",";
_right->printNumber();
std::cout << "]";
}
}
void addValue(uint64_t val) {
_simple_value += val;
}
uint64_t getValue() {
return _simple_value;
}
void fixNumber() {
// we rely on lazy execution
while (explodeNumber() || splitNumber()) {
}
}
std::shared_ptr<SnailFishNumber> findLeftNeighbour() {
auto child = this;
auto parent = _parent.get();
while (parent != nullptr && parent->isLeftChild(child)) {
child = parent;
parent = parent->getParent().get();
}
if (parent == nullptr) {
return nullptr;
}
auto left_neighbour = parent->getLeftChild();
while (!left_neighbour->isSimple()) {
left_neighbour = left_neighbour->getRightChild();
}
return left_neighbour;
}
std::shared_ptr<SnailFishNumber> findRightNeighbour() {
auto child = this;
auto parent = _parent.get();
while (parent != nullptr && parent->isRightChild(child)) {
child = parent;
parent = parent->getParent().get();
}
if (parent == nullptr) {
return nullptr;
}
auto right_neighbour = parent->getRightChild();
while (!right_neighbour->isSimple()) {
right_neighbour = right_neighbour->getLeftChild();
}
return right_neighbour;
}
std::shared_ptr<SnailFishNumber> getParent() {
return _parent;
}
std::shared_ptr<SnailFishNumber> getLeftChild() {
return _left;
}
std::shared_ptr<SnailFishNumber> getRightChild() {
return _right;
}
bool isSimple() {
return _simple;
}
bool isLeftChild(SnailFishNumber *ptr) {
return ptr == _left.get();
}
bool isRightChild(SnailFishNumber *ptr) {
return ptr == _right.get();
}
uint64_t getMagnitude() {
if (_simple) {
return _simple_value;
}
return 3 * _left->getMagnitude() + 2 * _right->getMagnitude();
}
std::shared_ptr<SnailFishNumber> copySelf() const {
auto res = std::make_shared<SnailFishNumber>();
if (_simple) {
res->setValue(_simple_value);
} else {
auto left_copy = _left->copySelf();
auto right_copy = _right->copySelf();
left_copy->setParent(res);
right_copy->setParent(res);
res->setLeft(left_copy);
res->setRight(right_copy);
}
return res;
}
private:
bool explodeNumber(int depth = 0) {
if (_simple) {
return false;
;
}
if (depth >= 4) {
auto left_neighbour = findLeftNeighbour();
auto right_neighbour = findRightNeighbour();
if (left_neighbour != nullptr) {
left_neighbour->addValue(_left->getValue());
}
if (right_neighbour != nullptr) {
right_neighbour->addValue(_right->getValue());
}
_simple = true;
_simple_value = 0;
_left.reset();
_right.reset();
return true;
}
if (_left->explodeNumber(depth + 1)) {
return true;
}
if (_right->explodeNumber(depth + 1)) {
return true;
}
return false;
}
bool splitNumber() {
if (!_simple) {
if (_left->splitNumber()) {
return true;
}
if (_right->splitNumber()) {
return true;
}
return false;
}
if (_simple_value > 9) {
_simple = false;
_left = std::make_unique<SnailFishNumber>();
_right = std::make_unique<SnailFishNumber>();
_left->setValue(_simple_value / 2);
_right->setValue(_simple_value - _left->getValue());
std::shared_ptr<SnailFishNumber> me{};
if (_parent->isRightChild(this)) {
me = _parent->getRightChild();
} else {
me = _parent->getLeftChild();
}
_left->setParent(me);
_right->setParent(me);
_simple_value = 0;
return true;
}
return false;
}
bool _simple = false;
uint64_t _simple_value{};
std::shared_ptr<SnailFishNumber> _left{ nullptr };
std::shared_ptr<SnailFishNumber> _right{ nullptr };
std::shared_ptr<SnailFishNumber> _parent{ nullptr };
};
std::vector<std::shared_ptr<SnailFishNumber>>
getNumbers(const std::string &file_name) {
std::vector<std::shared_ptr<SnailFishNumber>> numbers{};
std::ifstream file(file_name);
std::string str;
while (std::getline(file, str)) {
auto cur = std::make_shared<SnailFishNumber>();
numbers.push_back(cur);
std::deque<std::shared_ptr<SnailFishNumber>> parents;
for (auto &c : str) {
if (c == '[') {
parents.push_back(cur);
cur = std::make_shared<SnailFishNumber>();
cur->setParent(parents.back());
parents.back()->setLeft(cur);
}
if (c >= '0' && c <= '9') {
cur->setValue(c - '0');
}
if (c == ',') {
cur = std::make_shared<SnailFishNumber>();
cur->setParent(parents.back());
parents.back()->setRight(cur);
}
if (c == ']') {
cur = parents.back();
parents.pop_back();
}
}
if (parents.size() > 1) {
std::cout << "Something's wrong, I can feel it!" << std::endl;
}
}
return numbers;
}
std::shared_ptr<SnailFishNumber>
addNumbers(std::shared_ptr<SnailFishNumber> &a,
std::shared_ptr<SnailFishNumber> &b) {
auto result = std::make_shared<SnailFishNumber>();
result->setLeft(a);
result->setRight(b);
a->setParent(result);
b->setParent(result);
result->fixNumber();
return result;
}
uint64_t part1(const std::vector<std::shared_ptr<SnailFishNumber>> &numbers) {
auto n0 = numbers[0]->copySelf();
auto n1 = numbers[1]->copySelf();
auto res = addNumbers(n0, n1);
for (size_t i = 2; i < numbers.size(); i++) {
auto addition = numbers[i]->copySelf();
res = addNumbers(res, addition);
}
return res->getMagnitude();
}
uint64_t part2(const std::vector<std::shared_ptr<SnailFishNumber>> &numbers) {
uint64_t max_magnitude = 0;
for (const auto &number : numbers) {
for (const auto &number2 : numbers) {
if (number == number2) {
continue;
}
auto n1 = number->copySelf();
auto n2 = number2->copySelf();
auto res = addNumbers(n1, n2);
auto mag = res->getMagnitude();
if (mag > max_magnitude) {
max_magnitude = mag;
}
}
}
return max_magnitude;
}
int main(int argc, char **argv) {
if (argc < 2) {
std::cerr << "You must provide input file!" << std::endl;
return 1;
}
auto numbers = getNumbers(argv[1]);
std::cout << "The magnitude of final result is \033[91;1m" << part1(numbers)
<< "\033[0m." << std::endl;
std::cout
<< "The largest possible magnitude from only 2 numbers is \033[91;1m"
<< part2(numbers) << "\033[0m." << std::endl;
return 0;
}