web-dev-qa-db-fra.com

Trouver un triplet de Pythagore pour lequel a + b + c = 1000

Un triplet de Pythagore est un ensemble de trois nombres naturels, a <b <c, pour lesquels, A2 + b2 = c2

Par exemple, 32 + 42 = 9 + 16 = 25 = 52.

Il existe exactement un triplet de Pythagore pour lequel a + b + c = 1000 . Trouver le produit abc.

Source: http://projecteuler.net/index.php?section=problems&id=9

J'ai essayé mais je ne savais pas où mon code s'était mal passé. Voici mon code en C:

#include <math.h>
#include <stdio.h>
#include <conio.h>


void main()
{
    int a=0, b=0, c=0;
    int i;
    for (a = 0; a<=1000; a++)
    {
        for (b = 0; b<=1000; b++)
        {
            for (c = 0; c<=1000; c++)
            {
                if ((a^(2) + b^(2) == c^(2)) && ((a+b+c) ==1000)))
                    printf("a=%d, b=%d, c=%d",a,b,c);
            }
        }
    }
getch();    
}
27
Rahul
#include <math.h>
#include <stdio.h>

int main()
{
    const int sum = 1000;
    int a;
    for (a = 1; a <= sum/3; a++)
    {
        int b;
        for (b = a + 1; b <= sum/2; b++)
        {
            int c = sum - a - b;
            if ( a*a + b*b == c*c )
               printf("a=%d, b=%d, c=%d\n",a,b,c);
        }
    }
    return 0;
}

explication: 

  • b = a;
    si a, b (a <= b) et c sont le triplet de Pythagore, 
    alors b, a (b> = a) et c - également la solution, nous ne pouvons donc rechercher qu'un seul cas
  • c = 1000 - a - b; C'est l'une des conditions du problème (nous n'avons pas besoin d'analyser tout le 'c' possible: calculez-le simplement)
28
Oleg Razgulyaev

J'ai bien peur que ^ ne fasse pas ce que vous pensez qu'il fait en C. Votre meilleur choix est d'utiliser a*a pour les carrés entiers.

30
Paul Stephenson

Voici une solution utilisant la formule d'Euclid ( link ).

Faisons quelques maths: En général, chaque solution aura la forme

a=k(x²-y²)
b=2kxy
c=k(x²+y²)

où k, x et y sont des entiers positifs, y <x et gcd (x, y) = 1 (nous ignorerons cette condition, ce qui conduira à des solutions supplémentaires. Celles-ci pourront être ignorées par la suite)

Maintenant, a + b + c = kx²-ky² + 2kxy + kx² + ky² = 2kx² + 2kxy = 2kx (x + y) = 1000

Diviser par 2: kx (x + y) = 500

Maintenant nous définissons s = x + y: kxs = 500

Nous cherchons maintenant des solutions de kxs = 500, où k, x et s sont des entiers et x < s < 2x. Tous divisant par 500, ils ne peuvent prendre que les valeurs 1, 2, 4, 5, 10, 20, 25, 50, 100, 125, 250, 500. Quelques pseudocodes pour le faire pour n arbitraire (cela peut être fait à la main facilement pour n = 1000)

If n is odd
  return "no solution"
else
  L = List of divisors of n/2
for x in L
  for s in L
    if x< s <2*x and n/2 is divisible by x*s
      y=s-x
      k=((n/2)/x)/s      
      add (k*(x*x-y*y),2*k*x*y,k*(x*x+y*y)) to list of solutions
sort the triples in the list of solutions
delete solutions appearing twice
return list of solutions

Vous pouvez toujours améliorer ceci:

  • x ne sera jamais plus gros que la racine de n/2
  • la boucle pour s peut commencer à x et s'arrêter après que 2x soit passé (si la liste est ordonnée)

Pour n = 1000, le programme doit vérifier six valeurs pour x et en fonction des détails de la mise en œuvre, jusqu'à une valeur pour y. Cela se terminera avant que vous relâchiez le bouton.

17
do_the_math

Comme mentionné ci-dessus, ^ est au niveau du bit xor, pas du pouvoir.

Vous pouvez également supprimer la troisième boucle et utiliser plutôt c = 1000-a-b; et l'optimiser un peu.

Pseudocode

for a in 1..1000
    for b in a+1..1000
        c=1000-a-b
        print a, b, c if a*a+b*b=c*c
