Weihnachten ist zwar schon vorbei, aber ich habe immer noch Spaß mit den Advent of Code Aufgaben. Für Tag 15 habe ich folgendes gebastelt:
(Python 3)
Code: Alles auswählen
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import re
import fileinput
from itertools import tee, product
from functools import reduce
from operator import mul
ATTRIBUTES = ('capacity', 'durability', 'flavor', 'texture', 'calories')
EXCLUDED = ('calories')
SEPARATOR = re.compile(r'^(\w+)[^\d-]+(-?[\d]+)[^\d-]+(-?[\d]+)[^\d-]+(-?[\d]+)[^\d-]+(-?[\d]+)[^\d-]+(-?[\d]+)$')
SPOONS = 100
CALORIES = 500
class Cookie:
def __init__(self, amounts, stats, spoons=SPOONS):
self.amounts = amounts
self.stats = stats
if not sum(self.amounts.values()) == spoons:
raise ValueError
def __getattr__(self, name):
attribute = name
result = sum(
self.stats[ingredient][attribute]*amount
for ingredient, amount in self.amounts.items()
)
return result if result > 0 else 0
@property
def score(self):
return reduce(
mul,
[getattr(self, attribute) for attribute in ATTRIBUTES if not attribute in EXCLUDED]
)
def parse_file():
result = dict()
lines = [line.strip() for line in fileinput.input()]
for line in lines:
name, *stats = re.search(SEPARATOR, line).groups()
stats = map(int, stats)
result[name] = dict(zip(ATTRIBUTES, stats))
return result
def main():
stats = parse_file()
ingredients = stats.keys()
ingredients_n = len(ingredients)
upper_boundary = SPOONS - ingredients_n + 1
print("Part A")
result = max(
Cookie(dict(zip(ingredients, item)), stats).score
for item in filter(
lambda x:sum(x)==SPOONS,
product(*tee(range(1, upper_boundary), ingredients_n))
)
)
print(result)
print("Part B")
result = 0
for item in filter(
lambda x:sum(x)==SPOONS,
product(*tee(range(1, upper_boundary), ingredients_n))):
cookie = Cookie(dict(zip(ingredients, item)), stats)
if cookie.calories == CALORIES:
result = cookie.score if cookie.score > result else result
print(result)
if __name__ == '__main__':
main()Bzgl. der eigentlichen Lösung war ich unkreativ; das Verfahren ist ineffizient, aber liefert das Ergebnis in vertretbarer Zeit. Gibt es eigentlich auch einen effizienteren Algorithmus, um das zu bewältigen? Ich hatte zwischenzeitlich mal zufällige Kekse erstellt und mir den jeweils besten gemerkt; das gesuchte Optimum kommt spannenderweise meist in wenigen Sekunden und deutlich schneller, als per Brute-Force
An Kommentaren und Alternativvorschlägen wäre ich wie immer sehr interessiert.
