-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathproblem86.rb
More file actions
73 lines (66 loc) · 1.66 KB
/
problem86.rb
File metadata and controls
73 lines (66 loc) · 1.66 KB
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
require 'euler_helper.rb'
require 'mathn'
def variants(x, y, bound) #for each pyphagorean triplet there are some cuboids with 1) integer shortest path 2) a,b,c < M
x, y = [x,y].sort
count = 0
c = x # a+b > c
for a in y-c..y/2
count +=1 if a <= bound && y-a <= bound && c <= bound
end
c = y # a+b < c
for a in 1..x/2
count +=1 if a <= bound && x-a <= bound && c <= bound
end
count
end
def pyth_triplet m,n
[m**2 - n**2, 2*m*n, m**2 + n**2]
end
def pyphagorean_triplets bound
result = []
b = bound / 4
(2..b).each do |m|
(1...m).each do |n|
next unless m.gcd(n) == 1
result.push pyth_triplet(m, n).sort
end
end
result.select {|triplet| triplet[0] <= bound && triplet[1] <= (bound * 2)}
end
def derivative_triplets base_triplets, bound
condition = lambda {|triplet| triplet[0] <= bound && triplet[1] <= bound * 2}
result = []
base_triplets.each do |triplet|
i = 2
tr = triplet.map {|a| a*i}
while condition.call(tr)
result.push tr
i += 1
tr = triplet.map {|a| a*i}
end
end
result + base_triplets
end
def count_cuboids m
triplets = derivative_triplets(pyphagorean_triplets(m), m).uniq
variants = triplets.inject(0) {|memo, triplet| memo += variants(triplet[0], triplet[1], m)}
variants
end
def bisect fun, target, start, eend
while eend - start > 1
puts "step "+[start,eend].inspect
testpoint = ((start+eend) / 2).to_i
res = send(fun,testpoint)
if res < target
start = testpoint
elsif res > target
eend = testpoint
else
return testpoint
end
end
return start
end
benchmark do
puts bisect(:count_cuboids, 1000000, 1, 2500).inspect
end