218 lines
3.0 KiB
Ruby
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}"
|