14
Dogbert

Il existe une solution assez sale mais rapide à ce problème. Étant donné les deux équations

a * a + b * b = c * c

a + b + c = 1000.

Vous pouvez en déduire la relation suivante

a = (1000 * 1000-2000 * b)/(2000-2b)

ou après deux transformations mathématiques simples, vous obtenez: 

a = 1000 * (500-b)/(1000 - b)

puisque a doit être un nombre naturel. Par conséquent, vous pouvez:

for b in range(1, 500):
    if 1000*(500-b) % (1000-b) == 0:
        print b, 1000*(500-b) / (1000-b) 

Obtenu les résultats 200 et 375.

Bonne chance

12
dgg32
#include <stdio.h>

int main() // main always returns int!
{
 int a, b, c;
 for (a = 0; a<=1000; a++)
 {
  for (b = a + 1; b<=1000; b++) // no point starting from 0, otherwise you'll just try the same solution more than once. The condition says a < b < c.
  {
   for (c = b + 1; c<=1000; c++) // same, this ensures a < b < c.
   {
    if (((a*a + b*b == c*c) && ((a+b+c) ==1000))) // ^ is the bitwise xor operator, use multiplication for squaring
     printf("a=%d, b=%d, c=%d",a,b,c);
   }
  }
 }
 return 0;
}

Je n'ai pas testé cela, mais cela devrait vous mettre sur la bonne voie.

6
IVlad

De man pow:

POW(3)                                       Linux Programmer's Manual                                      POW(3)

NAME
       pow, powf, powl - power functions

SYNOPSIS
       #include <math.h>

       double pow(double x, double y);
       float powf(float x, float y);
       long double powl(long double x, long double y);

       Link with -lm.

   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

       powf(), powl(): _BSD_SOURCE || _SVID_SOURCE || _XOPEN_SOURCE >= 600 || _ISOC99_SOURCE; or cc -std=c99

DESCRIPTION
       The pow() function returns the value of x raised to the power of y.

RETURN VALUE
       On success, these functions return the value of x to the power of y.

       If  x  is  a  finite  value less than 0, and y is a finite non-integer, a domain error occurs, and a NaN is
       returned.

       If the result overflows, a range error occurs, and the functions return HUGE_VAL, HUGE_VALF, or  HUGE_VALL,

