1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
class Screen
  attr_reader :width, :height, :pixels

  def initialize(width, height)
    @width, @height = width, height
    @pixels = Array.new(height) { Array.new(width, false) }
  end

  def to_s
    pixels.map {|row| row.map {|pixel| pixel ? ?# : ?. }.join }.join("\n")
  end

  def <<(instruction)
    case instruction
    when /rect (\d+)x(\d+)/
      $1.to_i.times do |x|
        $2.to_i.times do |y|
          pixels[y][x] = true
        end
      end
    when /rotate column x=(\d+) by (\d+)/
      col = pixels.map {|row| row[$1.to_i] }.rotate(-$2.to_i)
      pixels.each do |row|
        row[$1.to_i] = col.shift
      end
    when /rotate row y=(\d+) by (\d+)/
      row = pixels[$1.to_i].rotate(-$2.to_i)
      pixels[$1.to_i] = row
    end
  end
end

if __FILE__ == $0
  screen = Screen.new(50, 6)
  DATA.lines.each do |line|
    screen << line
  end

  puts screen
  puts screen.pixels.map {|row| row.count {|pixel| pixel }}.inject(:+)
end

require 'minitest'
# require 'minitest/autorun'

class TestScreen < Minitest::Test
  def test_screen
    screen = Screen.new(7, 3)
    assert_equal <<-PIXELS.chomp, screen.to_s
.......
.......
.......
    PIXELS

    screen << 'rect 3x2'
    assert_equal <<-PIXELS.chomp, screen.to_s
###....
###....
.......
    PIXELS

    screen << 'rotate column x=1 by 1'
    assert_equal <<-PIXELS.chomp, screen.to_s
#.#....
###....
.#.....
    PIXELS

    screen << 'rotate row y=0 by 4'
    assert_equal <<-PIXELS.chomp, screen.to_s
....#.#
###....
.#.....
    PIXELS

    screen << 'rotate column x=1 by 1'
    assert_equal <<-PIXELS.chomp, screen.to_s
.#..#.#
#.#....
.#.....
    PIXELS
  end
end

__END__