Code for the Advent of Code event
aoc advent-of-code
at main 110 lines 3.0 kB view raw
1boss_data = {} 2 3stat_map = ['Hit Points']: 'hp', ['Damage']: 'damage', ['Armor']: 'armor' 4 5parse = (line) -> 6 trait, value = line\match '(.+): (%d+)' 7 boss_data[stat_map[trait]] = tonumber value if trait and value 8 9create_item = (name, cost, damage, armor) -> { :name, :cost, :damage, :armor } 10 11shop = 12 weapons: { 13 create_item 'Dagger', 8, 4, 0 14 create_item 'Shortsword', 10, 5, 0 15 create_item 'Warhammer', 25, 6, 0 16 create_item 'Longsword', 40, 7, 0 17 create_item 'Greataxe', 74, 8, 0 18 } 19 armor: { 20 create_item 'Naked', 0, 0, 0 21 create_item 'Leather', 13, 0, 1 22 create_item 'Chainmail', 31, 0, 2 23 create_item 'Splintmail', 53, 0, 3 24 create_item 'Bandedmail', 75, 0, 4 25 create_item 'Platemail', 102, 0, 5 26 } 27 rings: { 28 create_item 'Dummy 1', 0, 0, 0 29 create_item 'Dummy 2', 0, 0, 0 30 create_item 'Damage +1', 25, 1, 0 31 create_item 'Damage +2', 50, 2, 0 32 create_item 'Damage +3', 100, 3, 0 33 create_item 'Defense +1', 20, 0, 1 34 create_item 'Defense +2', 40, 0, 2 35 create_item 'Defense +3', 80, 0, 3 36 } 37 38calculate_combination = (list) -> 39 cost, damage, armor = 0, 0, 0 40 41 with shop.weapons[list[1]] 42 cost += .cost 43 damage += .damage 44 armor += .armor 45 46 with shop.armor[list[2]] 47 cost += .cost 48 damage += .damage 49 armor += .armor 50 51 for i = 3, 4 52 with shop.rings[list[i]] 53 cost += .cost 54 damage += .damage 55 armor += .armor 56 57 cost, damage, armor 58 59copy = (tbl) -> 60 return tbl unless type(tbl) == 'table' 61 { k, copy v for k, v in pairs tbl } 62 63fight = (damage, armor) -> 64 player = hp: 100, :damage, :armor 65 boss = copy boss_data 66 67 while player.hp > 0 and boss.hp > 0 68 hp_change = -player.damage + boss.armor 69 hp_change = -1 if hp_change > -1 70 boss.hp += hp_change 71 hp_change = -boss.damage + player.armor 72 hp_change = -1 if hp_change > -1 73 player.hp += hp_change 74 75 player.hp > 0 and boss.hp < 1 76 77combinations = -> coroutine.wrap -> 78 list = {} 79 80 -- Very dirty and hardcoded way to calculate all possible combinations 81 for w_i = 1, #shop.weapons 82 list[1] = w_i 83 for a_i = 1, #shop.armor 84 list[2] = a_i 85 for r1_i = 1, #shop.rings 86 list[3] = r1_i 87 for r2_i = 1, #shop.rings 88 continue if r2_i == r1_i 89 list[4] = r2_i 90 coroutine.yield list 91 92get_lowest_cost = -> 93 min_cost = 1e9 94 95 for list in combinations! 96 cost, damage, armor = calculate_combination list 97 min_cost = cost if fight(damage, armor) and cost < min_cost 98 99 min_cost 100 101get_highest_cost = -> 102 max_cost = 0 103 104 for list in combinations! 105 cost, damage, armor = calculate_combination list 106 max_cost = cost unless fight(damage, armor) or cost < max_cost 107 108 max_cost 109 110{ :parse, :get_lowest_cost, :get_highest_cost }