aoc24/11/main.cc

152 lines
No EOL
3.1 KiB
C++

#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;
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;;
}