-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathday-17-part2.rb
135 lines (93 loc) · 2.28 KB
/
day-17-part2.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
require 'benchmark'
require 'stringio'
require "enumerator"
file_content = File.read(File.join(__dir__, 'input.txt'))
Probe = Struct.new(:x, :y, :vx, :vy)
def within_area?((sx, sy, ex, ey), (x, y) )
x >= sx && x <= ex && y >= sy && y <= ey
end
def beyond_area?((sx, sy, ex, ey), (x, y) )
x > ex || y < sy
end
def create(vx:, vy:)
max_y = 0
Enumerator.new do |yielder|
probe = Probe.new(0, 0, vx, vy)
loop do
probe.x += probe.vx
probe.y += probe.vy
probe.vx += -1 * (probe.vx <=> 0)
probe.vy += -1
max_y = [probe.y, max_y].max
yielder << [[probe.x, probe.y], max_y]
end
end
end
class GridPrinter
def initialize
@grid = Hash.new('.')
end
def add((x,y))
puts x,y
@grid[[x, y]] = '#'
end
def create_area(sx, sy, w, h, symbol = 'T')
w.times do |y|
h.times do |x|
@grid[[sx + x, sy + y]] = "#{symbol}"
end
end
end
def width
@grid.keys.map{_1[0]}.max + 1
end
def height
@grid.keys.map{_1[1]}.max + 1
end
def print
height.times.inject([]) do |memo, y|
width.times do |x|
memo[y] ||= []
memo[y][x] = @grid[[x, y]]
memo
end
memo
end.each{puts _1.join}
end
end
def find
end
printer = GridPrinter.new
printer.create_area(20, 5, 5, 5, 'T')
def find_hit(vx, vy, target_area)
probe_trajectory = create(vx: vx, vy: vy)
last_within = nil
while (trajectory = probe_trajectory.next) do
position, max_y = trajectory
within = within_area?(target_area, position)
beyond = beyond_area?(target_area, position)
if within
return [position, [vx, vy], max_y]
end
if beyond
return nil
end
end
end
target_area = [60, -171, 94, -136]
# target_area = [20, -10, 30, -5]
# brute forced by manual tinkering
# 1. for x I used velocities that make sense (everything that does not overshoot on the first step)
# 2. for y I used the lower bounds as the minimum vy and then probed
range_x = (0..94)
range_y = (-171..170) # guessed
combinations = range_x.to_a.product(range_y.to_a)
# brute force every combination
result = combinations.inject([]) do |memo, (vx, vy)|
if hit = find_hit(vx, vy, target_area)
memo << hit[1]
end
memo
end
puts "found #{result.size}"
# result.each {puts "#{_1}"}