-
Notifications
You must be signed in to change notification settings - Fork 0
/
12_3.jl
230 lines (190 loc) · 7.39 KB
/
12_3.jl
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
#!/usr/bin/env julia
"""
https://adventofcode.com/2019/day/3
"""
# In hindsight, instead of storing points as NamedTuples I could have just created a Point type, which would have made array declarations a lot easier
function calc_manhattan_distance(point)
origin_x = 0
origin_y = 0
distance = abs(origin_x - point.x) + abs(origin_y - point.y)
return distance
end
function calc_min_manhattan_distance(intersections)
# 'min' processes arguments, 'minimum' processes in iterative function
return minimum(map(x -> calc_manhattan_distance(x), intersections))
end
function calc_num_steps(coords1, coords2, x, y, ind1, ind2)
# 'x' and 'y' are the coordinates of the intersection found
# ind1 is the last coord-1 position index before the intersection
# ind2 is the same index for coord-2 array
total_x = coords1[1].x
total_y = coords1[1].y
total_u = coords2[1].x
total_v = coords2[1].y
for i in 1:ind1-1
x1 = coords1[i].x
x2 = coords1[i+1].x
y1 = coords1[i].y
y2 = coords1[i+1].y
# Could have parsed the directions array instead of getting the 'delta' of coordinate points
# but would still have needed to coordinate point before the intersection
total_x += abs(x2 - x1)
total_y += abs(y2 - y1)
end
total_x += abs(x - coords1[ind1].x)
total_y += abs(y - coords1[ind1].y)
for j in 1:ind2-1
u1 = coords2[j].x
u2 = coords2[j+1].x
v1 = coords2[j].y
v2 = coords2[j+1].y
total_u += abs(u2 - u1)
total_v += abs(v2 - v1)
end
total_u += abs(x - coords2[ind2].x)
total_v += abs(y - coords2[ind2].y)
total_steps = total_u + total_v + total_x + total_y
return total_steps
end
function create_coordinates_from_directions(directions)
coords = [(x=0, y=0)]
for dir in directions
if dir[1] == 'U'
push!(coords, move_up(coords[end], dir))
elseif dir[1] == 'D'
push!(coords, move_down(coords[end], dir))
elseif dir[1] == 'L'
push!(coords, move_left(coords[end], dir))
else # is R
push!(coords, move_right(coords[end], dir))
end
end
return coords
end
function find_intersections(coords1, coords2)
intersection_points = NamedTuple{(:x, :y),Tuple{Int,Int}}[]
for i in 1:length(coords1)-1, j in 1:length(coords2)-1
# Collect two sets of coords for each set
x1 = min(coords1[i].x, coords1[i+1].x)
x2 = max(coords1[i].x, coords1[i+1].x)
y1 = min(coords1[i].y, coords1[i+1].y)
y2 = max(coords1[i].y, coords1[i+1].y)
u1 = min(coords2[j].x, coords2[j+1].x)
u2 = max(coords2[j].x, coords2[j+1].x)
v1 = min(coords2[j].y, coords2[j+1].y)
v2 = max(coords2[j].y, coords2[j+1].y)
# After every movement, one axis will be unchanged
# For an intersection, the other coord set's opposite axis will be unchanged
if x1 == x2
# Movement of coordinate 1 was vertical
# ...so coordinate 2 needs to be horizontal
if v1 == v2
if u1 <= x1 <= u2 && y1 <= v1 <= y2
push!(intersection_points, (x=x1, y=v1))
end
end
elseif y1 == y2
# Movement of coordinate 1 was horizontal
# ...so coordinate 2 needs to be vertical
if u1 == u2
if v1 <= y1 <= v2 && x1 <= u1 <= x2
push!(intersection_points, (x=u1, y=y1))
end
end
end
end
return intersection_points
end
function find_min_num_steps_to_intersections(coords1, coords2)
min_num_steps = Inf # Start at Infinty
for i in 1:length(coords1)-1, j in 1:length(coords2)-1
# Collect two sets of coords for each set
x1 = min(coords1[i].x, coords1[i+1].x)
x2 = max(coords1[i].x, coords1[i+1].x)
y1 = min(coords1[i].y, coords1[i+1].y)
y2 = max(coords1[i].y, coords1[i+1].y)
u1 = min(coords2[j].x, coords2[j+1].x)
u2 = max(coords2[j].x, coords2[j+1].x)
v1 = min(coords2[j].y, coords2[j+1].y)
v2 = max(coords2[j].y, coords2[j+1].y)
# After every movement, one axis will be unchanged
# For an intersection, the other coord set's opposite axis will be unchanged
if x1 == x2
# Movement of coordinate 1 was vertical
# ...so coordinate 2 needs to be horizontal
if v1 == v2
if u1 <= x1 <= u2 && y1 <= v1 <= y2
num_steps = calc_num_steps(coords1, coords2, x1, v1, i, j)
min_num_steps = min(min_num_steps, num_steps)
end
end
elseif y1 == y2
# Movement of coordinate 1 was horizontal
# ...so coordinate 2 needs to be vertical
if u1 == u2
if v1 <= y1 <= v2 && x1 <= u1 <= x2
num_steps = calc_num_steps(coords1, coords2, u1, y1, i, j)
min_num_steps = min(min_num_steps, num_steps)
end
end
end
end
return min_num_steps
end
function move_down(coordinate, dir)
num_steps = parse(Int, dir[2:end])
return (x=coordinate.x, y=coordinate.y - num_steps)
end
function move_left(coordinate, dir)
num_steps = parse(Int, dir[2:end])
return (x=coordinate.x - num_steps, y=coordinate.y)
end
function move_right(coordinate, dir)
num_steps = parse(Int, dir[2:end])
return (x=coordinate.x + num_steps, y=coordinate.y)
end
function move_up(coordinate, dir)
num_steps = parse(Int, dir[2:end])
return (x=coordinate.x, y=coordinate.y + num_steps)
end
function parse_line(line)
line = chomp(line) # Knew julia had 'strip' but didn't know it had 'chomp' as well :-)
return split(line, ",")
end
function main1()
input_file = joinpath(pwd(), "files", "12_3_input.txt")
lines = readlines(open(input_file, "r"))
directions1 = parse_line(lines[1])
directions2 = parse_line(lines[2])
# Test cases
#directions1 = parse_line("R75,D30,R83,U83,L12,D49,R71,U7,L72")
#directions2 = parse_line("U62,R66,U55,R34,D71,R55,D58,R83")
# Array of named tuples
# Coordinates will be based on current position after processing a direction
coords1 = create_coordinates_from_directions(directions1)
coords2 = create_coordinates_from_directions(directions2)
intersection_points = find_intersections(coords1, coords2)
min_distance = calc_min_manhattan_distance(intersection_points)
println("Part 1 answer:")
@show min_distance
end
function main2()
input_file = joinpath(pwd(), "files", "12_3_input.txt")
lines = readlines(open(input_file, "r"))
directions1 = parse_line(lines[1])
directions2 = parse_line(lines[2])
# Test cases
#directions1 = parse_line("R75,D30,R83,U83,L12,D49,R71,U7,L72")
#directions2 = parse_line("U62,R66,U55,R34,D71,R55,D58,R83")
#directions1 = parse_line("R98,U47,R26,D63,R33,U87,L62,D20,R33,U53,R51")
#directions2 = parse_line("U98,R91,D20,R16,D67,R40,U7,R15,U6,R7")
# Array of named tuples
# Coordinates will be based on current position after processing a direction
coords1 = create_coordinates_from_directions(directions1)
coords2 = create_coordinates_from_directions(directions2)
min_num_steps = find_min_num_steps_to_intersections(coords1, coords2)
println("Part 2 answer:")
@show min_num_steps
end
main1()
main2()