1
1
# euler 86
2
- import math
2
+
3
+ """
4
+ Damnn this problem taught me a alotttt. Damnnnn OMfucking geeeee Damnnnn nibbazzz! figured it out mother fuckerssssss!!!!
5
+ Okay here is the theory behind the problem and how I solved it. I just needed to sit in a place and think properly for a sec...
6
+
7
+ For any triple P Q R, where P < Q <R; we wanna express P and Q as (a,b,c) such that a<=b<=c
8
+
9
+ Now, the shortest dist pair will be sqrt((a+b)**2+ c**2) because of our condition. So we don't really have to compute the distance as long
10
+ as abc are sorted.
11
+
12
+ if P & Q are less than the upper limit M:
13
+ P can be expressed as: (a+b) and Q can be c
14
+ or similarly
15
+ P can be expressed as a and Q can be expressed as (b+c)
16
+ for P, we can express a total of floor(P/2) unique splits
17
+ and for Q we can express a total of floor(Q/2) unique splits
18
+
19
+ but for Q we have to aware of a condition where, the splits of Q are smaller than P (cuz of a<=b<=c condition)
20
+ so we eliminate all pairs for Q where smallest value is greater than P.
21
+
22
+ For example:
23
+
24
+ consider the triple (P,Q,R) == (6,8,10)
25
+
26
+ P can be split into a total of floor(P/2) ways (3 ways):
27
+ (1, 5)
28
+ (2, 4)
29
+ (3, 3)
30
+
31
+ then pick any pair and it will satisfy the condition of:
32
+ (a+b)**2+c**2 = R**2
33
+ (1+5)**2+8**2 = 10**2
34
+
35
+ But for splits of Q, we can see:
36
+ (1,7) --> (1,7,6) (a<=b<=c fails here)
37
+ (2,6) --> (2,6,6) a<=b<=c
38
+ (3,5) --> (3,5,6) a<=b<=c
39
+ (4,4) --> (4,4,6) a<=b<=c
40
+
41
+ So we can't split Q as 1,7 as that will violate the condition.
42
+ To count that out it is easy to see that No.of ways to skip = Q-P-1
43
+
44
+ in this case it is: 8-6-1 = 1
45
+ so total ways for Q = floor(Q/2)-(Q-P-1) = (8/2)-(1) = 3
46
+
47
+ SO total unique pairs that can be generated for (6,8,10) is 3(for P) + 3(forQ) = 6
48
+
49
+ if Q-P-1 <0 then don't count Q at all
50
+ """
3
51
import time
4
- import operator as op
5
- from functools import reduce
6
- from itertools import combinations
7
-
8
- # a smarter distance func
9
- dist2 = lambda s : math .sqrt (s )
10
-
11
- # spider is at start of a
12
- # fly is at the end of c
13
- # square lookup:
14
- square_lookup = {}
15
- familiar_pair = {}
16
- familiar_combinations = {}
17
- seen_results = {}
18
- def shortest_dist2 (a , b , c ):
19
- if a not in square_lookup :
20
- square_lookup [a ] = a ** 2
21
- if b not in square_lookup :
22
- square_lookup [b ] = b ** 2
23
- if c not in square_lookup :
24
- square_lookup [c ] = c ** 2
25
- base = square_lookup [c ]+ square_lookup [b ]+ square_lookup [a ]
26
- s1 = base + (2 * b * c )
27
- s2 = base + (2 * a * c )
28
- s3 = base + (2 * a * b )
29
- if s1 not in familiar_pair :
30
- familiar_pair [s1 ] = dist2 (s1 )
31
- if s2 not in familiar_pair :
32
- familiar_pair [s2 ] = dist2 (s2 )
33
- if s3 not in familiar_pair :
34
- familiar_pair [s3 ] = dist2 (s3 )
35
- p1 = familiar_pair [s1 ]
36
- p2 = familiar_pair [s2 ]
37
- p3 = familiar_pair [s3 ]
38
- return min (p1 , p2 , p3 )
39
-
40
- def ncr (n , r ):
41
- r = min (r , n - r )
42
- numer = reduce (op .mul , range (n , n - r , - 1 ), 1 )
43
- denom = reduce (op .mul , range (1 , r + 1 ), 1 )
44
- return numer // denom
45
-
46
- def dim_generator2 (M ):
47
- for i in range (1 , M + 1 ):
48
- for j in range (1 , M + 1 ):
49
- yield (i , i , j )
50
- combs = list (combinations ([i for i in range (1 ,M + 1 )], 3 ))
51
- for a ,b ,c in combs :
52
- yield (a , b , c )
52
+ def pythagoreanTriplets (limits ) :
53
+ c , m = 0 , 2
54
+ while c < limits :
55
+ for n in range (1 , m ) :
56
+ a = m * m - n * n
57
+ b = 2 * m * n
58
+ c = m * m + n * n
59
+ if c > limits :
60
+ break
61
+ yield (a , b , c )
62
+ m = m + 1
53
63
54
64
start = time .time ()
55
- seen_dims = {}
56
- total_ints = 0
57
- upper_lim = 1000000
58
- upper_lim = 1000
59
- upper_lim = 500
60
- for a ,b ,c in dim_generator2 (upper_lim ):
65
+ upper_lim = 1818
66
+
67
+ def count_combs (A , B , U ):
68
+ temp = 0
69
+ if A <= U and B <= U :
70
+ temp += int (A / 2 )
71
+ ways = B - A - 1
72
+ if (int (B / 2 )- ways )>= 0 :
73
+ temp += (int (B / 2 )- ways )
74
+ if A <= U and B > U and int (B / 2 ) <= U :
75
+ ways = B - A - 1
76
+ if (int (B / 2 )- ways )>= 0 :
77
+ temp += (int (B / 2 )- ways )
78
+ if A > U :
79
+ temp = 0
80
+ return temp
81
+
82
+ is_triples = {}
83
+ total_count = 0
84
+ xs = []
85
+ m2 = set ()
86
+ for a , b , c in pythagoreanTriplets (10000 ):
61
87
S = [a ,b ,c ]
62
88
S .sort ()
63
- dim_set = ',' .join (list (map (str ,S )))
64
- if dim_set in seen_dims :
65
- continue
66
- seen_dims [dim_set ] = True
67
- distance = shortest_dist2 (a ,b ,c )
68
- if distance .is_integer ():
69
- total_ints += 1
70
- print (total_ints )
71
-
72
- print ("finished in: " , time .time ()- start )
73
-
74
- # val = upper_lim + (upper_lim*(upper_lim-1))+ ncr(upper_lim, 3)
75
- # print(val, upper_lim**3)
76
- # the current loop generates
77
- # 1000000000000000000
78
- # when the total uniques are
79
- # 166667166667000000
80
-
89
+ for i in range (1 ,1000 ):
90
+ A ,B = i * S [0 ], i * S [1 ]
91
+ if (A ,B ) in is_triples :
92
+ continue
93
+ X = count_combs (A , B , upper_lim )
94
+ xs .append (X )
95
+ total_count += X
96
+ is_triples [A ,B ]= True
97
+ print (total_count )
98
+ print ("finished in: " , time .time ()- start )
0 commit comments