18
This commit is contained in:
parent
ac58465ce2
commit
0f2ef15f94
22
18/CMakeLists.txt
Normal file
22
18/CMakeLists.txt
Normal 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
100
18/input
Normal 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
299
18/main.cpp
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user