comme vous le voyez, pow utilise une arithmétique en virgule flottante, ce qui ne vous donnera probablement pas le résultat exact (même si dans ce cas devrait être OK, car les entiers relativement petits ont une représentation exacte; ne vous fiez pas à cela pour les cas généraux). .. utilisez n*n pour faire cadrer les nombres en arithmétique entière (également, dans les CPU modernes avec de puissantes unités à virgule flottante, le débit peut être encore plus élevé en virgule flottante, mais la conversion d'entier en virgule flottante a un coût très élevé en nombre de cycles de CPU, donc si vous avez affaire à des nombres entiers, essayez de vous en tenir à l’arithmétique des nombres entiers).

un pseudocode pour vous aider à optimiser un peu votre algorithme:

for a from 1 to 998:
    for b from 1 to 999-a:
        c = 1000 - a - b
        if a*a + b*b == c*c:
             print a, b, c
6
fortran

En C, l'opérateur ^ calcule xor au niveau du bit, pas la puissance. Utilisez x*x à la place.

5
swegi

Je sais que cette question est assez ancienne et que tout le monde a publié des solutions avec 3 boucles pour, ce qui n'est pas nécessaire. Je l'ai résolu en O (n), par **equating the formulas**; **a+b+c=1000 and a^2 + b^2 = c^2**

Donc, en résolvant plus loin nous obtenons;

a+b = 1000-c

(a+b)^2 = (1000-c)^2

Si nous résolvons plus loin nous en déduisons à; 

a = ((50000- (1000 * b))/(1000-b)) . Nous bouclons pour "b" et trouvons "a". 

Une fois que nous avons "a" et "b", nous obtenons "c".

public long pythagorasTriplet(){
    long a = 0, b=0 , c=0;

    for(long divisor=1; divisor<1000; divisor++){
        if( ((500000-(1000*divisor))%(1000-divisor)) ==0){
            a = (500000 - (1000*divisor))/(1000-divisor);
            b = divisor;
            c = (long)Math.sqrt(a*a + b*b);
            System.out.println("a is " + a + " b is: " + b + " c is : " + c);
            break;
        }
    }
    return a*b*c;
}
2
JNL

Comme d'autres l'ont déjà mentionné, vous devez comprendre l'opérateur ^ ..____ De plus, votre algorithme produira plusieurs réponses équivalentes avec les paramètres a, b et c dans des ordres différents.

2
Elemental

Tandis que autant de personnes ont fait remarquer que votre code fonctionnera correctement une fois que vous passerez à pow. Si vous êtes intéressé à apprendre un peu de théorie mathématique telle qu’elle s’applique à CS, je vous recommanderais d’implémenter une version plus efficace en utilisant "la formule d’Euclide" pour générer des triples de Pythagore ( link ).

2
Kendall Hopkins

La méthode euclide donne le périmètre à m (m + n) = p/2 où m> n et les côtés sont m ^ 2 + n ^ 2 est l'hypoténuse et les jambes sont 2mn et m ^ 2-n ^ 2. m (m + n) = 500 donne rapidement m = 20 et n = 5. Les côtés sont 200, 375 et 425. Utilisez Euclid pour résoudre toutes les questions primitives pythoriennes.

1
Duncan Fraser

Comme il existe deux équations (a+b+c = 1000 && aˆ2 + bˆ2 = cˆ2) avec trois variables, nous pouvons le résoudre en temps linéaire en parcourant simplement toutes les valeurs possibles d’une variable, puis nous pouvons résoudre les deux autres variables en temps constant.

A partir de la première formule, nous obtenons b=1000-a-c, et si nous remplaçons b dans la 2ème formule par ceci, nous obtenons c^2 = aˆ2 + (1000-a-c)ˆ2, ce qui simplifie à c=(aˆ2 + 500000 - 1000a)/(1000-a).

Ensuite, nous parcourons toutes les valeurs possibles de a, résolvons c et b avec les formules ci-dessus et, si les conditions sont remplies, nous avons trouvé notre triplet.

    int n = 1000;

    for (int a = 1; a < n; a++) {
        int c = (a*a + 500000 - 1000*a) / (1000 - a);
        int b = (1000 - a - c);

        if (b > a && c > b && (a * a + b * b) == c * c) {
            return a * b * c;
        }
    }
1
Juha Siren
func maxProd(sum:Int)->Int{
    var prod = 0
    //    var b = 0
    var c = 0
    let bMin:Int = (sum/4)+1 //b can not be less than sum/4+1 as (a+b) must be greater than c as there will be no triangle if this condition is false and any pythagorus numbers can be represented by a triangle.
    for b in bMin..<sum/2 {
        for a in ((sum/2) - b + 1)..<sum/3{ //as (a+b)>c for a valid triangle
            c = sum - a - b
            let csquare = Int(pow(Double(a), 2) + pow(Double(b), 2))
            if(c*c == csquare){
                let newProd = a*b*c
                if(newProd > prod){
                    prod = newProd
                    print(a,b,c)
                }
            }
        }
    }
    //
    return prod
}

Les réponses ci-dessus sont suffisantes, mais il manque un élément d'information important a + b> c . ;)

Plus de détails seront fournis à ceux qui le demandent.

0
Madhup Singh Yadav
for a in range(1,334):
    for b in range(500, a, -1):
        if a + b < 500:
            break
        c = 1000 - a - b
        if a**2 + b**2 == c**2:
            print(a,b,c)

Optimisation plus poussée à partir de la réponse d'Oleg ... Un des côtés ne peut pas être supérieur à la somme des deux autres ... Donc, a + b ne peut être inférieur à 500 

0
Moosa Ahmed

Je pense que la meilleure approche est la suivante:

int n = 1000;
unsigned long long b =0;
unsigned long long c =0;
for(int a =1;a<n/3;a++){
    b=((a*a)- (a-n)*(a-n)) /(2*(a-n));
    c=n-a-b;

    if(a*a+b*b==c*c)
        cout<<a<<' '<<b<<' '<<c<<endl;
 }

explication: Nous nous référerons à la constante N et A pour ne pas avoir à utiliser deux boucles . Nous pouvons le faire car c=n-a-b et b = (a^2-(a-n)^2)/(2(a-n)) J'ai obtenu ces formules en résolvant un système d'équations:

a+b+c=n, a^2+b^2=c^2

0
H_meir