Day 15: Science for Hungry People

Day 15.1


In [1]:
import csv
import numpy as np

def parse(input_path):
    with open(input_path, 'rt') as f_input:
        csv_reader = csv.reader(f_input, delimiter=' ')
        l = next(csv_reader)
        a = np.array([int(l[2*(j + 1)].rstrip(',')) for j in range(5)])
        count = 1
        for l in csv_reader:
            a = np.concatenate((a, np.array([int(l[2*(j + 1)].rstrip(',')) for j in range(5)])))
            count += 1
    return a.reshape((count, 5))

Generator of tuples of integers that add up to a given constant.


In [2]:
from itertools import combinations

def intervals(cuts, n):
    last = -1
    for cut in cuts:
        yield cut - last - 1
        last = cut
    yield n - 1 - last


def partitions(n, k):
    """
    Generator of seqs of k integers that sum up to n.
    """
    assert(1 <= k <= n)
    for cut in combinations(range(n + k - 1), k - 1):
        yield np.array(tuple(intervals(cut, n + k - 1)))

Test all recipy candidates.


In [3]:
import operator
from functools import reduce

def max_recipy_score(values, n=100):
    max_score = 0
    k = values.shape[0]
    for recipy in partitions(n, k):
        y = np.dot(recipy, values[:,:-1])
        mask = y > 0
        if reduce(operator.and_, mask, True):
            score = np.prod(y)
            if max_score < score: max_score = score
    return max_score

Test


In [4]:
values = parse('inputs/input15.test1.txt')
assert(max_recipy_score(values) == 62842880)

Solution


In [5]:
values = parse('inputs/input15.txt')
max_recipy_score(values)


Out[5]:
222870

Day 15.2


In [6]:
def max_recipy_score_calorie(values, n=100, c=500):
    max_score = 0
    k = values.shape[0]
    for recipy in partitions(n, k):
        y = np.dot(recipy, values[:,:-1])
        positive_totals = y > 0
        calorie_restriction = (np.dot(recipy, values[:,-1]) == c)
        if reduce(operator.and_, positive_totals, True) and calorie_restriction:
            score = np.prod(y)
            if max_score < score: max_score = score
    return max_score

Test


In [7]:
values = parse('inputs/input15.test1.txt')
assert(max_recipy_score_calorie(values) == 57600000)

Solution


In [8]:
values = parse('inputs/input15.txt')
max_recipy_score_calorie(values)


Out[8]:
117936

In [ ]: