Code for the Advent of Code event
aoc advent-of-code
at main 63 lines 1.5 kB view raw
1# frozen_string_literal: true 2 3require_relative 'pqueue' 4 5INF = Float::INFINITY 6 7module AStar 8 class << self 9 def find_path(graph, start, goal, &heuristic) 10 heuristic ||= method(:default_heuristic) 11 12 frontier = PriorityQueue.new 13 came_from = {} 14 cost_so_far = {} 15 16 if start.is_a?(Enumerable) && !start.is_a?(Vector) 17 start.each do 18 frontier.enqueue _1, 0 19 came_from[_1] = nil 20 cost_so_far[_1] = 0 21 end 22 else 23 frontier.enqueue start, 0 24 came_from[start] = nil 25 cost_so_far[start] = 0 26 end 27 28 while frontier.any? 29 current = frontier.dequeue 30 break if current == goal 31 graph.neighbors(current).each do |vertex| 32 new_cost = cost_so_far[current] + graph.cost(current, vertex) 33 next unless !cost_so_far.key?(vertex) || new_cost < cost_so_far[vertex] 34 cost_so_far[vertex] = new_cost 35 priority = new_cost + heuristic.call(vertex, goal) 36 frontier.enqueue vertex, priority 37 came_from[vertex] = current 38 end 39 end 40 41 [came_from, cost_so_far] 42 end 43 44 def reconstruct_path(came_from, start, goal) 45 current = goal 46 path = [] 47 while current != start 48 path << current 49 current = came_from[current] 50 end 51 path << start 52 path.reverse 53 end 54 55 private 56 57 def default_heuristic(a, b) 58 x1, y1 = a.to_a 59 x2, y2 = b.to_a 60 (x1 - x2).abs + (y1 - y2).abs 61 end 62 end 63end