-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday9.rb
152 lines (110 loc) · 3.03 KB
/
day9.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
class Location
attr_reader :name
attr_reader :distances
def initialize(name)
@name = name
@distances = {}
end
def distance_to(location)
@distances[location]
end
def set_distance_to(location, distance)
@distances[location] = distance
end
def hash
@name.hash
end
def eql?(other)
self == other
end
def ==(other)
@name == other.name
end
def to_s
@name
end
end
class Route
attr_accessor :visited
def initialize
@visited = []
end
def not_visited(location)
!@visited.include?(location)
end
def visit(location)
@visited << location
return self
end
def distance
total = 0
for i in 0...@visited.length - 1
total += @visited[i].distance_to(@visited[i+1])
end
total
end
def to_s
@visited.map{|l|l.name}.join(" => ") + " = #{distance}"
end
def copy
route = Route.new
route.visited = @visited.dup
route
end
end
class Processor
attr_reader :locations
def initialize
@locations = {}
end
def get_location(name)
location = @locations[name]
if (!location)
location = Location.new(name)
@locations[name] = location
end
location
end
def process(input)
input.each do |line|
match = line.match(/(\w+) to (\w+) = (\d+)/)
all, start, finish, distance = match.to_a
start_location = get_location(start)
end_location = get_location(finish)
start_location.set_distance_to(end_location, distance.to_i)
end_location.set_distance_to(start_location, distance.to_i)
end
routes
end
def routes
#setup
routes = []
@locations.values.each do |loc|
r = Route.new
routes << r.visit(loc)
end
new_routes = routes
final_routes = routes
while (new_routes.length != 0)
final_routes = new_routes
new_routes = perform_visits(final_routes)
end
puts "Day 9 part 1: #{ final_routes.sort_by{|r|r.distance}.first}"
puts "Day 9 part 2: #{ final_routes.sort_by{|r|r.distance}.last}"
end
def perform_visits(input_routes)
new_routes = []
input_routes.each do |r|
r.visited.last.distances.keys.each do |available_loc|
if (r.not_visited(available_loc))
new_routes << r.copy.visit(available_loc)
end
end
end
#puts "routes:#{input_routes.size} -> new routes:#{new_routes.size}"
new_routes
end
end
input = File.new("input9.txt").readlines.map{|l|l.strip}
p = Processor.new
p.process(input)