From 47b07ceb342250f2b113badae56cf456cd2b6cf8 Mon Sep 17 00:00:00 2001 From: Alpha Chen Date: Fri, 11 Dec 2020 20:54:41 -0800 Subject: [PATCH] [2020][ruby][11.x] refactor --- 2020/ruby/day_11.rb | 146 +++++++++++++++++++++++++------------------- 1 file changed, 82 insertions(+), 64 deletions(-) diff --git a/2020/ruby/day_11.rb b/2020/ruby/day_11.rb index 1328360..9930129 100644 --- a/2020/ruby/day_11.rb +++ b/2020/ruby/day_11.rb @@ -1,72 +1,90 @@ -layout = ARGF.read.split("\n").map(&:chars) -Y_MAX = layout.size -X_MAX = layout.first.size +class Layout + def self.from(raw, &logic) + seats = Hash.new + raw.split("\n").each.with_index do |row,y| + row.chars.each.with_index do |pos,x| + seats[[y,x]] = false if pos == ?L + end + end + self.new(seats, &logic) + end -# NEIGHBORS = (-1..1).flat_map {|y| (-1..1).map {|x| [y, x] }} - [[0, 0]] + attr_reader :seats, :y_max, :x_max -# def tick(layout) -# (0...Y_MAX).map {|y| -# (0...X_MAX).map {|x| -# occupied = NEIGHBORS -# .map {|dy,dx| [y+dy, x+dx] } -# .select {|y,x| (0...Y_MAX).cover?(y) && (0...X_MAX).cover?(x) } -# .select {|y,x| layout[y][x] == ?# } -# .count -# case layout[y][x] -# when ?. -# ?. -# when ?L -# occupied == 0 ? ?# : ?L -# when ?# -# occupied >= 4 ? ?L : ?# -# else -# fail -# end -# } -# } -# end + def initialize(seats, &logic) + @seats, @logic = seats, logic + @y_max = @seats.keys.map(&:first).max + @x_max = @seats.keys.map(&:last).max + end -DIRS = (-1..1).flat_map {|y| (-1..1).map {|x| [y, x] }} - [[0, 0]] + def [](yx) + @seats[yx] + end -def tick(layout) - (0...Y_MAX).map {|y| - (0...X_MAX).map {|x| - next ?. if layout[y][x] == ?. - occupied = DIRS - .map {|dy,dx| - (1..) - .lazy - .map {|i| [dy*i+y, dx*i+x] } - .map {|y,x| - if (0...Y_MAX).cover?(y) && (0...X_MAX).cover?(x) - layout[y][x] - else - nil - end - } - .find {|s| s != ?. } - } - .select {|s| s == ?# } - .count - case occupied - when 0 - ?# - when (5..) - ?L - else - layout[y][x] - end - } - } -end + def each + return enum_for(__method__) unless block_given? -loop do - next_layout = tick(layout) - break if next_layout == layout - layout = next_layout + loop do + yield self + seats = tick(&@logic) + break if seats == @seats + @seats = seats + end + end - puts layout.map(&:join).join("\n") - puts + def tick + @seats.keys.map {|yx| + [yx, @logic[self, yx]] + }.to_h + end + + def to_s + (0..@y_max).map {|y| + (0..@x_max).map {|x| + case @seats[[y,x]] + when true then ?# + when false then ?L + when nil then ?. + else fail + end + }.join + }.join("\n") + end end -p layout.map {|row| row.count(?#) }.sum +NEIGHBORS = (-1..1).flat_map {|y| (-1..1).map {|x| [y, x] }} - [[0, 0]] +day1 = ->(layout, yx) { + y, x = yx + occupied_neighbors = NEIGHBORS.filter_map {|dy,dx| layout[[y+dy, x+dx]] } + if !layout[yx] && occupied_neighbors.empty? + true + elsif layout[yx] && occupied_neighbors.size >= 4 + false + else + layout[yx] + end +} + +day2 = ->(layout, yx) { + y, x = yx + occupied_neighbors = NEIGHBORS.filter_map {|dy,dx| + (1..).lazy + .map {|i| [y+dy*i, x+dx*i] } + .find {|y,x| + !(0..layout.y_max).cover?(y) || + !(0..layout.x_max).cover?(x) || + layout.seats.has_key?([y, x]) + } + }.filter_map {|yx| layout[yx] } + if !layout[yx] && occupied_neighbors.empty? + true + elsif layout[yx] && occupied_neighbors.size >= 5 + false + else + layout[yx] + end +} + +layout = Layout.from(ARGF.read, &day2) +layout.each.take_while(&:itself).last +puts layout.seats.count(&:last)