input = DATA.read.split("\n\n") map = {} input.shift.split("\n").each.with_index do |row, y| row.chars.each.with_index do |pos, x| map[[y,x]] = pos unless pos == ?. end end robot = map.find { _2 == ?@ }.first bounds = [ (0..map.keys.map(&:first).max), (0..map.keys.map(&:last).max), ] map_s = ->() { bounds[0].map { |y| bounds[1].map { |x| map.fetch([y,x], ?.) }.join }.join("\n") } Nope = Class.new(Exception) def push(map, pos, move) delta = DELTAS.fetch(move) pospos = pos.zip(delta).map { _1 + _2 } case map.fetch(pospos, nil) when ?# raise Nope when ?O push(map, pospos, move) when nil else fail end map[pospos] = map.fetch(pos) map.delete(pos) pospos end DELTAS = %w[ ^ v < > ].zip([[-1,0], [1,0], [0,-1], [0, 1]]).to_h movements = input.shift.gsub("\n", "").chars movements.each do |move| begin robot = push(map, robot, move) rescue Nope end end pp map.select { _2 == ?O }.sum {|(y,x),_| 100 * y + x } __END__ ####### #...#.# #.....# #..OO@# #..O..# #.....# #######