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
In [4]:
values = parse('inputs/input15.test1.txt')
assert(max_recipy_score(values) == 62842880)
In [5]:
values = parse('inputs/input15.txt')
max_recipy_score(values)
Out[5]:
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
In [7]:
values = parse('inputs/input15.test1.txt')
assert(max_recipy_score_calorie(values) == 57600000)
In [8]:
values = parse('inputs/input15.txt')
max_recipy_score_calorie(values)
Out[8]:
In [ ]: