-
Notifications
You must be signed in to change notification settings - Fork 0
/
11.rb
151 lines (132 loc) · 3.82 KB
/
11.rb
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
testing = false
file_name = testing ? 'input11_test.txt' : 'input11.txt'
file = open(file_name).readlines
def to_numeric_row(str_row)
str_row.split('').each do |single_char|
puts single_char
end
end
class Seat
attr_accessor :adjacent_seats, :row_position, :col_position
attr_reader :occupied
def initialize(str_value)
@occupied = 0
@usable = str_value.eql?('L') ? 1 : 0
@adjacent_seats = []
@next_round = 0
@row_position = 0
@col_position = 0
end
def to_s
if @usable.eql?(1)
@occupied.eql?(1) ? '#' : 'L'
else
'.'
end
end
def to_i
@occupied
end
def +(other)
@occupied + other.occupied
end
def coerce(other)
[other.to_i, @occupied]
end
def calc_next_round
case @adjacent_seats.sum
when 0
@next_round = 1 * @usable
when 5..10
@next_round = 0
else
@next_round = @occupied
end
end
def update
@occupied = @next_round
end
def stable?
@occupied.eql? @next_round
end
def usable?
@usable.eql?(1)
end
end
class SeatingGrid
def initialize(seating_map)
@seating_rows = []
seating_map.each do |r|
@seating_rows << r.gsub("\n", "").split('').map{|e| Seat.new(e)}
end
@width = @seating_rows[0].length
@height = @seating_rows.length
# @seating_rows.each_index { |r_idx| @seating_rows[r_idx].each_index { |c_idx| surrounding_seats(r_idx, c_idx)}}
@seating_rows.each_index { |r_idx| @seating_rows[r_idx].each_index { |c_idx| visible_seats(r_idx, c_idx)}}
end
def to_s
@seating_rows.map { |r| r.join('') }.join("\n")
end
def surrounding_seats(r_idx, c_idx)
@seating_rows[r_idx][c_idx].row_position = r_idx
@seating_rows[r_idx][c_idx].col_position = c_idx
3.times do |r_id_2|
3.times do |c_id_2|
adjacent_row = r_idx + r_id_2 - 1
adjacent_col = c_idx + c_id_2 - 1
if (adjacent_row).between?(0, @height - 1) and (adjacent_col).between?(0, @width - 1)
unless r_id_2.eql?(1) and c_id_2.eql?(1)
@seating_rows[r_idx][c_idx].adjacent_seats << @seating_rows[adjacent_row][adjacent_col]
end
end
end
end
end
def visible_seats(r_idx, c_idx)
@seating_rows[r_idx][c_idx].row_position = r_idx
@seating_rows[r_idx][c_idx].col_position = c_idx
3.times do |r_id_2|
3.times do |c_id_2|
direction_row = r_id_2 - 1
direction_col = c_id_2 - 1
distance = 1
unless direction_row.eql?0 and direction_col.eql? 0
adjacent_row = r_idx + distance * direction_row
adjacent_col = c_idx + distance * direction_col
while (adjacent_row).between?(0, @height - 1) and (adjacent_col).between?(0, @width - 1) and
not @seating_rows[adjacent_row][adjacent_col].usable?
distance += 1
adjacent_row = r_idx + distance * direction_row
adjacent_col = c_idx + distance * direction_col
end
if (adjacent_row).between?(0, @height - 1) and (adjacent_col).between?(0, @width - 1)
@seating_rows[r_idx][c_idx].adjacent_seats << @seating_rows[adjacent_row][adjacent_col]
end
end
end
end
end
def calc_next_round
@seating_rows.each { |r| r.each { |s| s.calc_next_round}}
end
def update_seats
@seating_rows.each { |r| r.each { |s| s.update}}
end
def stabilized?
@seating_rows.map { |row| row.map { |seat| seat.stable?}.all?}.all?
end
def total_seats
@seating_rows.map { |row| row.sum}.sum
end
end
seating_matrix = SeatingGrid.new(file)
puts seating_matrix
seating_matrix.calc_next_round
idx = 0
until seating_matrix.stabilized? do
puts seating_matrix
seating_matrix.update_seats
puts "\n\n---update round #{idx += 1}---\n\n"
seating_matrix.calc_next_round
end
puts "total number of occupied seats: #{seating_matrix.total_seats}"