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/2022/ruby/day_22.rb

79 lines
1.8 KiB

require "strscan"
include Math
map, path = ARGF.read.chomp.split("\n\n")
map = map.split("\n").each.with_index.with_object({}) {|(row,y),map|
row.chars.each.with_index do |tile,x|
map[[y,x]] = tile if tile != " "
end
}
max_y = map.keys.map(&:first).max
max_x = map.keys.map(&:last).max
start_x = map.keys.select { _1.first.zero? }.map(&:last).min
current = [0, start_x]
facing = 0
ss = StringScanner.new(path)
until ss.eos?
case
when n = ss.scan(/\d+/)
n = n.to_i
n.times do
y, x = current.zip([-sin(facing),cos(facing)]).map { _1 + _2 }.map(&:to_i)
next_tile = map[[y,x]]
unless next_tile
puts
p [y,x, facing]
y, x = case facing
when 0 then [y, 0]
when PI/2 then [max_y, x]
when PI then [y, max_x]
when 3*PI/2 then [0, x]
else fail "unexpected facing: #{facing}"
end
next_tile = map[[y,x]]
while next_tile.nil?
y, x = [y, x].zip([-sin(facing),cos(facing)]).map { _1 + _2 }.map(&:to_i)
next_tile = map[[y,x]]
end
p [y,x,next_tile]
end
case next_tile
when ?.
current = [y,x]
when ?#
break
else
fail "unexpected tile: #{next_tile}"
end
end
when dir = ss.scan(/R|L/)
facing += case dir
when ?R then -PI/2
when ?L then PI/2
else fail "unexpected dir: #{dir}"
end
facing %= 2*PI
else
fail ss.rest
end
end
row, col = current.map { _1 + 1 }
facing = case facing
when 0 then 0
when PI/2 then 3
when PI then 2
when 3*PI/2 then 2
else
fail "unexpected facing: #{facing}"
end
p [1000, 4, 1].zip([row, col, facing]).sum { _1 * _2 }