Code for the Advent of Code event
aoc advent-of-code
at rust 67 lines 1.8 kB view raw
1#!/usr/bin/env ruby 2# frozen_string_literal: true 3 4valves = {} 5 6ARGF.readlines.each do |line| 7 next unless line =~ /\b([A-Z]{2})\b.+?(\d+).+?((?:[A-Z]{2}(?:, )?)+)/ 8 valves[$1.to_sym] = { 9 rate: $2.to_i, 10 tunnels: $3.split(', ').map(&:to_sym).to_a 11 } 12end 13 14HAS_FLOW = valves.reject { _2[:rate] == 0 }.to_set { |k, _| k } 15 16def solve(valves, memory, mins, current, score, visited, opened) 17 key = [mins, current, score] 18 return memory[key] if memory.key?(key) 19 20 return [score, opened] if mins <= 0 21 return [score, opened] if HAS_FLOW.all? { opened.include? _1 } 22 23 visited = visited.dup 24 visited.add current 25 26 valve = valves[current] 27 rate = valve[:rate] 28 29 max = score 30 max_opened = opened 31 32 tovisit = valve[:tunnels] 33 tovisit.each do |tunnel| 34 simple_max, simple_o = solve(valves, memory, mins - 1, tunnel, score, visited, opened) 35 if simple_max > max 36 max = simple_max 37 max_opened = simple_o 38 end 39 next unless rate > 0 && !opened.include?(current) 40 added = rate * (mins - 1) 41 new_opened = opened.dup 42 new_opened.add current 43 complex_max, complex_o = solve(valves, memory, mins - 2, tunnel, score + added, visited, new_opened) 44 if complex_max > max 45 max = complex_max 46 max_opened = complex_o 47 end 48 end 49 50 memory[key] = [max, max_opened] 51 52 [max, max_opened] 53end 54 55part1, _opened = solve(valves, {}, 30, :AA, 0, Set.new, Set.new) 56 57puts part1 58 59part2_human, opened2_human = solve(valves, {}, 26, :AA, 0, Set.new, Set.new) 60opened2_human.each { valves[_1][:rate] = 0 } 61part2_elephant, opened2_elephant = solve(valves, {}, 26, :AA, 0, Set.new, Set.new) 62 63warn 'PART 2:' 64warn "Human score: #{part2_human} (opened #{opened2_human})" 65warn "Elephant score: #{part2_elephant} (opened #{opened2_elephant})" 66 67puts part2_human + part2_elephant