diff --git a/2022/ruby/day_09.rb b/2022/ruby/day_09.rb new file mode 100644 index 0000000..15239d0 --- /dev/null +++ b/2022/ruby/day_09.rb @@ -0,0 +1,43 @@ +require "set" + +motions = ARGF.read.scan(/([RLUD])\s+(\d+)/).map { [_1, _2.to_i] } + +class Snake + attr_reader :tail + + def initialize + @head, @tail = [0, 0], [0, 0] + end + + def move!(dir) + delta = case dir + when ?L then [ 0, -1] + when ?U then [ 1, 0] + when ?R then [ 0, 1] + when ?D then [-1, 0] + else fail dir.inspect + end + @head = @head.zip(delta).map { _1 + _2 } + + delta = @head.zip(@tail).map { _1 - _2 } + if delta.any? { _1.abs > 1 } + if delta.any?(&:zero?) + @tail = @tail.zip(delta.map { _1.clamp(-1, 1) }).map { _1 + _2 } + else + @tail = @tail.zip(delta.map { _1.clamp(-1, 1) }).map { _1 + _2 } + end + end + end +end + +snake = Snake.new +seen = Set.new + +motions.each do |dir, distance| + distance.times do + snake.move!(dir) + seen << snake.tail + end +end + +p seen.size