[2020][ruby][11.x] refactor

pull/2/head
Alpha Chen 4 years ago
parent 77256e1bf8
commit 47b07ceb34

@ -1,72 +1,90 @@
layout = ARGF.read.split("\n").map(&:chars) class Layout
Y_MAX = layout.size def self.from(raw, &logic)
X_MAX = layout.first.size 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
attr_reader :seats, :y_max, :x_max
def initialize(seats, &logic)
@seats, @logic = seats, logic
@y_max = @seats.keys.map(&:first).max
@x_max = @seats.keys.map(&:last).max
end
# NEIGHBORS = (-1..1).flat_map {|y| (-1..1).map {|x| [y, x] }} - [[0, 0]] def [](yx)
@seats[yx]
end
def each
return enum_for(__method__) unless block_given?
# def tick(layout) loop do
# (0...Y_MAX).map {|y| yield self
# (0...X_MAX).map {|x| seats = tick(&@logic)
# occupied = NEIGHBORS break if seats == @seats
# .map {|dy,dx| [y+dy, x+dx] } @seats = seats
# .select {|y,x| (0...Y_MAX).cover?(y) && (0...X_MAX).cover?(x) } end
# .select {|y,x| layout[y][x] == ?# } end
# .count
# case layout[y][x]
# when ?.
# ?.
# when ?L
# occupied == 0 ? ?# : ?L
# when ?#
# occupied >= 4 ? ?L : ?#
# else
# fail
# end
# }
# }
# end
DIRS = (-1..1).flat_map {|y| (-1..1).map {|x| [y, x] }} - [[0, 0]] def tick
@seats.keys.map {|yx|
[yx, @logic[self, yx]]
}.to_h
end
def tick(layout) def to_s
(0...Y_MAX).map {|y| (0..@y_max).map {|y|
(0...X_MAX).map {|x| (0..@x_max).map {|x|
next ?. if layout[y][x] == ?. case @seats[[y,x]]
occupied = DIRS when true then ?#
.map {|dy,dx| when false then ?L
(1..) when nil then ?.
.lazy else fail
.map {|i| [dy*i+y, dx*i+x] } end
.map {|y,x| }.join
if (0...Y_MAX).cover?(y) && (0...X_MAX).cover?(x) }.join("\n")
layout[y][x] end
end
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 else
nil layout[yx]
end end
} }
.find {|s| s != ?. }
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])
} }
.select {|s| s == ?# } }.filter_map {|yx| layout[yx] }
.count if !layout[yx] && occupied_neighbors.empty?
case occupied true
when 0 elsif layout[yx] && occupied_neighbors.size >= 5
?# false
when (5..)
?L
else else
layout[y][x] layout[yx]
end end
} }
}
end
loop do
next_layout = tick(layout)
break if next_layout == layout
layout = next_layout
puts layout.map(&:join).join("\n")
puts
end
p layout.map {|row| row.count(?#) }.sum layout = Layout.from(ARGF.read, &day2)
layout.each.take_while(&:itself).last
puts layout.seats.count(&:last)

Loading…
Cancel
Save