From e008591ae70bf5beada8f1f666c846a9792e311c Mon Sep 17 00:00:00 2001 From: Alpha Chen Date: Tue, 25 Dec 2018 17:02:55 -0700 Subject: [PATCH] [2018][ruby][18.1] --- 2018/ruby/day_18.rb | 233 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 233 insertions(+) create mode 100644 2018/ruby/day_18.rb diff --git a/2018/ruby/day_18.rb b/2018/ruby/day_18.rb new file mode 100644 index 0000000..136a5c9 --- /dev/null +++ b/2018/ruby/day_18.rb @@ -0,0 +1,233 @@ +require "minitest" +require "minitest/pride" + +class Area + def self.parse(input) + acres = input.chomp.lines.map {|row| row.chomp.chars.to_a } + new(acres) + end + + attr_reader :acres + + def initialize(acres) + @acres = acres + end + + def changes + return enum_for(__method__) unless block_given? + + loop do + yield self + + acres = @acres.map.with_index {|row, y| + row.map.with_index {|acre, x| + adjacent = self.adjacent(x, y) + case self[x, y] + when ?. + (adjacent.count(?|) >= 3) ? ?| : ?. + when ?| + (adjacent.count(?#) >= 3) ? ?# : ?| + when ?# + (adjacent.count(?#) >= 1 && adjacent.count(?|) >= 1) ? ?# : ?. + else + fail "Unexpected acre: #{self[x, y]}" + end + } + } + @acres = acres + end + end + + def to_s + @acres.map {|row| row.join }.join(?\n) + end + + def [](x, y) + @acres.fetch(y).fetch(x) + end + + def adjacent(x, y) + (-1..1).flat_map {|dx| (-1..1).map {|dy| [dx, dy] } } + .reject {|dx,dy| dx == 0 && dy == 0 } + .map {|dx, dy| [x+dx, y+dy] } + .reject {|x, y| x < 0 || y < 0 } + .map {|x, y| + @acres.fetch(y) { [] }.fetch(x) { nil } + }.compact + end +end + +class TestArea < Minitest::Test + def test_area + area = Area.parse(<<~AREA) + .#.#...|#. + .....#|##| + .|..|...#. + ..|#.....# + #.#|||#|#| + ...#.||... + .|....|... + ||...#|.#| + |.||||..|. + ...#.|..|. + AREA + changes = area.changes + + assert_equal <<~AREA.chomp, changes.next.to_s + .#.#...|#. + .....#|##| + .|..|...#. + ..|#.....# + #.#|||#|#| + ...#.||... + .|....|... + ||...#|.#| + |.||||..|. + ...#.|..|. + AREA + + assert_equal <<~AREA.chomp, changes.next.to_s + .......##. + ......|### + .|..|...#. + ..|#||...# + ..##||.|#| + ...#||||.. + ||...|||.. + |||||.||.| + |||||||||| + ....||..|. + AREA + + assert_equal <<~AREA.chomp, changes.next.to_s + .......#.. + ......|#.. + .|.|||.... + ..##|||..# + ..###|||#| + ...#|||||. + |||||||||. + |||||||||| + |||||||||| + .||||||||| + AREA + + assert_equal <<~AREA.chomp, changes.next.to_s + .......#.. + ....|||#.. + .|.||||... + ..###|||.# + ...##|||#| + .||##||||| + |||||||||| + |||||||||| + |||||||||| + |||||||||| + AREA + + assert_equal <<~AREA.chomp, changes.next.to_s + .....|.#.. + ...||||#.. + .|.#||||.. + ..###||||# + ...###||#| + |||##||||| + |||||||||| + |||||||||| + |||||||||| + |||||||||| + AREA + + assert_equal <<~AREA.chomp, changes.next.to_s + ....|||#.. + ...||||#.. + .|.##||||. + ..####|||# + .|.###||#| + |||###|||| + |||||||||| + |||||||||| + |||||||||| + |||||||||| + AREA + + assert_equal <<~AREA.chomp, changes.next.to_s + ...||||#.. + ...||||#.. + .|.###|||. + ..#.##|||# + |||#.##|#| + |||###|||| + ||||#||||| + |||||||||| + |||||||||| + |||||||||| + AREA + + assert_equal <<~AREA.chomp, changes.next.to_s + ...||||#.. + ..||#|##.. + .|.####||. + ||#..##||# + ||##.##|#| + |||####||| + |||###|||| + |||||||||| + |||||||||| + |||||||||| + AREA + + assert_equal <<~AREA.chomp, changes.next.to_s + ..||||##.. + ..|#####.. + |||#####|. + ||#...##|# + ||##..###| + ||##.###|| + |||####||| + ||||#||||| + |||||||||| + |||||||||| + AREA + + assert_equal <<~AREA.chomp, changes.next.to_s + ..||###... + .||#####.. + ||##...##. + ||#....### + |##....##| + ||##..###| + ||######|| + |||###|||| + |||||||||| + |||||||||| + AREA + + assert_equal <<~AREA.chomp, changes.next.to_s + .||##..... + ||###..... + ||##...... + |##.....## + |##.....## + |##....##| + ||##.####| + ||#####||| + ||||#||||| + |||||||||| + AREA + end +end + +def solve(input) + area = Area.parse(input) + area = area.changes.lazy.drop(10).first + wooded = area.acres.flat_map(&:itself).count(?|) + lumberyards = area.acres.flat_map(&:itself).count(?#) + wooded * lumberyards +end + +if __FILE__ == $0 + require "minitest/autorun" and exit if ENV["TEST"] + + puts solve(ARGF.read) +end