You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
advent-of-code/2016/ruby/day_24.rb

136 lines
2.3 KiB

class Solver
def initialize(maze)
@maze = maze
end
def solve(from, to)
seen = Set.new(from)
queue = [[from, 0]]
current = queue.shift
loop do
location = current[0]
break if location == to
if seen.include?(location)
current = queue.shift
next
end
seen << location
neighbors = maze
.open_neighbors(location[0], location[1])
.reject {|location| seen.include?(location) }
queue.concat(neighbors.map {|location| [location, current[1] + 1] })
return nil if queue.empty?
current = queue.shift
end
current[1]
end
private
attr_reader :maze
end
class Maze
attr_reader :locations
def initialize(input)
@maze = Hash.new
@locations = Hash.new
x, y = 0, 0
input.chars.each do |char|
case char
when /\d/
@locations[char.to_i] = [x,y]
char = ?.
when "\n"
x = -1
y += 1
else
# no-op
end
@maze[[x,y]] = char
x += 1
end
end
def [](x,y)
maze[[x,y]]
end
def open_neighbors(x, y)
[[-1, 0],
[ 1, 0],
[ 0, -1],
[ 0, 1]].map {|dx,dy|
[x+dx, y+dy]
}.select {|x,y|
self[x,y] == ?.
}
end
private
attr_reader :maze
end
if __FILE__ == $0
maze = Maze.new(ARGF.read)
solver = Solver.new(maze)
hash = maze.locations.to_a.combination(2).each.with_object({}) {|(a, b), hash|
steps = solver.solve(a[1], b[1])
hash[[a[0],b[0]]] = steps
hash[[b[0],a[0]]] = steps
}
p maze
.locations
.map(&:first)
.permutation
.select {|route| route[0] == 0 }
.map {|route|
[route, route.each_cons(2).map {|a,b| hash[[a,b]] }.inject(:+)]
}.sort_by(&:last)
.first
end
require 'minitest'
# require 'minitest/autorun'
class TestMaze < Minitest::Test
def test_maze
maze = Maze.new(<<-MAZE)
###########
#0.1.....2#
#.#######.#
#4.......3#
###########
MAZE
assert_equal [1,1], maze.locations[0]
assert_equal [[2,1], [1,2]], maze.open_neighbors(1,1)
end
end
class TestSolver < Minitest::Test
def test_solver
maze = Maze.new(<<-MAZE)
###########
#0.1.....2#
#.#######.#
#4.......3#
###########
MAZE
solver = Solver.new(maze)
assert_equal 2, solver.solve(maze.locations[0], maze.locations[4])
end
end