Re: A Sunday Programming Challenge Message #40 Posted by C.Ret on 15 Mar 2012, 10:19 a.m., in response to message #24 by Allen
I am really glad to learn that my first approach doesn’t below to the first naïve category and is consider as ‘reduce naïve’.
Because, in my point of view, my first code is really a “brute force scan”, since very few optimization in the search strategy is done.
Two loops imbedded.
By luck the outer one scan step by step on a which is fortunately the shortest side of the triangle, make it walk trough it as short as possible because limited to (P/3) ! How Lucky I am here!
On the other hand, the inner loop (which will weight much more of the time to find the solution) is far for a good optimization. Despite the two exit tests which appropriately short-cut the long b walk through, the worst in my code is that at b is scan step by step (only increase by one). Here I am bad.
This bad strategy is perhaps not a shame for small perimeter, but will be a disaster for larger perimeter.
As a lot of Euler problems, here a more tricky strategy have to be take into account, to avoid this very long systematic scans of “brute force like” algorithm.
There must be a way to scan over a only, not over b !
What are the constraints:
(1) Sorted Sides: a <= b <= c
(2) Being a triangle c <= a + b
Since other inequalities are both verified:
Due to a < b we get a <= b + n whatever is the natural integer n.
Due to initial condition (1) b <= c so we get b <= c + n for any natural integer n, thus b <= c +a.
As long as initial condition (1) is respected, we only have to care about c <= a + b
(3) Limited perimeter a+b+c <= P
As Marcus Von Cube pointed it out, this constraint has to be tested. But generally it is less constringent than (2).
(4) Specific condition: b2 = a.c
Here is the key to reduce
Suppose that b decompose into the following product of primary factors : b1, b2, b3…
With b = b1. b2. b3… then (4) implies that a and c are both a subset of the primary factors of b.
To illustrate that, investigate all the triplets (a,b,c) that verify (4). Only a fraction of this list of triplets corresponds to constraints (1) (2) and (3):
Looking for triangle P<=100
b = 2 x 2 x 3 = 12 scanning all (a,c) pairs built up table 1:
TABLE 1:
========
a b c P=a+b+c Violate constraints
----- ---- ---- --------- ------------------------------------------
1 12 144 157 (2)(3) Not a triangle + P Too large
2 12 72 86 (2) Not a triangle
3 12 48 63 (2) Not a triangle
4 12 36 52 (2) Not a triangle
6 12 24 42 (2) Not a triangle
8 12 18 38 Ok n°1
9 12 16 37 Ok n°2
12 12 12 36 Ok n°3
16 12 9 37 (1) a b c not sorted
18 12 8 38 (1) a b c not sorted
24 12 6 42 (1) a b c not sorted
36 12 4 52 (1) a b c not sorted
48 12 3 63 (1) a b c not sorted
72 12 2 86 (1) a b c not sorted
144 12 1 157 (1)(3) a b c not sorted + Too large P
----- ---- ---- --------- ------------------------------------------
We can observe :
- the symmetry role of a and c, scanning over a or c is equivalent.
- half of the triplet have a>b (i.e. c<b), scan can be reduce considerably (for example by only scanning over a from 1 to b)
- not every avalue have to be scan.
In fact, only value of a composed using a subset of the primary factor from b2 :
Table 2 :
=========
b = 2 x 2 x 3 b.b = 2 x 2 x 2 x 2 x 3 x 3
------------------------- ------------------------------
a = 1 c = 2 x 2 x 2 x 2 x 3 x 3 = 144
a = 2 c = 2 x 2 x 2 x 3 x 3 = 72
a = 3 c = 2 x 2 x 2 x 2 x 3 = 48
a = 2 x 2 c = 2 x 2 x 3 x 3 = 36
a = 2 x 3 c = 2 x 2 x 2 x 3 = 24
a = 2 x 2 x 2 c = 2 x 3 x 3 = 18
a = 3 x 3 c = 2 x 2 x 2 x 2 = 16
a = 2 x 2 x 3 c = 2 x 2 x 3 = 12
...
This prove that scanning step by step over a or b is not the trickiest way to look for such triangle.
This suggest that an algorithm based on combination of a prime factors decomposition of bcan be more adapt to this Week-End challenge.
On the other hands, having to scan over the smallest side a will be much simpler and allow the uses of short-cut tests. I am on the way thinking that investigating how to built the correct b side from a given a under constrains (1) to (4) will be an elegant and surely efficient method.
Of course, the over-head need to analyze a and built up b will only be benefic for scanning over large Perimeter and large side. But the great interest would be that no more inner loop over b will be needed.
To investigate how to construct b from a given a, please consider a first example:
Looking for geometric triangle responding to constraints (1) to (4) with perimeter less or egal to P = 100.
Considering a prime :
Table 3: prime a = 7 , P <=100
=======
a b c P=a+b+c Violate constraints
----- ---- ---- --------- ------------------------------------------
7 7 7 21 none OK
7 14 28 49 (2) not a triangle (c>a+b)
7 21 63 91 (2) not a triangle
7 28 112 147 (2)(3) not a triangle & too large
7 35 175 217 (2)(3) not a triangle & too large
and so on...
----- ---- ---- --------- ------------------------------------------
Only first triplet (7,7,7) correspond to the researched geometric triangle.
As soon as the second line, triplets violate one or more constrains, so I may have stop the scan as soon.
Putting more values in the table shows how b value are build.
As a is prim, there is no combination of factors is possible, and we observe that b is multiple of a
The triplets are of the general formulae (a , k.a , a.k2) with k=1, 2, 3, ...
Now, what if a is a simple composite: a = 8
Table 4: simple composite a = 8 , P <=100
=======
a b c P=a+b+c Violate constraints
----- ---- ---- --------- ------------------------------------------
8 8 8 24 none OK
8 12 18 38 none OK
8 16 32 56 (2) not a triangle
8 20 50 78 (2) not a triangle
8 24 72 104 (2)(3) not a triangle & too large
8 28 98 134 (2)(3) not a triangle & too large
and so on...
----- ---- ---- --------- ------------------------------------------
Here, two triangles of small side 8 exist (8,8,8) and (8,12,18). Both candidates respect all the constraints.
If we consider the b set , we now observe an arithmetic suite a, a+4, a+2x4, a+3x4,…
At each rwo, we have to increase b by 4. Where come this value from?
Is there any chance that 4 is built from half of the prime factors of a ?
a = 1x2x2x2 = 8 , the delta D to use to built the set of b is D = 2x2 = 4
The triplets are of the form (a, a+D.k, c)., where k = 0, 1, 2, ....
Now, what if a is a[italic] square: [italic]a = 9
Table 5: simple composite a = 25 , P <= 100
=======
a b c P=a+b+c Violate constraints
----- ---- ---- --------- ------------------------------------------
25 25 25 75 none OK
25 30 36 91 none OK
25 35 49 109 (3) perimeter too long
25 40 64 129 (3) perimeter too long
25 45 81 151 (2)(3) not a triangle & too long
25 50 100 175 (2)(3) not a triangle & too long
25 55 121 201 (2)(3) not a triangle & too long
and so on...
----- ---- ---- --------- ------------------------------------------
At each row, b have to be increase by D = 5 (not 25). So we have to construct D as small as possible with “half” of the factors of a.
Triplets are of the form ( a2, a2+k.a, (a+k) 2).
In fact, D has to be built from each factor of a, but using only half of the multiple factors (i.e; with half to power of each factor).
Table 6: simple composite a = 42 , P <= 500
=======
a b c P=a+b+c Violate constraints
----- ---- ---- --------- ------------------------------------------
42 42 25 126 none OK
42 84 168 294 (2) not a triangle
42 126 378 546 (2)(3) nat & perimeter too long
42 168 672 882 (2)(3) nat & perimeter too long
----- ---- ---- --------- ------------------------------------------
Here a = 1x2x3x7 = 42 , and b = a + 42.k with k = 0, 1, 2, ....
This confirming that D has to be built from each factor of a, but using only half of the multiple factors (i.e; with half to power of each factor).
Table 7: Samples of D from factor decomposition of a
=======
a D | a D | a D |
----- ------------ ----- -------------|----- ------------ ----- -------------|----- ------------ ----- -------------|
1 1x1 1 | 31 1x31 31 | 61 1x61 61 |
2 1x2 2 | 32 1x2x2x2x2x2 8 = 2x2x2 | 62 1x2x31 62 = 2x31 |
3 1x3 3 | 33 1x33 33 | 63 1x63 63 |
4 1x2x2 2 = 2 | 34 1x2x17 34 = 2x17 | 64 1x2x2x2x2x2x2 8 = 2x2x2 |
5 1x5 5 | 35 1x5x7 35 = 5x7 |
6 1x2x3 6 = 2x3 | 36 1x2x13 36 = 2x2x2 |
7 1x7 7 | 37 1x37 37 |
8 1x2x2x2 4 = 2x2 | 38 1x2x19 38 = 2x19 |
9 1x3x3 3 = 3 | 39 1x3x13 39 = 3x13 |
10 1x2x5 10 = 2x5 | 40 1x2x2x2x5 20 = 2x2x5 |
11 1x11 11 | 41 1x41 41 |
12 1x2x2x3 6 = 2x3 | 42 1x2x3x7 42 = 2x3x7 |
13 1x13 13 | 43 1x42 43 |
14 1x2x7 14 = 2x7 | 44 1x2x2x11 22 = 2x11 |
15 1x3x5 15 = 3x5 | 45 1x3x3x5 15 = 3x5 |
16 1x2x2x2x2 4 = 2x2 | 46 1x2x23 46 = 2x23 |
17 1x17 17 | 47 1x47 47 |
18 1x2x3x3 6 = 2x3 | 48 1x2x2x2x2x3 12 = 2x2x3 |
19 1x19 19 | 49 1x7x7 7 = 7 |
20 1x2x2x5 10 = 2x5 | 50 1x2x5x5 10 = 2x25 |
21 1x3x7 21 = 3x7 | 51 1x3x17 51 = 3x17 |
22 1x2x11 22 = 2x11 | 52 1x2x2x13 26 = 2x13 |
23 1x23 23 | 53 1x53 53 |
24 1x2x2x2x3 12 = 2x2x3 | 54 1x2x3x3x3 18 = 2x3x3 |
25 1x5x5 5 = 5 | 55 1x5x11 55 = 5x11 |
26 1x2x13 26 = 2x13 | 56 1x2x2x2x7 28 = 2x2x7 |
27 1x3x3x3 9 = 3x3 | 57 1x3x19 57 = 3x19 |
28 1x2x2x7 14 = 2x7 | 58 1x2x29 58 = 2x29 |
29 1x29 29 | 59 1x59 59 |
30 1x2x3x5 30 = 2x3x5 | 60 1x2x2x3x5 30 = 2x3x5 |
----- ------------ ----- -------------|----- ------------ ----- -------------|
The larger is D, the more rapid is the scan. As we can see, the process (involving the two embedded loops) has a great chance to be speed-up, since most of the a value leads to D = a. Especially when a is prime.
The inner loop (the one over b) can be suppress if we found a way of forecasting at which k we have to stop because the triplet violate one (or more) constraints.
To test for constraint (2) : ( a, b, c) being a triangle, we have to test c >= a + b
From the given a value, we may get D (see table 7 above) or find a way to built D from a factors.
With such a D, we know that the triplet (a, a+k.D, c) respect (4) b2 = a.c when
b = a + k.D , therefore c = b2 / a
To test for constrinat (2), we have to express c >= a + b as a function of variable k and parameters a and D.
The inequality c >= a + b can be transform into k2.D2 + k.D.(2-a) - a2 <= 0. Resolving the corresponding quadratic equation, allow to indicate the domain of validity:
The variable have to be set from 0 up to k2 = -(a/2D).(1-V5)
To test for constraint (3) : a+b+c <=P , we may found the limit for k the same way, by expression the inequality as a function of variable k and parameters a, P and D
a+b+c <=P is transform into k2.D2 + k.D.(2+a) + 3a2-aP <= 0.
Solving the corresponding quadratic equation for k indicate that k may varie from 0 upto k3 = -(a/2D).(3-V(4P/a - 3))
This give you the way to code for a more efficient algorithm using only one loop over a :
Input P upper limit of perimeter
Initiate Sum = 0
For each integer a from 1 to P/3
Determine D ( 1 <= D <= a ) from the prime factor decomposition of a.
In most of the cases D will be equal to a
or less than a in specific cases
IF P > (3+SQR(5))*a
THEN ' Limited by triangle (2)
kl = -(a/2D)*(1-SQR(5))
ELSE ' Limited by perimeter (3)
kl = -(a/2D)*(3-SQR(4P/a - 3))
End if
There is n = INT( 1 + kl ) geometric triangles of small side [italic]a[/italic] since k = 0,1, 2, ..., kl
Sum = Sum + n Add integer n into the Sum
At end, display Sum that contains number of researched triangle of perimeter less or equal to P.
In conclusion, I leave you a few to compose you own code on your favorite calculator or system.
I curious to know how much time this new algorithm loose on shot perimeter (P = 100, 1000), and what it is win for larger size (P> 10^4).
Edited: 15 Mar 2012, 7:26 p.m. after one or more responses were posted
|