Generating unique, ordered Pythagorean triplets

前端 未结 19 1190
借酒劲吻你
借酒劲吻你 2020-11-29 16:57

This is a program I wrote to calculate Pythagorean triplets. When I run the program it prints each set of triplets twice because of the if statement. Is there any way I can

相关标签:
19条回答
  • 2020-11-29 17:39

    You should define x < y < z.

    for x in range (1, 1000):
        for y in range (x + 1, 1000):
                for z in range(y + 1, 1000):
    

    Another good optimization would be to only use x and y and calculate zsqr = x * x + y * y. If zsqr is a square number (or z = sqrt(zsqr) is a whole number), it is a triplet, else not. That way, you need only two loops instead of three (for your example, that's about 1000 times faster).

    0 讨论(0)
  • 2020-11-29 17:39

    Just checking, but I've been using the following code to make pythagorean triples. It's very fast (and I've tried some of the examples here, though I kind of learned them and wrote my own and came back and checked here (2 years ago)). I think this code correctly finds all pythagorean triples up to (name your limit) and fairly quickly too. I used C++ to make it.

    ullong is unsigned long long and I created a couple of functions to square and root my root function basically said if square root of given number (after making it whole number (integral)) squared not equal number give then return -1 because it is not rootable. _square and _root do as expected as of description above, I know of another way to optimize it but I haven't done nor tested that yet.

    generate(vector<Triple>& triplist, ullong limit) {
    cout<<"Please wait as triples are being generated."<<endl;
    register ullong a, b, c;
    register Triple trip;
    time_t timer = time(0);
    
    for(a = 1; a <= limit; ++a) {
        for(b = a + 1; b <= limit; ++b) {
            c = _root(_square(a) + _square(b));
    
            if(c != -1 && c <= limit) {
                trip.a = a; trip.b = b; trip.c = c;
    
                triplist.push_back(trip);
    
            } else if(c > limit)
                break;
        }
    }
    
    timer = time(0) - timer;
    cout<<"Generated "<<triplist.size()<<" in "<<timer<<" seconds."<<endl;
    cin.get();
    cin.get();
    

    }

    Let me know what you all think. It generates all primitive and non-primitive triples according to the teacher I turned it in for. (she tested it up to 100 if I remember correctly).

    The results from the v4 supplied by a previous coder here are

    Below is a not-very-scientific set of timings (using Java under Eclipse on my older laptop with other stuff running...), where the "use x, y, z" was implemented by instantiating a Triple object with the three values and putting it in an ArrayList. (For these runs, N was set to 10,000, which produced 12,471 triples in each case.)

    Version 4: 46 sec. using square root: 134 sec. array and map: 400 sec.

    The results from mine is How many triples to generate: 10000

    Please wait as triples are being generated. Generated 12471 in 2 seconds.

    That is before I even start optimizing via the compiler. (I remember previously getting 10000 down to 0 seconds with tons of special options and stuff). My code also generates all the triples with 100,000 as the limit of how high side1,2,hyp can go in 3.2 minutes (I think the 1,000,000 limit takes an hour).

    I modified the code a bit and got the 10,000 limit down to 1 second (no optimizations). On top of that, with careful thinking, mine could be broken down into chunks and threaded upon given ranges (for example 100,000 divide into 4 equal chunks for 3 cpu's (1 extra to hopefully consume cpu time just in case) with ranges 1 to 25,000 (start at 1 and limit it to 25,000), 25,000 to 50,000 , 50,000 to 75,000, and 75,000 to end. I may do that and see if it speeds it up any (I will have threads premade and not include them in the actual amount of time to execute the triple function. I'd need a more precise timer and a way to concatenate the vectors. I think that if 1 3.4 GHZ cpu with 8 gb ram at it's disposal can do 10,000 as lim in 1 second then 3 cpus should do that in 1/3 a second (and I round to higher second as is atm).

    0 讨论(0)
  • 2020-11-29 17:40
    
    for a in range(1,20):
        for b in range(1,20):
            for c in range(1,20):
                if a>b and c and c>b:
                    if a**2==b**2+c**2:
                        print("triplets are:",a,b,c)
    
    
    0 讨论(0)
  • 2020-11-29 17:40

    Version 5 to Joel Neely.

    Since X can be max of 'N-2' and Y can be max of 'N-1' for range of 1..N. Since Z max is N and Y max is N-1, X can be max of Sqrt ( N * N - (N-1) * (N-1) ) = Sqrt ( 2 * N - 1 ) and can start from 3.

    MaxX = ( 2 * N - 1 ) ** 0.5
    
    for x in 3..MaxX {
      y = x+1
      z = y+1
      m = x*x + y*y
      k = z * z
      while z <= N {
         while k < m {
            z = z + 1
            k = k + (2*z) - 1
        }
        if k == m and z <= N then {
            // use x, y, z
        }
        y = y + 1
        m = m + (2 * y) - 1
      }
     }
    
    0 讨论(0)
  • 2020-11-29 17:47

    The previously listed algorithms for generating Pythagorean triplets are all modifications of the naive approach derived from the basic relationship a^2 + b^2 = c^2 where (a, b, c) is a triplet of positive integers. It turns out that Pythagorean triplets satisfy some fairly remarkable relationships that can be used to generate all Pythagorean triplets.

    Euclid discovered the first such relationship. He determined that for every Pythagorean triple (a, b, c), possibly after a reordering of a and b there are relatively prime positive integers m and n with m > n, at least one of which is even, and a positive integer k such that

    a = k (2mn)
    b = k (m^2 - n^2)
    c = k (m^2 + n^2)
    

    Then to generate Pythagorean triplets, generate relatively prime positive integers m and n of differing parity, and a positive integer k and apply the above formula.

    struct PythagoreanTriple {
        public int a { get; private set; }
        public int b { get; private set; }
        public int c { get; private set; }
    
        public PythagoreanTriple(int a, int b, int c) : this() {
            this.a = a < b ? a : b;
            this.b = b < a ? a : b;
            this.c = c;
        }
    
        public override string ToString() {
            return String.Format("a = {0}, b = {1}, c = {2}", a, b, c);
        }
    
        public static IEnumerable<PythagoreanTriple> GenerateTriples(int max) {
            var triples = new List<PythagoreanTriple>();
            for (int m = 1; m <= max / 2; m++) {
                for (int n = 1 + (m % 2); n < m; n += 2) {
                    if (m.IsRelativelyPrimeTo(n)) {
                        for (int k = 1; k <= max / (m * m + n * n); k++) {
                            triples.Add(EuclidTriple(m, n, k));
                        }
                    }
                }
            }
    
            return triples;
        }
    
        private static PythagoreanTriple EuclidTriple(int m, int n, int k) {
            int msquared = m * m;
            int nsquared = n * n;
            return new PythagoreanTriple(k * 2 * m * n, k * (msquared - nsquared), k * (msquared + nsquared));
        }
    }
    
    public static class IntegerExtensions {
        private static int GreatestCommonDivisor(int m, int n) {
            return (n == 0 ? m : GreatestCommonDivisor(n, m % n));
        }
    
        public static bool IsRelativelyPrimeTo(this int m, int n) {
            return GreatestCommonDivisor(m, n) == 1;
        }
    }
    
    class Program {
        static void Main(string[] args) {
            PythagoreanTriple.GenerateTriples(1000).ToList().ForEach(t => Console.WriteLine(t));            
        }
    }
    

    The Wikipedia article on Formulas for generating Pythagorean triples contains other such formulae.

    0 讨论(0)
  • 2020-11-29 17:47

    Yes, there is.

    Okay, now you'll want to know why. Why not just constrain it so that z > y? Try

    for z in range (y+1, 1000)
    
    0 讨论(0)
提交回复
热议问题