From 098e5fe232b034a6fa97b2b9f6493e7436ce2346 Mon Sep 17 00:00:00 2001 From: Leon Vatthauer Date: Thu, 12 Dec 2024 01:20:00 +0100 Subject: [PATCH] solve day11 --- 11/example | 1 + 11/hash.h | 53 +++++++++++++++++++ 11/input | 1 + 11/main.cc | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 208 insertions(+) create mode 100644 11/example create mode 100644 11/hash.h create mode 100644 11/input create mode 100644 11/main.cc diff --git a/11/example b/11/example new file mode 100644 index 0000000..9b26c84 --- /dev/null +++ b/11/example @@ -0,0 +1 @@ +125 17 diff --git a/11/hash.h b/11/hash.h new file mode 100644 index 0000000..128b589 --- /dev/null +++ b/11/hash.h @@ -0,0 +1,53 @@ +#include +// function has to live in the std namespace +// so that it is picked up by argument-dependent name lookup (ADL). +namespace std{ + namespace + { + + // Code from boost + // Reciprocal of the golden ratio helps spread entropy + // and handles duplicates. + // See Mike Seymour in magic-numbers-in-boosthash-combine: + // https://stackoverflow.com/questions/4948780 + + template + inline void hash_combine(std::size_t& seed, T const& v) + { + seed ^= hash()(v) + 0x9e3779b9 + (seed<<6) + (seed>>2); + } + + // Recursive template code derived from Matthieu M. + template ::value - 1> + struct HashValueImpl + { + static void apply(size_t& seed, Tuple const& tuple) + { + HashValueImpl::apply(seed, tuple); + hash_combine(seed, get(tuple)); + } + }; + + template + struct HashValueImpl + { + static void apply(size_t& seed, Tuple const& tuple) + { + hash_combine(seed, get<0>(tuple)); + } + }; + } + + template + struct hash> + { + size_t + operator()(std::tuple const& tt) const + { + size_t seed = 0; + HashValueImpl >::apply(seed, tt); + return seed; + } + + }; +} \ No newline at end of file diff --git a/11/input b/11/input new file mode 100644 index 0000000..d6eb041 --- /dev/null +++ b/11/input @@ -0,0 +1 @@ +4 4841539 66 5279 49207 134 609568 0 diff --git a/11/main.cc b/11/main.cc new file mode 100644 index 0000000..1df541d --- /dev/null +++ b/11/main.cc @@ -0,0 +1,153 @@ +#include +#include +#include +#include +#include +#include "hash.h" + +using namespace std; + +struct Node { + unsigned long long value; + Node *next; +}; + +Node *parseList(const char *path) { + ifstream input(path); + string line; + + getline(input, line); + stringstream ss; + ss << line; + unsigned long long a; + + // head + ss >> a; + Node *curr = new Node(); + curr->value = a; + Node *head = curr; + + // rest + while (ss >> a) { + Node *prev = curr; + curr = new Node(); + curr->value = a; + prev->next = curr; + } + + return head; +} + +void blink(Node *head) { + Node *curr = head; + while (curr != nullptr) { + // get next already, to skip newly appended elements + Node *next = curr->next; + + // do blink + string num = to_string(curr->value); + if (curr->value == 0) { + curr->value = 1; + } else if (num.size() % 2 == 0) { + string num1 = num.substr(0, num.size() / 2); + string num2 = num.substr(num.size() / 2, num.size() / 2); + + Node *new_node = new Node(); + curr->value = stol(num1); + curr->next = new_node; + new_node->value = stol(num2); + new_node->next = next; + } else { + curr->value = curr->value * 2024; + } + curr = next; + } +} + +int length(Node *head) { + int ret = 0; + Node *curr = head; + while (curr != nullptr) { + ret++; + curr = curr->next; + } + return ret; +} + +void printList(Node *head) { + Node *curr = head; + + while (curr != nullptr) { + cout << curr->value << " "; + curr = curr->next; + } + cout << endl; +} + +// highly inefficient +int part1(const char *path) { + Node *head = parseList(path); + for (int i = 0; i < 25; i++) { + blink(head); + } + + return length(head); +} + +unordered_map, long> memo; + +unsigned long long doBlinks(unsigned long long value, int iterations) { + if (iterations == 0) { + return 1; + } + + // cache hit + if (memo.count(make_tuple(value, iterations))) { + // return memo.at(make_tuple(value, iterations)); + return memo[make_tuple(value, iterations)]; + } + + // cache miss -> do blink + if (value == 0) { + long ret = doBlinks(1 , iterations - 1); + memo[make_tuple(value, iterations)] = ret; + // memo.insert(make_pair(make_tuple(value, iterations), ret)); + return ret; + } + + unsigned long long ret = 0; + string num = to_string(value); + if (num.size() % 2 == 0) { + string num1 = num.substr(0, num.size() / 2); + string num2 = num.substr(num.size() / 2, num.size() / 2); + ret += doBlinks(stol(num1), iterations - 1); + ret += doBlinks(stol(num2), iterations - 1); + memo[make_tuple(value, iterations)] = ret; + return ret; + } else { + long ret = doBlinks(value * 2024, iterations - 1); + memo[make_tuple(value, iterations)] = ret; + return ret; + } +} + +unsigned long long part2(const char *path) { + Node *head = parseList(path); + + unsigned long long sum = 0; + + while (head != nullptr) { + sum += doBlinks(head->value, 75); + head = head->next; + } + + return sum; +} + +int main(int argc, char *argv[]) { + cout << "example1: " << part1("example") << endl; + cout << "input1: " << part1("input") << endl; + cout << "example2: " << part2("example") << endl; + cout << "input2: " << part2("input") << endl; + return 0;; +} \ No newline at end of file