From 51c91ab2f2c9c337fc17ec04661ed60fb7326d79 Mon Sep 17 00:00:00 2001 From: Alpha Chen Date: Sun, 17 Dec 2023 20:40:57 -0800 Subject: [PATCH] [2023][ruby][17.1] --- 2023/ruby/day_17.rb | 61 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 2023/ruby/day_17.rb diff --git a/2023/ruby/day_17.rb b/2023/ruby/day_17.rb new file mode 100644 index 0000000..e09ef49 --- /dev/null +++ b/2023/ruby/day_17.rb @@ -0,0 +1,61 @@ +def succ(coord, delta) + coord.zip(delta).map { _1 + _2 } +end + +map = ARGF.readlines(chomp: true) + .flat_map.with_index {|row, y| + row.chars.map.with_index {|elem, x| + [[y,x], elem.to_i] + } + }.to_h + +max_y = map.keys.map(&:first).max +max_x = map.keys.map(&:last).max +dest = [max_y,max_x] + +Node = Data.define(:pos, :dir, :continued) + +frontier = [] +visited = {} + +# seed initial directions +[ + [1,0], # down + [0,1], # right +].each do |dir| + node = Node.new(dir, dir, 1) + frontier << node + visited[node] = map.fetch(dir) +end + +loop do + frontier.sort_by! { visited.fetch(_1) } + current = frontier.shift + + # turn left and right + nexts = [current.dir.reverse, current.dir.reverse.map { -_1 }].map {|turn| + Node.new(current.pos.zip(turn).map { _1 + _2 }, turn, 1) + } + + # keep going? + if current.continued < 3 + nexts << Node.new( + current.pos.zip(current.dir).map { _1 + _2 }, + current.dir, + current.continued + 1, + ) + end + + if found = nexts.find { _1.pos == dest } + p visited.fetch(current) + map.fetch(dest) + exit + end + + nexts + .select { map.has_key?(_1.pos) } + .reject { visited.has_key?(_1) } + .each do |node| + frontier << node + visited[node] = visited.fetch(current) + map.fetch(node.pos) + end +end