mirror of
https://github.com/cupcakearmy/advent-of-code.git
synced 2024-12-22 16:16:26 +00:00
7
This commit is contained in:
parent
ad6001e572
commit
791b94827e
15
solutions/7/README.md
Normal file
15
solutions/7/README.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# 7
|
||||||
|
|
||||||
|
This one was maybe the coolest yet! Fixed-point iteration and some recursion. Amazing :)
|
||||||
|
|
||||||
|
For the first part we iterate as long as we don't find any enclosing bags anymore. This can build long chains.
|
||||||
|
|
||||||
|
The second we recurse down the bag chain und sum it up recursively.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Solutions</summary>
|
||||||
|
<ol>
|
||||||
|
<li>164</li>
|
||||||
|
<li>7872</li>
|
||||||
|
</ol>
|
||||||
|
</details>
|
70
solutions/7/python/main.py
Normal file
70
solutions/7/python/main.py
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
from os.path import join, dirname
|
||||||
|
from typing import Dict, List, Set, Tuple
|
||||||
|
import re
|
||||||
|
|
||||||
|
TRules = Dict[str, Dict[str, int]]
|
||||||
|
|
||||||
|
|
||||||
|
def split_trim(input: str, split: str) -> List[str]:
|
||||||
|
return list(map(lambda s: s.strip(), input.split(split)))
|
||||||
|
|
||||||
|
|
||||||
|
def extract_inner(input: str) -> Tuple[int, str]:
|
||||||
|
parts = input.split(' ')
|
||||||
|
amount = int(parts[0])
|
||||||
|
color = ' '.join(parts[1:-1])
|
||||||
|
return amount, color
|
||||||
|
|
||||||
|
|
||||||
|
def parse_rules(rules: str) -> TRules:
|
||||||
|
d: TRules = {}
|
||||||
|
for rule in rules.strip().split('\n'):
|
||||||
|
outer, inner = split_trim(rule, 'contain')
|
||||||
|
outer = re.sub(r'bags?', '', outer).strip()
|
||||||
|
d[outer] = {
|
||||||
|
color: amount
|
||||||
|
for amount, color in [
|
||||||
|
extract_inner(i)
|
||||||
|
for i in split_trim(inner, ',')
|
||||||
|
if 'no other bag' not in i # Also matches "bags"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
|
||||||
|
|
||||||
|
def find_enclosing_bags(rules: TRules, color: str) -> Set[str]:
|
||||||
|
colors: Set[str] = set()
|
||||||
|
stack: Set[str] = set([color])
|
||||||
|
|
||||||
|
while len(stack):
|
||||||
|
for item in list(stack):
|
||||||
|
stack.remove(item)
|
||||||
|
for contains, enclosing in rules.items():
|
||||||
|
if item in enclosing:
|
||||||
|
if contains not in colors:
|
||||||
|
stack.add(contains)
|
||||||
|
colors.add(contains)
|
||||||
|
return colors
|
||||||
|
|
||||||
|
|
||||||
|
def count_containing(rules: TRules, color: str) -> int:
|
||||||
|
children = rules[color]
|
||||||
|
if not children:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
return sum([
|
||||||
|
amount + amount * count_containing(rules, clr)
|
||||||
|
for clr, amount in children.items()
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
data = join(dirname(__file__), '../data.txt')
|
||||||
|
with open(data) as f:
|
||||||
|
rules = parse_rules(f.read())
|
||||||
|
|
||||||
|
color = 'shiny gold'
|
||||||
|
first = len(find_enclosing_bags(rules, color))
|
||||||
|
print(f'We can pack the {color} into {first} bags')
|
||||||
|
|
||||||
|
second = count_containing(rules, color)
|
||||||
|
print(f'We need to put {second} bags into {color}')
|
Loading…
Reference in New Issue
Block a user