Skip to content

Instantly share code, notes, and snippets.

@tomviner
Last active December 27, 2019 18:07
Show Gist options
  • Save tomviner/5aa9449ee7742f70747fd46bdaab8031 to your computer and use it in GitHub Desktop.
Save tomviner/5aa9449ee7742f70747fd46bdaab8031 to your computer and use it in GitHub Desktop.
Advent of Code 2019 Day 14
import math
from collections import Counter
from funcy import post_processing
from parse import parse
from scipy.optimize import minimize_scalar
@post_processing(dict)
def parse_input(input_str):
quantity_pattern = '{num:d} {unit:w}'
for line in input_str.strip().splitlines():
left_str, right = line.split(' => ')
lefts = [parse(quantity_pattern, input) for input in left_str.split(', ')]
lefts = {input['unit']: input['num'] for input in lefts}
right = parse(quantity_pattern, right)
yield right['unit'], {'right_num': right['num'], 'lefts': lefts}
def calc_ore(eqs, fuel):
chemicals = Counter()
chemicals['FUEL'] = fuel
last_chemicals = None
while last_chemicals != chemicals:
last_chemicals = chemicals.copy()
for right, eq_data in eqs.items():
for got_unit, got_num in list(chemicals.items()):
if got_unit == right and got_num > 0:
mult = math.ceil(got_num / eq_data['right_num'])
chemicals[got_unit] -= mult * eq_data['right_num']
for left_unit, left_num in eq_data['lefts'].items():
chemicals[left_unit] += mult * left_num
return chemicals['ORE']
def part_one(input_str):
eqs = parse_input(input_str)
return calc_ore(eqs, fuel=1)
def part_two(input_str):
eqs = parse_input(input_str)
max_ore = 1e12
def fuel_error(fuel_quota):
ore = calc_ore(eqs, int(fuel_quota))
print(fuel_quota, ore)
ore_left = max_ore - ore
if ore_left < 0:
# Penalise using more than the quota
return abs(ore_left) * 100
return ore_left
ore_per_fuel = calc_ore(eqs, fuel=1)
fuel_estimate = max_ore / ore_per_fuel
fuel = minimize_scalar(
fuel_error,
bracket=(fuel_estimate, 2 * fuel_estimate)
).x
return int(fuel)
@dkwgit
Copy link

dkwgit commented Dec 27, 2019

Yes, once you have a complex enough problem, being able to black box it like this is a huge plus.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment