Code for the Advent of Code event
aoc
advent-of-code
1ingredients = {}
2
3parse = (line) ->
4 name, capacity, durability, flavor, texture, calories = line\match '(%w+): capacity (%-?%d+), durability (%-?%d+), flavor (%-?%d+), texture (%-?%d+), calories (%-?%d+)'
5 ingredients[#ingredients + 1] = {
6 :name
7 capacity: tonumber capacity
8 durability: tonumber durability
9 flavor: tonumber flavor
10 texture: tonumber texture
11 calories: tonumber calories
12 }
13
14calc = (counts, ignore_calories = false) ->
15 capacity = 0
16 durability = 0
17 flavor = 0
18 texture = 0
19 calories = 0
20
21 for i, data in ipairs ingredients
22 capacity += counts[i] * data.capacity
23 durability += counts[i] * data.durability
24 flavor += counts[i] * data.flavor
25 texture += counts[i] * data.texture
26 calories += counts[i] * data.calories
27
28 capacity = 0 if capacity < 0
29 durability = 0 if durability < 0
30 flavor = 0 if flavor < 0
31 texture = 0 if texture < 0
32 calories = 0 if calories < 0
33
34 score = capacity * durability * flavor * texture
35 score *= calories unless ignore_calories
36 score, calories
37
38generate = (tbl = {}, i = 1, count = #ingredients, limit = 100, aggregator = 0) ->
39 if i == count
40 tbl[i] = 100 - aggregator
41 coroutine.yield tbl
42
43 for n = 0, limit
44 tbl[i] = n
45 generate tbl, i + 1, count, limit - n, aggregator + n
46
47combinations = ->
48 coroutine.wrap -> generate!
49
50best_score = (calorie_watch = false) ->
51 max = 0
52
53 --for combination in combinations!
54 -- score = calc combination, true
55 -- max = score if score > max
56
57 for first = 0, 100
58 for second = 0, 100 - first
59 for third = 0, 100 - first - second
60 fourth = 100 - first - second - third
61 score, calories = calc {first, second, third, fourth}, true
62 max = score if score > max and (not calorie_watch or calories == 500)
63
64 max
65
66{ :parse, :calc, :best_score }