solve day11

This commit is contained in:
Leon Vatthauer 2024-12-12 01:20:00 +01:00
parent f51ad60b73
commit 098e5fe232
Signed by: leonv
SSH key fingerprint: SHA256:G4+ddwoZmhLPRB1agvXzZMXIzkVJ36dUYZXf5NxT+u8
4 changed files with 208 additions and 0 deletions

1
11/example Normal file
View file

@ -0,0 +1 @@
125 17

53
11/hash.h Normal file
View file

@ -0,0 +1,53 @@
#include <tuple>
// 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 <class T>
inline void hash_combine(std::size_t& seed, T const& v)
{
seed ^= hash<T>()(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
}
// Recursive template code derived from Matthieu M.
template <class Tuple, size_t Index = std::tuple_size<Tuple>::value - 1>
struct HashValueImpl
{
static void apply(size_t& seed, Tuple const& tuple)
{
HashValueImpl<Tuple, Index-1>::apply(seed, tuple);
hash_combine(seed, get<Index>(tuple));
}
};
template <class Tuple>
struct HashValueImpl<Tuple,0>
{
static void apply(size_t& seed, Tuple const& tuple)
{
hash_combine(seed, get<0>(tuple));
}
};
}
template <typename ... TT>
struct hash<std::tuple<TT...>>
{
size_t
operator()(std::tuple<TT...> const& tt) const
{
size_t seed = 0;
HashValueImpl<std::tuple<TT...> >::apply(seed, tt);
return seed;
}
};
}

1
11/input Normal file
View file

@ -0,0 +1 @@
4 4841539 66 5279 49207 134 609568 0

153
11/main.cc Normal file
View file

@ -0,0 +1,153 @@
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <unordered_map>
#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<tuple<long, int>, 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;;
}