|
SIZE, IDS, ADJ, EDGES = 50, [1, 2, 4, 6, 7, 9], {1+0i => 0, 1i => 1, -1+0i => 1+1i, -1i => 1i}, { |
|
2+1i => [9, 1], 9-1i => [2, 1], 1 => [7, -1], 6 => [2, -1], 2 => [6, -1], 7 => [1, -1], 1+1i => [9, 1i], |
|
10 => [1, -1i], 6+1i => [4, 1i], 5 => [6, -1i], 7-1i => [9, 1i], 8 => [7, -1i], 2-1i => [4, 1i], 3 => [2, -1i] |
|
}.transform_keys(&:to_c) |
|
|
|
def id(pos) = (pos.imag / SIZE) * 3 + pos.real / SIZE |
|
def origin(face) = ((face / 3) * SIZE).i + ((face % 3) * SIZE) |
|
def clamp(point) = point.real % SIZE + (point.imag % SIZE).i |
|
def step(p, d) = IDS.include?(id(p + d)) && [p + d, d] |
|
def wrap(grid, p, d) = step(p, d) || [Enumerator.produce(p) { _1 - d }.take_while { grid[_1] }.last, d] |
|
def cube(_, p, d) = step(p, d) || EDGES[id(p) - d].then { [origin(_1) + clamp(p * _2 + d * _2 - ADJ[_2.to_c]), _2 * d] } |
|
|
|
def solve(grid, path) |
|
dir, pos = 1.to_c, grid.keys.min_by { [_1.imag, _1.real] } |
|
|
|
path.scan(/\d+|[LR]/) do |match| |
|
dir *= {?L => -1i, ?R => 1i}.fetch(match, 1) |
|
match.to_i.times.lazy.take_while { grid[yield(pos, dir)[0]] != '#' }.each { pos, dir = yield pos, dir } |
|
end |
|
|
|
1000 * pos.imag.succ + 4 * pos.real.succ + [1, 1i, -1, -1i].map(&:to_c).index(dir) |
|
end |
|
|
|
a, b = File.read('input22.txt').split(/\n\n/) |
|
grid = a.lines.flat_map.with_index { |l, x| l.chomp.chars.map.with_index { [x.i + _2, _1] }.reject { _2 == ' ' } }.to_h |
|
p solve(grid, b) { wrap(grid, _1, _2) }, solve(grid, b) { cube(grid, _1, _2) } |