|
| 1 | +#!/usr/bin/env ruby |
| 2 | + |
| 3 | +require 'numo/narray' |
| 4 | +require 'algorithms' |
| 5 | + |
| 6 | +class Map |
| 7 | + attr_accessor :map, :costs |
| 8 | + |
| 9 | + def initialize |
| 10 | + @height = 71 |
| 11 | + @width = 71 |
| 12 | + @map = Numo::UInt8.zeros(@height, @width) |
| 13 | + @costs = Numo::UInt32.new(@height, @width).fill Numo::UInt32::MAX |
| 14 | + end |
| 15 | + |
| 16 | + def push!(input) |
| 17 | + input.each do |line| |
| 18 | + x, y = line.split(',').map(&:to_i) |
| 19 | + @map[y, x] = 1 |
| 20 | + end |
| 21 | + end |
| 22 | + |
| 23 | + def solve! |
| 24 | + queue = Containers::MinHeap.new |
| 25 | + queue.push(0, { y: 0, x: 0 }) |
| 26 | + |
| 27 | + until queue.empty? |
| 28 | + cost = queue.next_key |
| 29 | + pos = queue.pop |
| 30 | + |
| 31 | + y = pos[:y] |
| 32 | + x = pos[:x] |
| 33 | + |
| 34 | + @costs[y, x] = cost |
| 35 | + |
| 36 | + return cost if y == @height - 1 && x == @width - 1 |
| 37 | + |
| 38 | + if y > 0 && @map[y - 1, x].zero? && @costs[y - 1, x] > (cost + 1) && @costs[y - 1, x] != Numo::UInt32::MAX - 1 |
| 39 | + queue.push(cost + 1, { y: y - 1, x: x }) |
| 40 | + @costs[y - 1, x] = Numo::UInt32::MAX - 1 |
| 41 | + end |
| 42 | + if x < @width - 1 && @map[y, x + 1].zero? && @costs[y, x + 1] > (cost + 1) && @costs[y, x + 1] != Numo::UInt32::MAX - 1 |
| 43 | + queue.push(cost + 1, { y: y, x: x + 1 }) |
| 44 | + @costs[y, x + 1] = Numo::UInt32::MAX - 1 |
| 45 | + end |
| 46 | + if y < @height - 1 && @map[y + 1, x].zero? && @costs[y + 1, x] > (cost + 1) && @costs[y + 1, x] != Numo::UInt32::MAX - 1 |
| 47 | + queue.push(cost + 1, { y: y + 1, x: x }) |
| 48 | + @costs[y + 1, x] = Numo::UInt32::MAX - 1 |
| 49 | + end |
| 50 | + if x > 0 && @map[y, x - 1].zero? && @costs[y, x - 1] > (cost + 1) && @costs[y, x - 1] != Numo::UInt32::MAX - 1 |
| 51 | + queue.push(cost + 1, { y: y, x: x - 1 }) |
| 52 | + @costs[y, x - 1] = Numo::UInt32::MAX - 1 |
| 53 | + end |
| 54 | + end |
| 55 | + end |
| 56 | + |
| 57 | + def inspect |
| 58 | + to_s |
| 59 | + end |
| 60 | + |
| 61 | + def to_s |
| 62 | + chars = ['.', '#'] |
| 63 | + s = "<#{self.class}:\n" |
| 64 | + @height.times do |y| |
| 65 | + @width.times do |x| |
| 66 | + s += chars[@map[y, x]] |
| 67 | + end |
| 68 | + s += "\n" |
| 69 | + end |
| 70 | + s += '>' |
| 71 | + s |
| 72 | + end |
| 73 | +end |
| 74 | + |
| 75 | +map = Map.new |
| 76 | +map.push! File.read('18.input').lines.map(&:strip)[..1023] |
| 77 | +puts map.solve! |
0 commit comments