-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.rb
149 lines (110 loc) · 3.04 KB
/
main.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
require_relative "image"
file = File.open("input.txt")
images = file.read.split("\n\n")
$complementary = {
:top => :bottom,
:right => :left,
:bottom => :top,
:left => :right
}
def assemble(images)
mosaic = [[ images[0] ]]
images = images[1..]
while images.length > 0
[:top, :bottom, :right, :left].each{ |pos|
border_images = get_border(mosaic, pos)
new_border_images = border_images.map{ |border_image|
border = get_border(border_image.view, pos)
find_match(images, border, $complementary[pos])
}
unless new_border_images.include? false
images -= new_border_images
add_border(mosaic, new_border_images, pos)
end
}
end
mosaic
end
def find_match(images, border, pos)
images.each{ |image|
return image if image.match(border, pos)
}
false
end
def mosaic_to_views(mosaic)
@view = @view
view = mosaic.map{ |row|
row.map{ |image| image.view[1..-2].map{ |row| row[1..-2] }.transpose }.inject(:+).transpose
}.flatten(1)
permutations(view)
end
def waters_roughness(views)
views.each{ |view|
monsters = count_sea_monsters(view)
return count(view, "#") - 15 * monsters if monsters > 0
}
return 0
end
def count_sea_monsters(view)
view[..-3].map.with_index { |row, j|
row[..-20].select.with_index { |char, i|
is_a_monster([
view[j][i..i+19],
view[j+1][i..i+19],
view[j+2][i..i+19]
])
}.length
}.compact.inject(:+)
end
def count(view, symbol)
view.sum{ |row| row.select{ |char| char == symbol }.length }
end
def is_a_monster(section)
monster = [
" # ",
"# ## ## ###",
" # # # # # # "
].map(&:chars)
section.each_with_index{ |row, j|
row.each_with_index{ |sqr, i|
return false unless monster[j][i] == " " || sqr == "#"
}
}
true
end
def get_borders(mosaic)
[:top, :bottom, :left, :right].map{ |pos| get_border(mosaic, pos) }
end
def get_border(mosaic, pos)
case pos
when :top
return mosaic[0]
when :bottom
return mosaic[-1]
when :right
return mosaic.map{ |row| row[-1] }
when :left
return mosaic.map{ |row| row[0] }
end
end
def add_border(mosaic, border, pos)
case pos
when :top
return mosaic.unshift(border)
when :bottom
return mosaic.push(border)
when :right
return mosaic.map.with_index{ |row, i| row.push(border[i]) }
when :left
return mosaic.map.with_index{ |row, i| row.unshift(border[i]) }
end
end
def product_of_corner_keys(mosaic)
[0, -1].repeated_permutation(2).map{ |i, j|
mosaic[i][j].id
}.inject(:*)
end
images.map!{ |image| Image.new(image) }
mosaic = assemble(images)
puts "Part 1: " + product_of_corner_keys(mosaic).to_s
puts "Part 2: " + waters_roughness(mosaic_to_views(mosaic)).to_s