aoc_omni/ruby/2016/8/problem.rb
2025-08-07 06:20:08 -04:00

218 lines
3.0 KiB
Ruby

class Command
def self.for(line)
if line.split.first == "rect"
RectCommand
elsif line.split[1] == "row"
RotateRowCommand
elsif line.split[1] == "column"
RotateColumnCommand
end.new line
end
end
class RectCommand < Command
attr_reader :width, :height
def initialize(line)
@width, @height = line.split.last.split("x").map(&:to_i)
end
def apply(screen)
screen.rect!(width, height)
end
end
class RotateRowCommand < Command
attr_reader :row, :by
def initialize(line)
@row = line.split[2].split("=")[1].to_i
@by = line.split[4].to_i
end
def apply(screen)
screen.rotate_row!(row, by)
end
end
class RotateColumnCommand < Command
attr_reader :column, :by
def initialize(line)
@column = line.split[2].split("=")[1].to_i
@by = line.split[4].to_i
end
def apply(screen)
screen.rotate_column!(column, by)
end
end
class Screen
attr_reader :pixels
def initialize
@pixels = Array.new(height) { Array.new(width, " ") }
end
def width
50
end
def height
6
end
def rect!(width, height)
width.times { |x| height.times { |y| pixels[y][x] = "#" } }
end
def rotate_row!(row, by)
by.times { rotate_row_once! row }
end
def rotate_row_once!(row)
last = pixels[row].pop
pixels[row].unshift(last)
end
def rotate_column!(column, by)
by.times { rotate_column_once! column }
end
def rotate_column_once!(column)
last = pixels[height - 1][column]
(height - 1).downto(1) do |y|
pixels[y][column] = pixels[y - 1][column]
end
pixels[0][column] = last
end
def print
puts pixels.map(&:join)
end
def lit_pixel_count
pixels.flatten.count { |pixel| pixel == "#" }
end
end
class ScreenLetter
attr_reader :pixels
def initialize(screen, position)
@pixels = screen.pixels.map { |line| line.slice(position * 5, 5) }
end
def print
puts pixels.map(&:join)
puts " "
end
def to_s
pixels.map(&:join).join("\n").to_s
end
def letter_value
case to_s
when LETTER_E.chomp
"E"
when LETTER_F.chomp
"F"
when LETTER_Y.chomp
"Y"
when LETTER_K.chomp
"K"
when LETTER_R.chomp
"R"
when LETTER_I.chomp
"I"
when LETTER_J.chomp
"J"
else
"?"
end
end
end
LETTER_E = <<-E
####
#
###
#
#
####
E
LETTER_F = <<-F
####
#
###
#
#
#
F
LETTER_Y = <<-Y
# #
# #
# #
#
#
#
Y
LETTER_K = <<-K
# #
# #
##
# #
# #
# #
K
LETTER_R = <<-R
###
# #
# #
###
# #
# #
R
LETTER_I = <<-I
###
#
#
#
#
###
I
LETTER_J = <<-J
##
#
#
#
# #
##
J
input = STDIN.read.chomp
commands = input.split("\n").map { |line| Command.for line }
screen = Screen.new
commands.each { |command| command.apply screen }
part_1 = screen.lit_pixel_count
puts "Part 1: #{part_1}"
letters = 0.upto(9).map do |position|
ScreenLetter.new screen, position
end
part_2 = letters.map(&:letter_value).join
puts "Part 2: #{part_2}"