From 02d51ee4a43166a9287db99ab50b62111e635084 Mon Sep 17 00:00:00 2001 From: "Dr. Martin Goik" <goik@hdm-stuttgart.de> Date: Fri, 12 Nov 2021 19:54:44 +0100 Subject: [PATCH] Better pythagorean triple solution --- Doc/Sd1/statements.xml | 136 +++++++++++++++++++++++++---------------- 1 file changed, 84 insertions(+), 52 deletions(-) diff --git a/Doc/Sd1/statements.xml b/Doc/Sd1/statements.xml index 889a94c47..1ad7de93a 100644 --- a/Doc/Sd1/statements.xml +++ b/Doc/Sd1/statements.xml @@ -6640,10 +6640,14 @@ Found (28, 96, 100)</screen> combinations being evaluated and the number of Pythagorean triples being found creating a final line like:</para> - <screen>52 triples found by filtering 131935 combinations</screen> + <screen>... +(60, 63, 87) +(60, 80, 100) +(65, 72, 97) +52 triples found by filtering 34766 combinations</screen> <para>Your solution should find all 52 triples by filtering - from at most 131935 combinations. If you do need less + from at most 34766 combinations. If you do need less combinations in the first place please let me know. I'm more than happy publishing an enhanced solution.</para> </question> @@ -6654,67 +6658,92 @@ Found (28, 96, 100)</screen> <orderedlist> <listitem> - <para>We calculate <inlineequation> - <m:math display="inline"> - <m:msup> - <m:mi>c</m:mi> - - <m:mi>2</m:mi> - </m:msup> - </m:math> - </inlineequation> beforehand:</para> + <para>We start with the rectangle's smaller leg:</para> <programlisting language="java">... -for (int c = 2; c <= LIMIT; c++) { - <emphasis role="red">final int cSquare = c * c</emphasis>; +for (int a = 1; a < LIMIT - 1; a++) { + +} ...</programlisting> + + <note> + <para>Since <inlineequation> + <m:math display="inline"> + <m:mrow> + <m:mi>1</m:mi> + + <m:mo><</m:mo> + + <m:mi>a</m:mi> + + <m:mo>≤</m:mo> + + <m:mi>b</m:mi> + + <m:mo><</m:mo> + + <m:mi>c</m:mi> + + <m:mo>≤</m:mo> + + <m:mi>LIMIT</m:mi> + </m:mrow> + </m:math> + </inlineequation> holds the rectangle's leg a can only + exceed <code>LIMIT - 2</code>. </para> + </note> </listitem> <listitem> - <para>Within the next inner loop we calculate - <inlineequation> + <para>Since <inlineequation> <m:math display="inline"> <m:mrow> - <m:msup> - <m:mi>c</m:mi> - - <m:mi>2</m:mi> - </m:msup> - - <m:mo>-</m:mo> + <m:mi>a</m:mi> - <m:msup> - <m:mi>b</m:mi> + <m:mo>≤</m:mo> - <m:mi>2</m:mi> - </m:msup> + <m:mi>b</m:mi> </m:mrow> </m:math> - </inlineequation> beforehand as well:</para> + </inlineequation> holds the next inner loop is + straightforward:</para> <programlisting language="java">... -for (int b = 1; b < c; b++) { // b must not exceed c since a == 0 otherwise - <emphasis role="red">final int cSquare_minus_bSquare = cSquare - b * b</emphasis>; +for (int b = a; b < LIMIT; b++) { + final int /* useful constants*/ + aPlusB = a + b, + aSquarePlusBsquare = a * a + b * b; + ... +} ...</programlisting> + + <note> + <para>The two variables <code>aPlusB</code> and + <code>aSquarePlusBsquare</code> will not have to be + re-calculated inside the innermost loop yet to be + defined.</para> + </note> </listitem> <listitem> - <para>The innermost loop will terminate on two - conditions:</para> + <para>We are dealing with triangles. c must thus be longer + than the triangle's longest leg. The innermost loop will + terminate on multiple conditions:</para> <programlisting language="java">... -for (int a = 1; - <emphasis role="red">a <= b</emphasis> && // Only ordered triples - <emphasis role="red">a * a <= cSquare_minus_bSquare</emphasis>; // Only till square root of c² - b² - a++) { ...</programlisting> +for (int c = b + 1; + <emphasis role="red">c <= LIMIT</emphasis> && + <emphasis role="red">c < aPlusB</emphasis> && // + <emphasis role="red">c * c <= aSquarePlusBsquare</emphasis>; + c++) { ...</programlisting> </listitem> <listitem> <para>Finally we re-write our filtering condition:</para> <programlisting language="java">... -if (<emphasis role="red">a * a == cSquare_minus_bSquare</emphasis>) { // Equivalent to a² + b² == c² - System.out.println("Found (" + a + ", " + b + ", " + c + ")"); +if (<emphasis role="red">aSquarePlusBsquare == c * c</emphasis>) { // Equivalent to a² + b² == c² + System.out.format("(%2d, %2d, %3d)\n", a, b , c); }</programlisting> </listitem> </orderedlist> @@ -6728,24 +6757,27 @@ if (<emphasis role="red">a * a == cSquare_minus_bSquare</emphasis>) { int comparisons = 0, countTriples = 0; -for (int c = 2; c <= LIMIT; c++) { - final int cSquare = c * c; - for (int b = 1; b < c; b++) { // b must not exceed c since a == 0 otherwise - final int cSquare_minus_bSquare = cSquare - b * b; // c² - b² - for (int a = 1; - a <= b && // Only ordered triples - a * a <= cSquare_minus_bSquare; // Only till square root of c² - b² - a++) { - if (a * a == cSquare_minus_bSquare ) { // Equivalent to a² + b² == c² - System.out.println( - "Found (" + a + ", " + b + ", " + c + ")"); - countTriples++; - } - comparisons++; +for (int a = 1; a < LIMIT - 1; a++) { + for (int b = a; b < LIMIT; b++) { + final int + aPlusB = a + b, + aSquarePlusBsquare = a * a + b * b; + + for (int c = b + 1; // c must be longer than the maximum of a and b + c <= LIMIT && + c < aPlusB && // c must be smaller than the sum of a and b + c * c <= aSquarePlusBsquare; // c² must not be larger than a² + b² + c++) { + if (aSquarePlusBsquare == c * c) { // Equivalent to a² + b² == c² + System.out.format("(%2d, %2d, %3d)\n", a, b , c); + countTriples++; } + comparisons++; } + } } -System.out.println(countTriples + " triples found by filtering " + comparisons + " combinations");</programlisting> +System.out.println(countTriples + " triples found by filtering " + comparisons + " combinations"); +</programlisting> </answer> </qandaentry> </qandadiv> -- GitLab