From e3fe7fb6bccb8dfb61eae3fbd80323686294db24 Mon Sep 17 00:00:00 2001 From: cupcakearmy Date: Mon, 28 Nov 2022 23:51:45 +0100 Subject: [PATCH] 14 --- 2021/14/README.md | 13 +++++++ 2021/14/python/main.py | 86 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 2021/14/README.md create mode 100644 2021/14/python/main.py diff --git a/2021/14/README.md b/2021/14/README.md new file mode 100644 index 0000000..e19a636 --- /dev/null +++ b/2021/14/README.md @@ -0,0 +1,13 @@ +# 14 + +This was nice! Similar to the Lanterfish one. The naive way is to have a big string, but that becomes unfeasible quickly. + +The solution was to keep track of the number of combinations available and at the end divide by 2 the counted elements. Rounding up so that the first and last element is not neglected as they are not doubled. + +
+ Solutions +
    +
  1. 2988
  2. +
  3. 3572761917024
  4. +
+
diff --git a/2021/14/python/main.py b/2021/14/python/main.py new file mode 100644 index 0000000..cd198d2 --- /dev/null +++ b/2021/14/python/main.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python + +import math +from collections import defaultdict +from os.path import dirname, join + +# Day 14 + +# Common + + +def read_input(filename): + data = join(dirname(__file__), '..', filename) + with open(data) as f: + return f.read().strip() + + +test = read_input('test.txt') +data = read_input('input.txt') + + +class Polymer: + def __init__(self, state: str, insertions: dict[str, str]): + self.state = state + self.insertions = insertions + self.states: defaultdict[str, int] = defaultdict(lambda: 0) + + for i in range(len(self) - 1): + pair = self.state[i:i+2] + self.states[pair] += 1 + + def __len__(self): + return len(self.state) + + def step(self): + new = defaultdict(lambda: 0) + for state, count in self.states.items(): + if count == 0: + continue + insertion = self.insertions[state] + for key in [state[0] + insertion, insertion + state[1]]: + new[key] += count + self.states = new + + def score(self): + elements = defaultdict(lambda: 0) + for state, count in self.states.items(): + for element in state: + elements[element] += count + for element, count in elements.items(): + elements[element] = math.ceil(elements[element]/2) + return max(elements.values()) - min(elements.values()) + + def flag(self, steps: int): + for _ in range(steps): + self.step() + print(self.score()) + + @staticmethod + def parse(data: str): + state, raw = data.split('\n\n') + lines = [ + l.split(' -> ') + for l in raw.split('\n') + ] + insertions = { + i[0]: i[1] + for i in lines + } + return Polymer(state.strip(), insertions) + + +# 1 +print('1.') + +polymer = Polymer.parse(test) +polymer.flag(10) +polymer = Polymer.parse(data) +polymer.flag(10) + +# 2 +print('\n2.') +polymer = Polymer.parse(test) +polymer.flag(40) +polymer = Polymer.parse(data) +polymer.flag(40)