I'm well aware this brute force method is bad and that I should be using something like Euclid's formula, and that the final loop isn't needed as c = 1000 - (a + b) etc... but right now I just want this to work.
bool isPythagorean(int a, int b, int c) {
if((a*a + b*b) == c*c && a < b && b < c) {
cout << a << " " << b << " " << c << endl;
return true;
} else {
return false;
}
}
int main()
{
int a = 1;
int b = 2;
int c = 3;
for(a = 1; a < b; ++a) {
for(b = 2; b < c; ++b) {
for(c = 3; a + b + c != 1000 && !isPythagorean(a, b, c); ++c) {
}
}
}
return 0;
}
For the most part, the code works as I expect it to. I cannot figure out why it is stopping shy of a + b + c = 1000.
My final triplet is 280 < 294 < 406, totalling 980.
If I remove the a < b < c check, the triplet becomes 332, 249, 415 totalling 996.
All results fit the pythagorean theorem -- I just cannot land a + b + c = 1000.
What is preventing me?
This part of the code iterates very strangely:
for(a = 1; a < b; ++a) {
for(b = 2; b < c; ++b) {
for(c = 3; a + b + c != 1000 && !isPythagorean(a, b, c); ++c) {
}
}
}
Initially, a = 1, b = 2, c = 3. But upon the first for(c), c=997, so the second iteration of for(b) will run up to b=996. Keep doing this, and at some point you find a triple (a,b,c), at that point, c is probably not close to 1000, b will iterate up to whatever state c was is in... and so on. I don't think you can accurately predict the way it's going to come up with triples.
I suggest you go with something like
for(a = 1; 3*a < 1000; ++a) {
for(b = a+1; a+2*b < 1000; ++b) {
for(c = b+1; a + b + c != 1000 && !isPythagorean(a, b, c); ++c) {
}
}
}
That way, loops won't depend on the previously found triple.
... and you really should use Euclid's method.
The condition in your innermost for loop explicitly says to never test anything where a + b + c is equal to 1000. Did you mean a + b + c <= 1000?
Alternate possible Solution:
#include <iostream>
#define S(x) x*x
int main() {
int c = 0;
for(int a=1;a<(1000/3);++a) {
// a < b; so b is at-least a+1
// If a < b < c and a + b + c = 1000 then 'a' can't be greater than 1000/3
// 'b' can't be greater than 1000/2.
for(int b=a+1;b<(1000/2);++b) {
c = (1000 - a - b); // problem condition
if(S(c) == (S(a) + S(b) ))
std::cout<<a*b*c;
}
}
return 0;
}
For additional reference please refer the following posts
Finding Pythagorean Triples: Euclid's Formula
Generating unique, ordered Pythagorean triplets
Related
Given following in C++:
$$k = 2^a \cdot b,$$
only knowing the value of k and that b is odd. How do you find the value for a and the value for b?
I did consider the following:
if k is odd, a has to be zero and b is k
if k is even, I would go through all possible b's with a for-loop and check if k % b == 0. If that is the case, I would take log2(k/b) and if that gives me back an integer, b = k/b and a = log2(b).
My problem: how do I check if log2(k/b) gives me back an integer?
C++ code:
Big k(9);
int r = 4;
int n = pow(2,r);
if (k % 2 == 1)
{
a = 0;
b = k;
}
else
{
for (int b = 1; b < n; b += 2)
{
if (k % b == 0 && LOGARITHM OF k / b IS POSSIBLE)
{
a = log2(b);
}
}
}
By the way: n is given as well. Everything but a and b is given.
You might do the following:
int a = 0;
while (k % 2 == 0) {
++a;
k /= 2;
}
int b = k;
// you have a, b
idest, divide by 2 the number 2**a*b until it is no longer even, so you found b.
Assuming k is unsigned int,
#include <bit>
...
int a = std::countr_zero(k);
unsigned int b = k >> a;
The question need the user input two value, P and Q. The program then will output the number of right angle integer triangle as well as its perimeter from P to Q.
For example:
Input:
154 180
Output:
154 1
156 1
160 1
168 3
176 1
180 3
I think i need to find out the Pythagorean Triples in the P-Q range, but how to count the " number of right-angled triangle " ?
Here are my code :
#include <iostream>
#include <math.h>
using namespace std;
int main() {
int P, Q, a, b, c, i = 0;
cin >> P >> Q;
for ( a = P; a <= Q; ++a)
{
for ( b = a; b <= Q; ++b)
{
for ( c = b; b <= Q; ++c)
{
if ((pow(a, 2) + pow(b, 2)) == pow(c, 2) && a + b + c <= Q)
{
i +=1;
cout << a + b + c << " " << i << endl;
}
}
}
}
return 0;
}
Super Thanks !!
We can count the right angle integer triangles with a specific perimeter by std::map which has the perimeters as keys and the number of triangles as values:
std::map<int, int> triangle_map;
Next, using the symmetry of triangles of exchanging a and b with flipping, we can restrict our finding search into the case of a<=b.
But if a==b then c=sqrt(2)*a which is not an integer when a is an integer.
Therefore the following double-loop search would well work for us and can find all the target triangles:
const int Qmax_a = (Q-1)/2; // 1 is the minimum value of c.
for (int a = 1; a <= Qmax_a; ++a)
{
const int a_sqr = a*a;
for (int b = a+1; b <= Q-a-1; ++b)
{
const int two_side_sqr = a_sqr + b*b;
// possible candidate
const int c = static_cast<int>(std::round(std::sqrt(two_side_sqr)));
const int perimeter = (a+b+c);
if((c*c == two_side_sqr) && (P <= perimeter) && (perimeter <= Q)){
triangle_map[perimeter] += 1;
}
}
}
Finally, we can get the desired output from the resulted map:
DEMO
for(const auto& p : triangle_map){
std::cout << p.first << "," << p.second << std::endl;
}
I'm trying to find the sum of all divisors of c in a give range a, b a <= b.
I've tried to loop from a to b and sum all divisors of c, but this seems inefficient, because the absolute difference between a and b can be 10^9.
Is there a way that reduces the time complexity of this approach?
int a, b, c;
cin >> a >> b >> c;
long long sum = 0;
for (int i = a; i <= b; i++) {
if (i % c == 0) {
ans += i;
}
}
cout << sum << endl;
Note: the question is unclear whether we need to sum divisors (in the description) or divisible integers (in the code sample). The answer sums up divisible items.
This is simple.
Find from, the smallest value such that from % c == 0 && from >= a
Find to, the largest value such that to % c == 0 && to <= b
.
int n = (to - from) / c + 1;
return n * (to + from) / 2;
Return to - from + c. Take care of boundary conditions when to could overflow your type and from can underflow.
To find from do something like:
if (c < 0) c *= -1; // works unless c == MIN_INT
if (a % c == 0)
from = a;
else if (a >= 0)
from = (a / c * c) + c
else
from = a / c * c;
Similarly for to, but accounting for the fact that we need to round down, and not up.
Also, need to handle the case of a > b separately.
EDIT
Here is the complete code with no loops, recursion, or containers. It runs in O(1):
int a, b, c;
std::cin >> a >> b >> c;
if (!std::cin) {
std::cout << "input error\n";
return 0;
}
if (c < 0) c*= -1;
const int from = [a,c] {
// no rounding needed
if (a % c == 0) return a;
// division rounds down to zero
if (a > 0) return (1 + a / c) * c;
// division rounds up to zero
return a / c * c;
}();
const int to = [b,c] {
// no rounding needed
if (b % c == 0) return b;
// division rounds down to zero
if (b > 0) return (b / c) * c;
// division rounds up to zero
return (b / c - 1) * c;
}();
int64_t sum = 0;
if (from <= to)
{
const int n = (to - from) / c + 1;
sum = n * (to + from) / 2;
}
std::cout << sum << '\n';
Identify all the prime numbers that are divisors of c first. That will leave you with a list of numbers [w,x,y,z…]. Then keep a hash table set of all multiples of integers in this list that are also divisors.
int a, b, c;
cin >> a >> b >> c;
long long sum = 0;
std::vector<int> all_prime_factors = // Get all prime factors of c
std::unordered_set<int> factorSet;
for (int primefactor : all_prime_factors)
{
int factor = primefactor;
while (factor <= b)
{
if (factor % c == 0)
factorSet.insert(factor);
factor += primefactor;
}
}
for (int x : factorSet)
{
sum += x;
}
cout << sum << endl;
I'm working on problem 9 in Project Euler:
There exists exactly one Pythagorean triplet for which a + b + c = 1000.
Find the product abc.
The following code I wrote uses Euclid's formula for generating primes. For some reason my code returns "0" as an answer; even though the variable values are correct for the first few loops. Since the problem is pretty easy, some parts of the code aren't perfectly optimized; I don't think that should matter. The code is as follows:
#include <iostream>
using namespace std;
int main()
{
int placeholder; //for cin at the end so console stays open
int a, b, c, m, n, k;
a = 0; b = 0; c = 0;
m = 0; n = 0; k = 0; //to prevent initialization warnings
int sum = 0;
int product = 0;
/*We will use Euclid's (or Euler's?) formula for generating primitive
*Pythagorean triples (a^2 + b^2 = c^2): For any "m" and "n",
*a = m^2 - n^2 ; b = 2mn ; c = m^2 + n^2 . We will then cycle through
*values of a scalar/constant "k", to make sure we didn't miss anything.
*/
//these following loops will increment m, n, and k,
//and see if a+b+c is 1000. If so, all loops will break.
for (int iii = 1; m < 1000; iii++)
{
m = iii;
for (int ii = 1; n < 1000; ii++)
{
n = ii;
for (int i = 1; k <=1000; i++)
{
sum = 0;
k = i;
a = (m*m - n*n)*k;
b = (2*m*n)*k;
c = (m*m + n*n)*k;
if (sum == 1000) break;
}
if (sum == 1000) break;
}
if (sum == 1000) break;
}
product = a * b * c;
cout << "The product abc of the Pythagorean triplet for which a+b+c = 1000 is:\n";
cout << product << endl;
cin >> placeholder;
return 0;
}
And also, is there a better way to break out of multiple loops without using "break", or is "break" optimal?
Here's the updated code, with only the changes:
for (m = 2; m < 1000; m++)
{
for (int n = 2; n < 1000; n++)
{
for (k = 2; (k < 1000) && (m > n); k++)
{
sum = 0;
a = (m*m - n*n)*k;
b = (2*m*n)*k;
c = (m*m + n*n)*k;
sum = a + b + c;
if ((sum == 1000) && (!(k==0))) break;
}
It still doesn't work though (now gives "1621787660" as an answer). I know, a lot of parentheses.
The new problem is that the solution occurs for k = 1, so starting your k at 2 misses the answer outright.
Instead of looping through different k values, you can just check for when the current sum divides 1000 evenly. Here's what I mean (using the discussed goto statement):
for (n = 2; n < 1000; n++)
{
for (m = n + 1; m < 1000; m++)
{
sum = 0;
a = (m*m - n*n);
b = (2*m*n);
c = (m*m + n*n);
sum = a + b + c;
if(1000 % sum == 0)
{
int k = 1000 / sum;
a *= k;
b *= k;
c *= k;
goto done;
}
}
}
done:
product = a * b * c;
I also switched around the two for loops so that you can just initialize m as being larger than n instead of checking every iteration.
Note that with this new method, the solution doesn't occur for k = 1 (just a difference in how the loops are run, this isn't a problem)
Presumably sum is supposed to be a + b + c. However, nowhere in your code do you actually do this, which is presumably your problem.
To answer the final question: Yes, you can use a goto. Breaking out of multiple nested loops is one of the rare occasions when it isn't considered harmful.
This loop works as long as l is 1 and h can be any number. But i need it to work from different ranges such as l = 20 h = 40? Can anyone tell me how to do it? I would greatly appreciate it.
#include <iostream>
#include <vector>
#include <list>
#include <math.h>
#include <algorithm>
using namespace std;
int main(void)
{
int a, b, c, i = 0;
unsigned long l = 1;
unsigned long h = 25;
int array[3];
for ( a = l; l <= a && a <= h; ++a )
for ( b = a; l <= b && b <= h; ++b )
for ( c = b; l < c && c <= h; ++c )
if ( a * a + b * b == c * c )
{
array[0] = a;
array[1] = b;
array[2] = c;
if (array[0]+array[1]+array[2] <= h)
cout << array[0] << " " << array[1] << " " << array[2] <<endl;
else
break;
}
return 0;
}
If I understand you right, you're trying to bruteforce Diophant's system
a^2 + b^2 = c^2
a + b + c < h
this is the solution
#include <iostream>
using namespace std;
int main() {
const int l = 1;
const int h = 25;
for ( int a = l; a <= h; ++a )
for ( int b = l; b <= h; ++b )
for ( int c = l; c <= h; ++c )
if ((a * a + b * b == c * c ) &&
(a + b + c <= h))
cout << a << " " << b << " " << c <<endl;
return 0;
}
the output is:
3 4 5
4 3 5
6 8 10
8 6 10
if you don't need to distinguish a and b, second cycle could be
for ( int b = a; b <= h; ++b )
so you will get this:
3 4 5
6 8 10
There is something funny with this line, I can't tell what you are trying to do...
for ( a = l; l <= a && a <= h; ++a )
So, on the first round a=l, a++, and the condition is checked l<=a. a will be l+1, which means that l<=l+1, so you are going to exit your loop after the first time. I suspect that is not the behavior you want, but I really don't know what you do want. I could speculate that you want something like this:
for ( a = 0; l <= a && a <= h; ++a )
EDIT: From your comments, I can see what you are trying to do, and this should work better. Basically, you don't need to have the conditional for the lower value, it is the root of your problems. Also, I don't see why you bother to put the values into an array, which is written over each time, so I removed that.
for ( a = l; a <= h; ++a ) {
for ( b = a; b <= h; ++b ) {
for ( c = b; c <= h; ++c ) {
if ( a * a + b * b == c * c ) {
if (a+b+c <= h) {
cout << a << " " << b << " " << c <<endl;
}
else {
break;
}
}
}
}
}
I think one problem is in your third loop, which is slightly different from the other two:
for ( c = b; l < c && c <= h; ++c ) {
On the first pass, a == 1 and b == 1 and l == 1 so c is set to 1, and l < c evaluates to false, so the inner loop does not execute.
You really don't need to test your lower bounds (the l < c, or l <= b etc in earlier loops) because you know from the way you set them up that the condition should be true, except when you make a typo in the condition.
The canonical form for a for loop in C++ is:
for (int i = lo; i < hi; ++i)
for a suitable type (int here), index variable (i) going from a lower bound lo up to but not including an upper bound hi. This works in C99 too, but not C89. If you need the loop index's value after the loop completes, you might declare the variable at larger scope than just the loop as shown, but you usually avoid doing that. (I used i++ in a comment because I'm an unreformed C programmer, but the pre-increment is better in C++ in general.)
at the first loop the condition will be false from the first time because l>a