Where is my mistake? Project Euler Problem 9 - algebra, <complex>, or something else?

From: https://projecteuler.net/problem=9

"A Pythagorean triplet is a set of three natural numbers, a < b < c, for which,
a^2 + b^2 = c^2. There exists exactly one Pythagorean triplet for which a + b + c = 1000. Find the product abc."

When I first saw this problem I thought, "Wow, easy," and I know I could totally brute force it and be done in a minute, but I wanted to learn new things instead. I decided to work it out algebraically until I found some kind of inspiration. What happened is I broke the problem down to a single variable second-degree polynomial, and then thought what a terrific idea it would be to try to build a quadratic equation function that I could use in any program. I also built my first struct to utilize it. I am a little proud of the program I've written, except that it gives the wrong answer. I've gone over my algebra a few times now, and it looks fine to me. I don't know where the problem actually occurs.

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
/*
A Pythagorean triplet is a set of three natural numbers, a < b < c, for which,
a^2 + b^2 = c^2

For example, 32 + 42 = 9 + 16 = 25 = 52.

There exists exactly one Pythagorean triplet for which a + b + c = 1000.
Find the product abc.
*/

/*
If: a + b + c = 1000, and: a^2 + b^2 = c^2, then: 
						a^2 + b^2 = (1000 - a - b)^2.
Expanded:				a^2 + b^2 = (1000 - a - b) * (1000 - a - b).
Foiled:					a^2 + b^2 = 1000^2 + a^2 + b^2 - 2000a - 2000b  + 2ab.
Subracting (a^2 + b^2):		0 = 1000^2 - 2000a - 2000b + 2ab.
Dividing by -2000:			a + b - (ab / 1000) - 500 = 0. 
If b is isolated:			        b * (1 - a / 1000) = (-a + 500).
b becomes eliminated:		b * (1 - a / 1000) * (1 + 1000 / a) = (-a + 500) * (1 + 1000 / a).
Foiled:					-a - 1000 + 500 + 500'000 / a = 0.
Multiplied by -a:			a^2 + 500a -500,000 = 0.

The quadratic equation:		(-b +- (b^2 - 4 * a * c)^(1/2)) / (2 * a)

The answer asked for:	        a = 200, b = 375, c = 425, product = 31'875'000.
*/

#include <iostream>
#include <complex>
#include <math.h>
#include <locale>

// quadraticType holds positive and negative solutions for a quadratic equation
struct quadraticType {
	std::complex<double> positive;
	std::complex<double> negative;
};

quadraticType solution(std::complex<double>, std::complex<double>, std::complex<double>);

int main()
{
	std::complex<double> quadA = 1.0, quadB = 500, quadC = -500'000;
	quadraticType answerSet = solution(quadA, quadB, quadC);

	int a = static_cast<int>(answerSet.positive.real());
	int b = static_cast<int>(answerSet.negative.real());
	int c = 1000 - a - b;

	int product = a * b * c;

	std::cout.imbue(std::locale(""));
	std::cout << "Answer: " << product << std::endl;

	std::cout << std::endl;
}

quadraticType solution(std::complex<double> a, std::complex<double> b, std::complex<double> c) {
	quadraticType answerSet;
	std::complex<double> rootPart = sqrt(pow(b, 2) - 4.0 * a * c);
	std::cout << "root part: " << rootPart << std::endl;
	answerSet.positive = (-b + rootPart) / (2.0 * a);
	answerSet.negative = (-b - rootPart) / (2.0 * a);

	return answerSet;
} 

I can't quite see the trick of translating nice looking comment indendation into the browser, so a better look at my algebra:
a^2 + b^2 = (1000 - a - b)^2.
a^2 + b^2 = (1000 - a - b) * (1000 - a - b).
a^2 + b^2 = 1000^2 + a^2 + b^2 - 2000a - 2000b  + 2ab.
0 = 1000^2 - 2000a - 2000b + 2ab.
a + b - (ab / 1000) - 500 = 0. 
b * (1 - a / 1000) = (-a + 500).
b * (1 - a / 1000) * (1 + 1000 / a) = (-a + 500) * (1 + 1000 / a).
-a - 1000 + 500 + 500'000 / a = 0.
a^2 + 500a -500,000 = 0.
Last edited on
Why, on lines 19 and 20 of your code (and the corresponding algebra) does b get eliminated? You have simply set the RHS to 0 - for no very good reason.
b * (1 - a / 1000) = (-a + 500)

From here I can multiply both sides by:
(1 + 1000 / a)

This makes the left side:
b * (1 - a / 1000) * (1 + 1000 / a)

foil:
b * ( (1) - (a / 1000) + (1000 / a) - 1)

that becomes:
b * (1000 / a - a / 1000)

which is different from what I had figured in my math above. I just needed another set of eyes it seems. I had thought it became:

b * (1 - 1)

Thanks.
Last edited on
a, b, c are natural numbers (positive integers), with a < b < c (so a is the smallest) and adding up to 1000.

Thus, if you want to do it by brute force (there are other ways, I think) you could simply check from a=1 to 332, noting that
>> from the correct part of your algebra, b = 1000 * ( 500 - a ) / ( 1000 - a ); check that this is a whole number and is greater than a;
>> then c = 1000 - a - b; check that this is greater than b; (the Pythagorean relation is already confirmed by your algebra leading to b).

If you are dealing solely with natural numbers then you won't require complex<> anywhere.
Last edited on
Yea, that ended up being the solution I used.
1
2
3
4
5
6
7
8
	double a = 0.0, b = 0.0, c = 0.0;

	do {
		a++;
		b = (500'000 - 1000 * a) / (1000 - a);
	} while ((round(b) != b));
	
	c = 1000 - a - b; 

Last edited on
I should make a, b, c ints, or you may hit floating-point round-off errors.

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
int main()
{
   for ( int a = 1; a <= 332; a++ )                        // all positive, add to 1000, a is smallest, so limited to 332
   {
      if ( 500000 % ( 1000 - a ) ) continue;               // check that b (if computed) will be a whole number
      int b = 1000 - 500000 / ( 1000 - a );                // OK, so compute b
      if ( b <= a ) continue;                              // problem statement requires a < b
      int c = 1000 - a - b;                                // remaining number computed from the given sum a+b+c = 1000
      if ( c <= b ) continue;                              // problem statement requires b < c
      std::cout << "a=" << a << "  b=" << b << "  c=" << c << "  abc=" << a * b * c << '\n';
   }
}


a=200  b=375  c=425  abc=31875000


Line 6 (just rearranged from my previous note) allows you to do this by hand, rather than computer.
500000 = 5625,
so, to be a factor,
1000-a
must be of the form:
(one number from 1, 5, 25, 125, 625, 3125, 15625) x (one number from 1, 2, 4, 8, 16, 32 )
and, given that 1000-a lies between 668 and 999, most of the products are easily seen to lie outside the range. There are only two possible products in the right range. You then select the one that gives a < b < c.
Last edited on
Topic archived. No new replies allowed.