Code for the Advent of Code event
aoc
advent-of-code
1people = {}
2
3parse = (line) ->
4 name, mod, amount, other = line\match '^(%w+) would (%w+) (%d+) happiness units by sitting next to (%w+)%.$'
5
6 change = (mod == 'gain' and 1 or -1) * amount
7
8 people[name] = {} unless people[name]
9 people[name][other] = change
10
11generate_permutations = (list, length) ->
12 coroutine.yield list if length == 0
13
14 for i = 1, length
15 list[length], list[i] = list[i], list[length]
16 generate_permutations list, length - 1
17 list[length], list[i] = list[i], list[length]
18
19permutations = (list) ->
20 length = table.getn list
21 coroutine.wrap -> generate_permutations list, length
22
23get_happiness = (order) ->
24 happiness = 0
25 for index, person in ipairs order
26 happiness += people[person][order[index == 1 and #order or index - 1]]
27 happiness += people[person][order[index == #order and 1 or index + 1]]
28 happiness
29
30get_max_happiness = ->
31 names = [k for k, _ in pairs people]
32 values = [get_happiness perm for perm in permutations names]
33 max = values[1]
34 for i = 2, #values
35 max = values[i] if values[i] > max
36 max
37
38add_self = ->
39 people.__SELF__ = {}
40 for name, _ in pairs people
41 unless name == '__SELF__'
42 people.__SELF__[name] = 0
43 people[name].__SELF__ = 0
44
45
46{ :parse, :get_max_happiness, :add_self }