Advent of Code 2016, Day 8: Two-Factor Authentication

#ruby #advent of code 2016

Part A and B

On Day 8 we can play around with tiny LCD screen which is 50 pixels wide and 6 pixels tall. Our input contains a set of instructions that can lit some pixels. This input looks like this:

rect 3x2
rotate column x=1 by 1
rotate row y=0 by 4
rotate column x=1 by 1

Here are example outputs after performing above instructions:

###....
###....
.......

#.#....
###....
.#.....

....#.#
###....
.#.....

.#..#.#
#.#....
.#.....

In Part A we need to output how many pixels are lit after performing all instructions from the input and in Part B we need to render what’s on the LCD.

Here is my solution for both parts:

WIDTH = 50
HEIGHT = 6

data = File.readlines("8.txt", chomp: true).map do |line|
  if line =~ /rect (\d+)x(\d+)/
    captures = Regexp.last_match.captures
    [:rect, *captures.map(&:to_i)]
  elsif line =~ /rotate row y=(\d+) by (\d+)/
    captures = Regexp.last_match.captures
    [:row, *captures.map(&:to_i)]
  elsif line =~ /rotate column x=(\d+) by (\d+)/
    captures = Regexp.last_match.captures
    [:column, *captures.map(&:to_i)]
  end
end

screen = (0..(HEIGHT - 1)).map { |_| Array.new(WIDTH, false) }

def display(screen)
  screen.map do |row|
    row.map do |cell|
      cell ? "#" : "."
    end.join
  end
end

def rect(screen, x, y)
  y.times do |row|
    x.times do |column|
      screen[row][column] = true
    end
  end

  screen
end

def row(screen, y, by)
  screen[y].rotate!(-by)
  screen
end

def column(screen, x, by)
  temp = Array.new(HEIGHT, nil)
  HEIGHT.times do |row|
    temp[row] = screen[row][x]
  end
  temp.rotate!(-by)

  HEIGHT.times do |row|
    screen[row][x] = temp[row]
  end

  screen
end

def count(screen)
  screen.map do |row|
    row.select { |cell| cell }.size
  end.sum
end

data.each do |command, *arguments|
  screen = send(command, screen, *arguments)
end

puts display(screen)
puts count(screen)