From 3da106ed46d2a1f40633dd557d496e60adb8d354 Mon Sep 17 00:00:00 2001 From: Andrew Tomaka Date: Wed, 25 Dec 2024 15:27:41 -0500 Subject: [PATCH] Day twenty-one Part two --- 21/main.rb | 255 ++++++++++------------------------------------------- 1 file changed, 46 insertions(+), 209 deletions(-) diff --git a/21/main.rb b/21/main.rb index 0f0aaa1..0d7e11f 100755 --- a/21/main.rb +++ b/21/main.rb @@ -114,220 +114,57 @@ def dijkstra(graph, movements, start, target) return dest, paths end -# calculate most efficient number pad paths -# actually AN efficient path; ties not included :\ -# @numeric_map = numeric_keypad -# .flatten.reject { _1.nil? } -# .permutation(2).to_a -# .map { [[_1, _2], dijkstra_with_lookup(numeric_keypad, numeric_movements, _1, _2)] } -# .map do |(start, target), (dest, paths)| -# presses = paths.map do |path| -# ([discover(start, numeric_keypad)] + path) -# .each_cons(2).to_a -# .map { @dir_arrows[[_2.first - _1.first, _2.last - _1.last]] }.join -# end -# [[start, target], presses] -# end -# .to_h - -@numeric_map = { - ["7", "8"]=>[">"], - ["7", "9"]=>[">>"], - ["7", "4"]=>["v"], - ["7", "5"]=>["v>"], - ["7", "6"]=>["v>>"], - ["7", "1"]=>["vv"], - ["7", "2"]=>["vv>"], - ["7", "3"]=>["vv>>"], - ["7", "0"]=>[">vvv", "v>vv", "vv>v"], - ["7", "A"]=>[">>vvv"], - ["8", "7"]=>["<"], - ["8", "9"]=>[">"], - ["8", "4"]=>["["v"], - ["8", "6"]=>["v>"], - ["8", "1"]=>["["vv"], - ["8", "3"]=>["vv>"], - ["8", "0"]=>["vvv"], - ["8", "A"]=>["vvv>"], - ["9", "7"]=>["<<"], - ["9", "8"]=>["<"], - ["9", "4"]=>["<["["v"], - ["9", "1"]=>["<["["vv"], - ["9", "0"]=>["["vvv"], - ["4", "7"]=>["^"], - ["4", "8"]=>["^>", ">^"], - ["4", "9"]=>["^>>", ">>^"], - ["4", "5"]=>[">"], - ["4", "6"]=>[">>"], - ["4", "1"]=>["v"], - ["4", "2"]=>["v>"], - ["4", "3"]=>["v>>"], - ["4", "0"]=>[">vv"], - ["4", "A"]=>[">>vv"], - ["5", "7"]=>["<^", "^<"], - ["5", "8"]=>["^"], - ["5", "9"]=>["^>", ">^"], - ["5", "4"]=>["<"], - ["5", "6"]=>[">"], - ["5", "1"]=>["["v"], - ["5", "3"]=>["v>"], - ["5", "0"]=>["vv"], - ["5", "A"]=>["vv>"], - ["6", "7"]=>["<<^", "^<<"], - ["6", "8"]=>["<^", "^<"], - ["6", "9"]=>["^"], - ["6", "4"]=>["<<"], - ["6", "5"]=>["<"], - ["6", "1"]=>["<["["v"], - ["6", "0"]=>["["vv"], - ["1", "7"]=>["^^"], - ["1", "8"]=>["^^>", ">^^"], - ["1", "9"]=>["^^>>", ">>^^"], - ["1", "4"]=>["^"], - ["1", "5"]=>["^>", ">^"], - ["1", "6"]=>["^>>", ">>^"], - ["1", "2"]=>[">"], - ["1", "3"]=>[">>"], - ["1", "0"]=>[">v"], - ["1", "A"]=>[">>v", ">v>"], - ["2", "7"]=>["<^^", "^^<"], - ["2", "8"]=>["^^"], - ["2", "9"]=>["^^>", ">^^"], - ["2", "4"]=>["<^", "^<"], - ["2", "5"]=>["^"], - ["2", "6"]=>["^>", ">^"], - ["2", "1"]=>["<"], - ["2", "3"]=>[">"], - ["2", "0"]=>["v"], - ["2", "A"]=>[">v", "v>"], - ["3", "7"]=>["<<^^", "^^<<"], - ["3", "8"]=>["<^^", "^^<"], - ["3", "9"]=>["^^"], - ["3", "4"]=>["<<^", "^<<"], - ["3", "5"]=>["<^", "^<"], - ["3", "6"]=>["^"], - ["3", "1"]=>["<<"], - ["3", "2"]=>["<"], - ["3", "0"]=>["["v"], - ["0", "7"]=>["^^^<"], - ["0", "8"]=>["^^^"], - ["0", "9"]=>["^^^>", ">^^^"], - ["0", "4"]=>["^^<"], - ["0", "5"]=>["^^"], - ["0", "6"]=>["^^>", ">^^"], - ["0", "1"]=>["^<"], - ["0", "2"]=>["^"], - ["0", "3"]=>["^>", ">^"], - ["0", "A"]=>[">"], - ["A", "7"]=>["^^^<<"], - ["A", "8"]=>["<^^^", "^^^<"], - ["A", "9"]=>["^^^"], - ["A", "4"]=>["^^<<"], - ["A", "5"]=>["<^^", "^^<"], - ["A", "6"]=>["^^"], - ["A", "1"]=>["^<<"], - ["A", "2"]=>["<^", "^<"], - ["A", "3"]=>["^"], - ["A", "0"]=>["<"] -} - -# cache efficient direction movements -# @directional_map = directional_keypad -# .flatten.reject { _1.nil? } -# .permutation(2).to_a -# .map { [[_1, _2], dijkstra_with_lookup(directional_keypad, directional_movements, _1, _2)] } -# .map do |(start, target), (dest, paths)| -# presses = paths.map do |path| -# ([discover(start, directional_keypad)] + path) -# .each_cons(2).to_a -# .map { @dir_arrows[[_2.first - _1.first, _2.last - _1.last]] }.join -# end -# [[start, target], presses] -# end -# .to_h - -@directional_map = { - ["^", "A"]=>[">"], - ["^", "<"]=>["v<"], - ["^", "v"]=>["v"], - ["^", ">"]=>[">v", "v>"], - ["A", "^"]=>["<"], - ["A", "<"]=>["v<<", "["v<", ""]=>["v"], - ["<", "^"]=>[">^"], - ["<", "A"]=>[">>^"], - ["<", "v"]=>[">"], - ["<", ">"]=>[">>"], - ["v", "^"]=>["^"], - ["v", "A"]=>["^>", ">^"], - ["v", "<"]=>["<"], - ["v", ">"]=>[">"], - [">", "^"]=>["^<", "<^"], - [">", "A"]=>["^"], - [">", "<"]=>["<<"], - [">", "v"]=>["<"] -} - -def solve(input, times = 3) - @robot_1 = input - @robot_2 = @robot_1 - .map { ["A"] + _1 } - .map { _1.each_cons(2).to_a } - .map { _1.map { |move| @numeric_map[move].first }.join("A") } - .map { _1 + "A" } - - (3..times).each do |num| - prev_robot = instance_variable_get(:"@robot_#{num - 1}") - - robot = prev_robot - .map { _1.chars } - .map { ["A"] + _1 } - .map { _1.each_cons(2).to_a } - .map do - _1.map do |move| - @directional_map[move].nil? ? "" : @directional_map[move].first - end.join("A") - end - .map { _1 + "A" } - instance_variable_set(:"@robot_#{num}", robot) - - @last_num = num - end - - last_robot = instance_variable_get(:"@robot_#{@last_num}") - me = last_robot - .map { _1.chars } - .map { ["A"] + _1 } - .map { _1.each_cons(2).to_a } - .map do - _1.map do |move| - @directional_map[move].nil? ? "" : @directional_map[move].first - end.join("A") +@numeric_map = numeric_keypad + .flatten.reject(&:nil?) + .permutation(2).to_a + .map { [[_1, _2], dijkstra_with_lookup(numeric_keypad, numeric_movements, _1, _2)] } + .map do |(start, target), (dest, paths)| + presses = paths.map do |path| + ([discover(start, numeric_keypad)] + path) + .each_cons(2).to_a + .map { @dir_arrows[[_2.first - _1.first, _2.last - _1.last]] } end - .map { _1 + "A" } + [[start, target], presses] + end + .to_h - me +@directional_map = directional_keypad + .flatten.reject(&:nil?) + .permutation(2).to_a + .map { [[_1, _2], dijkstra_with_lookup(directional_keypad, directional_movements, _1, _2)] } + .map do |(start, target), (dest, paths)| + presses = paths.map do |path| + ([discover(start, directional_keypad)] + path) + .each_cons(2).to_a + .map { @dir_arrows[[_2.first - _1.first, _2.last - _1.last]] } + end + [[start, target], presses] + end + .to_h + +def minimum(chars, robots = 2, depth = 0, cache = {}) + return cache[[chars, depth]] if cache.key?([chars, depth]) + + current, length, chars = "A", 0, Array(chars) + return cache[[chars, depth]] = chars.map do |char| + moves = (depth == 0 ? @numeric_map : @directional_map) + .fetch([current, char], [[]]) + .map { _1 + ["A"] } + current = char + + if depth == robots + moves.map(&:size).min + else + moves.map { minimum(_1, robots, depth + 1, cache) }.min + end + end.sum end -me = solve(input, 3) +@numeric_map = @numeric_map +@directional_map = @directional_map -me.each_with_index do |entry, i| - p "#{entry.length} * #{input[i].join.to_i} = #{entry.length * input[i].join.to_i}" -end -p me.map.with_index { |entry, i| entry.length * input[i].join.to_i }.sum +p input.map { minimum(_1) * _1.join.to_i }.sum +p input.map { minimum(_1, 25) * _1.join.to_i }.sum __END__ 029A