From 5df67831497e88d85757f7dd731d9985b0c675ae Mon Sep 17 00:00:00 2001
From: Martin Goik <goik@hdm-stuttgart.de>
Date: Sat, 26 Sep 2015 16:21:06 +0200
Subject: [PATCH] Recursive binomial calculation

---
 Doc/Sd1/Ref/Fig/pascal.fig                    |  96 ++++
 Doc/Sd1/objectsClasses.xml                    | 428 +++++++++++++++++-
 P/Sd1/Binomial/V3/.gitignore                  |   5 +
 P/Sd1/Binomial/V3/pom.xml                     |  20 +
 .../mi/sd1/binomial/Binomial.java             |  42 ++
 .../mi/sd1/binomial/Lottery.java              |  18 +
 .../mi/sd1/binomial/PerformanceTest.java      |  30 ++
 .../mi/sd1/binomial/test/BinomTest.java       |  60 +++
 P/pom.xml                                     |   3 +
 9 files changed, 678 insertions(+), 24 deletions(-)
 create mode 100644 Doc/Sd1/Ref/Fig/pascal.fig
 create mode 100644 P/Sd1/Binomial/V3/.gitignore
 create mode 100644 P/Sd1/Binomial/V3/pom.xml
 create mode 100644 P/Sd1/Binomial/V3/src/main/java/de/hdm_stuttgart/mi/sd1/binomial/Binomial.java
 create mode 100644 P/Sd1/Binomial/V3/src/main/java/de/hdm_stuttgart/mi/sd1/binomial/Lottery.java
 create mode 100644 P/Sd1/Binomial/V3/src/main/java/de/hdm_stuttgart/mi/sd1/binomial/PerformanceTest.java
 create mode 100644 P/Sd1/Binomial/V3/src/test/java/de/hdm_stuttgart/mi/sd1/binomial/test/BinomTest.java

diff --git a/Doc/Sd1/Ref/Fig/pascal.fig b/Doc/Sd1/Ref/Fig/pascal.fig
new file mode 100644
index 000000000..29c325144
--- /dev/null
+++ b/Doc/Sd1/Ref/Fig/pascal.fig
@@ -0,0 +1,96 @@
+#FIG 3.2  Produced by xfig version 3.2.5c
+Landscape
+Center
+Metric
+A4      
+100.00
+Single
+-2
+1200 2
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 1957 3442 2182 3217
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 2407 2992 2632 2767
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 2857 2542 3082 2317
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 5130 2970 5355 2745
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 2857 3442 3082 3217
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 3307 2992 3532 2767
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 3757 2542 3982 2317
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 3285 2115 3510 1890
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 2025 3510 2655 3510
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 2925 3510 3555 3510
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 3825 3510 4455 3510
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 4725 3510 5355 3510
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 2430 3060 3060 3060
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 3330 3060 3960 3060
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 4185 3060 4815 3060
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 2880 2610 3510 2610
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 3780 2610 4410 2610
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 3330 2160 3960 2160
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 2160 2610 2610 2610
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 1710 3060 2160 3060
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 1260 3510 1710 3510
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 2610 2160 3060 2160
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 3060 1710 3510 1710
+2 3 0 0 0 0 60 -1 2 0.000 0 0 -1 0 0 4
+	 1267 3877 3652 1537 6037 3877 1267 3877
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 3757 1642 3982 1417
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 4207 2092 4432 1867
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 4680 2520 4905 2295
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 5602 3397 5827 3172
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 3757 3397 3982 3172
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 4207 2947 4432 2722
+2 1 0 1 0 0 50 -1 2 0.000 0 0 -1 0 0 2
+	 4657 3442 4882 3217
+4 0 0 50 -1 30 12 0.0000 4 135 105 3600 1800 1\001
+4 0 0 50 -1 30 12 0.0000 4 135 105 3150 2250 1\001
+4 0 0 50 -1 30 12 0.0000 4 135 105 4050 2250 1\001
+4 0 0 50 -1 30 12 0.0000 4 135 105 2700 2700 1\001
+4 0 0 50 -1 30 12 0.0000 4 135 105 4500 2700 1\001
+4 0 0 50 -1 30 12 0.0000 4 120 105 3600 2700 2\001
+4 0 0 50 -1 30 12 0.0000 4 135 105 2250 3150 1\001
+4 0 0 50 -1 30 12 0.0000 4 135 105 4950 3150 1\001
+4 0 0 50 -1 30 12 0.0000 4 135 105 5400 3600 1\001
+4 0 0 50 -1 30 12 0.0000 4 135 105 1800 3600 1\001
+4 0 0 50 -1 30 12 0.0000 4 120 105 3150 3150 3\001
+4 0 0 50 -1 30 12 0.0000 4 120 105 4050 3150 3\001
+4 0 0 50 -1 30 12 0.0000 4 135 105 2700 3600 4\001
+4 0 0 50 -1 30 12 0.0000 4 120 105 3600 3600 6\001
+4 0 0 50 -1 30 12 0.0000 4 135 105 4500 3600 4\001
+4 0 0 50 -1 30 12 0.7854 4 150 345 5490 2745 k=3\001
+4 0 0 50 -1 30 12 0.7854 4 150 345 5895 3195 k=4\001
+4 0 0 50 -1 30 12 0.0000 4 135 345 810 3600 n=4\001
+4 0 0 50 -1 30 12 0.0000 4 120 345 1260 3150 n=3\001
+4 0 0 50 -1 30 12 0.0000 4 120 345 1710 2700 n=2\001
+4 0 0 50 -1 30 12 0.0000 4 135 345 2160 2250 n=1\001
+4 0 0 50 -1 30 12 0.0000 4 120 345 2610 1800 n=0\001
+4 0 0 50 -1 30 12 0.7854 4 150 345 4590 1845 k=1\001
+4 0 0 50 -1 30 12 0.7854 4 150 345 4140 1395 k=0\001
+4 0 0 50 -1 30 12 0.7854 4 150 345 4995 2250 k=2\001
diff --git a/Doc/Sd1/objectsClasses.xml b/Doc/Sd1/objectsClasses.xml
index 6130ddfa2..534dbb62c 100644
--- a/Doc/Sd1/objectsClasses.xml
+++ b/Doc/Sd1/objectsClasses.xml
@@ -3010,20 +3010,21 @@ Largest long value:9223372036854775807</programlisting></td>
       <para>The following sections provide exercises on implementing
       mathematical functions. We start with an easy one.</para>
 
-      <qandaset defaultlabel="qanda" xml:id="sd1QandaMaxAbs">
+      <section xml:id="sd1SectMaxAbs">
         <title>Maximum and absolute value</title>
 
-        <qandadiv>
-          <qandaentry>
-            <question>
-              <para>Implement a class method methods <methodname>double
-              abs(double)</methodname> and two overloaded methods
-              <methodname>double max(double, double)</methodname> and
-              <methodname>double max(double, double, double)</methodname> in a
-              class <classname>Math</classname> living in a package of your
-              choice:</para>
+        <qandaset defaultlabel="qanda" xml:id="sd1QandaMaxAbs">
+          <qandadiv>
+            <qandaentry>
+              <question>
+                <para>Implement a class method methods <methodname>double
+                abs(double)</methodname> and two overloaded methods
+                <methodname>double max(double, double)</methodname> and
+                <methodname>double max(double, double, double)</methodname> in
+                a class <classname>Math</classname> living in a package of
+                your choice:</para>
 
-              <programlisting language="java">package de.hdm_stuttgart.de.sd1.math;
+                <programlisting language="java">package de.hdm_stuttgart.de.sd1.math;
 
 /**
  * Some class methods.
@@ -3062,21 +3063,22 @@ public class Math {
   } 
 }</programlisting>
 
-              <para>Provide at at least 8 unit tests.</para>
-            </question>
+                <para>Provide at at least 8 unit tests.</para>
+              </question>
 
-            <answer>
-              <annotation role="make">
-                <para role="eclipse">Sd1/math/V0_5</para>
-              </annotation>
+              <answer>
+                <annotation role="make">
+                  <para role="eclipse">Sd1/math/V0_5</para>
+                </annotation>
 
-              <para>See <link
-              xlink:href="Ref/api/P/math/V0_5/de/hdm_stuttgart/de/sd1/math/Math.html">implementation
-              here.</link></para>
-            </answer>
-          </qandaentry>
-        </qandadiv>
-      </qandaset>
+                <para>See <link
+                xlink:href="Ref/api/P/math/V0_5/de/hdm_stuttgart/de/sd1/math/Math.html">implementation
+                here.</link></para>
+              </answer>
+            </qandaentry>
+          </qandadiv>
+        </qandaset>
+      </section>
 
       <section xml:id="sd1SectFactorialDirect">
         <title>Factorial, the direct way</title>
@@ -3636,6 +3638,384 @@ System.out.println(factorial(3));</programlisting>
         </qandaset>
       </section>
 
+      <section xml:id="sd1SectBinomRecursive">
+        <title>Binomials, the recursive way</title>
+
+        <qandaset defaultlabel="qanda" xml:id="sd1QandaBinomRecursive">
+          <qandadiv>
+            <qandaentry>
+              <question>
+                <para>With respect to the upcoming <link
+                linkend="sd1SectTicTacToeComputerVsHuman">tic-tac-toe strategy
+                exercise</link> we provide a second example of a recursively
+                defined method. Our binomial coefficients from our <link
+                linkend="sd1SectLotteryRevisited">lottery exercise</link> may
+                be computed in a recursive fashion. Consider pascal's
+                triangle: </para>
+
+                <figure xml:id="sd1FigPascalTriangle">
+                  <title>Pascal's triangle representing binomial
+                  coefficients.</title>
+
+                  <mediaobject>
+                    <imageobject>
+                      <imagedata fileref="Ref/Fig/pascal.fig"/>
+                    </imageobject>
+                  </mediaobject>
+                </figure>
+
+                <para>Each inner node within the triangle is the sum of its
+                two upper left and right neighbours. With respect to a
+                recursive definition <xref linkend="sd1FigPascalTriangle"/>
+                tells us:</para>
+
+                <glosslist>
+                  <glossentry>
+                    <glossterm>Reducing statement</glossterm>
+
+                    <glossdef>
+                      <para><inlineequation>
+                          <m:math display="inline">
+                            <m:mrow>
+                              <m:msub>
+                                <m:mo>∀</m:mo>
+
+                                <m:mrow>
+                                  <m:mi>0</m:mi>
+
+                                  <m:mo>&lt;</m:mo>
+
+                                  <m:mi>k</m:mi>
+
+                                  <m:mo>&lt;</m:mo>
+
+                                  <m:mi>n</m:mi>
+                                </m:mrow>
+                              </m:msub>
+
+                              <m:mi>:</m:mi>
+
+                              <m:mi> </m:mi>
+
+                              <m:mrow>
+                                <m:mrow>
+                                  <m:mo>(</m:mo>
+
+                                  <m:mrow>
+                                    <m:mtable>
+                                      <m:mtr>
+                                        <m:mtd>
+                                          <m:mrow>
+                                            <m:mi>n</m:mi>
+
+                                            <m:mo>+</m:mo>
+
+                                            <m:mi>1</m:mi>
+                                          </m:mrow>
+                                        </m:mtd>
+                                      </m:mtr>
+
+                                      <m:mtr>
+                                        <m:mtd>
+                                          <m:mrow>
+                                            <m:mi>k</m:mi>
+
+                                            <m:mo>+</m:mo>
+
+                                            <m:mi>1</m:mi>
+                                          </m:mrow>
+                                        </m:mtd>
+                                      </m:mtr>
+                                    </m:mtable>
+                                  </m:mrow>
+
+                                  <m:mo>)</m:mo>
+                                </m:mrow>
+                              </m:mrow>
+
+                              <m:mo>=</m:mo>
+
+                              <m:mrow>
+                                <m:mrow>
+                                  <m:mrow>
+                                    <m:mo>(</m:mo>
+
+                                    <m:mrow>
+                                      <m:mtable>
+                                        <m:mtr>
+                                          <m:mtd>
+                                            <m:mi>n</m:mi>
+                                          </m:mtd>
+                                        </m:mtr>
+
+                                        <m:mtr>
+                                          <m:mtd>
+                                            <m:mrow>
+                                              <m:mi>k</m:mi>
+
+                                              <m:mo>+</m:mo>
+
+                                              <m:mi>1</m:mi>
+                                            </m:mrow>
+                                          </m:mtd>
+                                        </m:mtr>
+                                      </m:mtable>
+                                    </m:mrow>
+
+                                    <m:mo>)</m:mo>
+                                  </m:mrow>
+                                </m:mrow>
+
+                                <m:mo>+</m:mo>
+
+                                <m:mrow>
+                                  <m:mrow>
+                                    <m:mo>(</m:mo>
+
+                                    <m:mrow>
+                                      <m:mtable>
+                                        <m:mtr>
+                                          <m:mtd>
+                                            <m:mi>n</m:mi>
+                                          </m:mtd>
+                                        </m:mtr>
+
+                                        <m:mtr>
+                                          <m:mtd>
+                                            <m:mi>k</m:mi>
+                                          </m:mtd>
+                                        </m:mtr>
+                                      </m:mtable>
+                                    </m:mrow>
+
+                                    <m:mo>)</m:mo>
+                                  </m:mrow>
+                                </m:mrow>
+                              </m:mrow>
+                            </m:mrow>
+                          </m:math>
+                        </inlineequation> .</para>
+
+                      <para>This equation is actually a straightforward
+                      exercise by simply adding two fractions. Wanna
+                      try?</para>
+                    </glossdef>
+                  </glossentry>
+
+                  <glossentry>
+                    <glossterm>Termination condition</glossterm>
+
+                    <glossdef>
+                      <para><inlineequation>
+                          <m:math display="inline">
+                            <m:mrow>
+                              <m:mrow>
+                                <m:mrow>
+                                  <m:mo>(</m:mo>
+
+                                  <m:mrow>
+                                    <m:mtable>
+                                      <m:mtr>
+                                        <m:mtd>
+                                          <m:mi>n</m:mi>
+                                        </m:mtd>
+                                      </m:mtr>
+
+                                      <m:mtr>
+                                        <m:mtd>
+                                          <m:mi>0</m:mi>
+                                        </m:mtd>
+                                      </m:mtr>
+                                    </m:mtable>
+                                  </m:mrow>
+
+                                  <m:mo>)</m:mo>
+                                </m:mrow>
+                              </m:mrow>
+
+                              <m:mo>=</m:mo>
+
+                              <m:mrow>
+                                <m:mrow>
+                                  <m:mo>(</m:mo>
+
+                                  <m:mrow>
+                                    <m:mtable>
+                                      <m:mtr>
+                                        <m:mtd>
+                                          <m:mi>n</m:mi>
+                                        </m:mtd>
+                                      </m:mtr>
+
+                                      <m:mtr>
+                                        <m:mtd>
+                                          <m:mi>n</m:mi>
+                                        </m:mtd>
+                                      </m:mtr>
+                                    </m:mtable>
+                                  </m:mrow>
+
+                                  <m:mo>)</m:mo>
+                                </m:mrow>
+                              </m:mrow>
+
+                              <m:mo>=</m:mo>
+
+                              <m:mi>1</m:mi>
+                            </m:mrow>
+                          </m:math>
+                        </inlineequation>.</para>
+
+                      <para>These are values from the left and right edge of
+                      <xref linkend="sd1FigPascalTriangle"/>.</para>
+                    </glossdef>
+                  </glossentry>
+                </glosslist>
+
+                <para>Tasks:</para>
+
+                <orderedlist>
+                  <listitem>
+                    <para>Re-implement <methodname>public static long
+                    binomial(int n, int k)</methodname> in a recursive fashion
+                    as outlined above.</para>
+
+                    <tip>
+                      <para>This is surprisingly simple. You may want to
+                      consider external resources dealing with the subject of
+                      recursively implemented methods.</para>
+                    </tip>
+                  </listitem>
+
+                  <listitem>
+                    <para>Compare the performance of your recursive
+                    implementation and the traditional loop based approach.
+                    The <quote>6 out of 90</quote> lottery is a good starting
+                    point.</para>
+
+                    <tip>
+                      <para>Measuring method execution times is simple using
+                      either <link
+                      xlink:href="https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#currentTimeMillis--">currentTimeMillis()</link>
+                      or <link
+                      xlink:href="https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#nanoTime--">nanoTime</link>.
+                      <quote
+                      xlink:href="http://www.mkyong.com/java/how-do-calculate-elapsed-execute-time-in-java">See
+                      How to calculate elapsed / execute time in
+                      Java</quote>.</para>
+                    </tip>
+                  </listitem>
+
+                  <listitem>
+                    <para>Reuse your unit tests from the <link
+                    linkend="sd1SectLotteryRevisited">lottery
+                    exercise</link>.</para>
+                  </listitem>
+                </orderedlist>
+              </question>
+
+              <answer>
+                <annotation role="make">
+                  <para role="eclipse">Sd1/Binomial/V3</para>
+                </annotation>
+
+                <para>The implementation is surprisingly simple:</para>
+
+                <programlisting language="java">  public static long binomial(int n, int k) {
+    
+    if (0 == k || n == k) { // End of recursion?
+      return 1;
+    } else { // Continue reducing: 0 &lt; k  &lt; n holds true.
+      return binomial(n - 1, k) + binomial(n - 1, k - 1);
+    }
+  }</programlisting>
+
+                <para>For the purpose of comparison we rename the
+                <quote>traditional</quote> loop based implementation as
+                <methodname>static public long binomialLoop(int n, int
+                k)</methodname> and add a performance test:</para>
+
+                <informaltable border="1">
+                  <colgroup width="10%"/>
+
+                  <colgroup width="90%"/>
+
+                  <tr>
+                    <th>Code</th>
+
+                    <td valign="top"><programlisting language="java">  public static void main(String[] args) {
+
+    long recursiveTime = 0, loopTime = 0;
+    
+    for (int i = 0; i &lt; 10; i++) {
+      {
+        final long start = System.nanoTime();
+        System.out.println(Binomial.binomial(90, 6));
+        final long duration = (System.nanoTime() - start);
+        recursiveTime += duration;
+        System.out.println("Recursive: Elapsed time:" + duration);
+      }
+      {
+        final long start = System.nanoTime();
+        System.out.println(Binomial.binomialLoop(90, 6));
+        final long duration = (System.nanoTime() - start);
+        loopTime += duration;
+        System.out.println("Loop: Elapsed time:" + duration);
+      }
+      System.out.println("           End of run #" + i + " -------------------------------");
+    }
+    System.out.println("Aggregated loop time: " + loopTime);
+    System.out.println("Aggregated recursion time: " + recursiveTime);
+    System.out.println("Ratio Recursive / Loop: " + (recursiveTime / loopTime));
+  }</programlisting></td>
+                  </tr>
+
+                  <tr>
+                    <th>Result</th>
+
+                    <td valign="top"><programlisting language="none">622614630
+Recursive: Elapsed time:1801476567
+622614630
+Loop: Elapsed time:27028
+           End of run #0 -------------------------------
+622614630
+Recursive: Elapsed time:1748821324
+622614630
+Loop: Elapsed time:22768
+           End of run #1 -------------------------------
+...
+           End of run #9 -------------------------------
+Aggregated loop time: 267557
+Aggregated recursion time: 17539461906
+Ratio Recursive / Loop: 65554</programlisting></td>
+                  </tr>
+                </informaltable>
+
+                <para>From a performance point of view this result is quite
+                disillusioning: The loop based implementation is on average
+                ~65000 times faster than the recursive approach. </para>
+
+                <para>This is a frequent result: Albeit providing elegant
+                solutions using recursion in many situations is a <emphasis
+                role="bold">very bad</emphasis> idea and thus strongly
+                discouraged. There are however situations where:</para>
+
+                <orderedlist>
+                  <listitem>
+                    <para>The performance penalty is not that large.</para>
+                  </listitem>
+
+                  <listitem>
+                    <para>Recursion is the (maybe only) way to implement a
+                    desired logic.</para>
+                  </listitem>
+                </orderedlist>
+              </answer>
+            </qandaentry>
+          </qandadiv>
+        </qandaset>
+      </section>
+
       <section xml:id="sd1SecExp">
         <title>Implementing exponentials.</title>
 
diff --git a/P/Sd1/Binomial/V3/.gitignore b/P/Sd1/Binomial/V3/.gitignore
new file mode 100644
index 000000000..cf5fd6bb2
--- /dev/null
+++ b/P/Sd1/Binomial/V3/.gitignore
@@ -0,0 +1,5 @@
+/.settings
+/target
+/.classpath
+/.project
+/A1.log
diff --git a/P/Sd1/Binomial/V3/pom.xml b/P/Sd1/Binomial/V3/pom.xml
new file mode 100644
index 000000000..e53220296
--- /dev/null
+++ b/P/Sd1/Binomial/V3/pom.xml
@@ -0,0 +1,20 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>de.hdm-stuttgart.mi</groupId>
+    <artifactId>lecturenotes-pom</artifactId>
+    <version>1.0</version>
+    <relativePath>../../../pom.xml</relativePath>
+  </parent>
+
+  <groupId>de.hdm-stuttgart.de.sd1</groupId>
+  <artifactId>binomial</artifactId>
+  <version>1.3</version>
+  <packaging>jar</packaging>
+
+  <name>Binomial</name>
+  <url>http://www.mi.hdm-stuttgart.de/freedocs</url>
+
+</project>
diff --git a/P/Sd1/Binomial/V3/src/main/java/de/hdm_stuttgart/mi/sd1/binomial/Binomial.java b/P/Sd1/Binomial/V3/src/main/java/de/hdm_stuttgart/mi/sd1/binomial/Binomial.java
new file mode 100644
index 000000000..1fc377f54
--- /dev/null
+++ b/P/Sd1/Binomial/V3/src/main/java/de/hdm_stuttgart/mi/sd1/binomial/Binomial.java
@@ -0,0 +1,42 @@
+package de.hdm_stuttgart.mi.sd1.binomial;
+
+public class Binomial {
+
+  static public long binomial(int n, int k) {
+    
+    if (0 == k || n == k) { // End of recursion?
+      return 1;
+    } else { // Continue reducing: 0 < k  < n holds true.
+      return binomial(n - 1, k) + binomial(n - 1, k - 1);
+    }
+  }
+
+  static public long binomialLoop(int n, int k) {
+
+    // Trying to avoid arithmetic overflow by making use of:
+    //             n        n
+    //           (   ) =  (   )
+    //             k       n-k
+    //
+    if (n / 2 < k) {
+      k = n - k;
+    }
+
+    // Numerator product n (n - 1) ... (n - k + 1)
+    long numerator = 1;
+    for (int i = n - k + 1; i <= n; i++) {
+      numerator *= i;
+    }
+    return numerator / factorial(k);
+  }
+
+  public static long factorial(int n) {
+    long ret = 1;
+
+    for (int i = 2; i <= n; i++) {
+      ret *= i;
+    }
+    return ret;
+  }
+
+}
diff --git a/P/Sd1/Binomial/V3/src/main/java/de/hdm_stuttgart/mi/sd1/binomial/Lottery.java b/P/Sd1/Binomial/V3/src/main/java/de/hdm_stuttgart/mi/sd1/binomial/Lottery.java
new file mode 100644
index 000000000..7a4dd57f1
--- /dev/null
+++ b/P/Sd1/Binomial/V3/src/main/java/de/hdm_stuttgart/mi/sd1/binomial/Lottery.java
@@ -0,0 +1,18 @@
+package de.hdm_stuttgart.mi.sd1.binomial;
+
+public class Lottery {
+
+  public static void main(String[] args) {
+
+    // Input values:
+    final int
+      totalNumberCount = 49,
+      drawnNumberCount = 6;
+    
+    System.out.println(
+        "Your chance to win when drawing " + drawnNumberCount + 
+        " out of " + totalNumberCount + 
+        " is 1 : " + Binomial.binomial(totalNumberCount, drawnNumberCount));
+  }
+  
+}
diff --git a/P/Sd1/Binomial/V3/src/main/java/de/hdm_stuttgart/mi/sd1/binomial/PerformanceTest.java b/P/Sd1/Binomial/V3/src/main/java/de/hdm_stuttgart/mi/sd1/binomial/PerformanceTest.java
new file mode 100644
index 000000000..642f9db8c
--- /dev/null
+++ b/P/Sd1/Binomial/V3/src/main/java/de/hdm_stuttgart/mi/sd1/binomial/PerformanceTest.java
@@ -0,0 +1,30 @@
+package de.hdm_stuttgart.mi.sd1.binomial;
+
+public class PerformanceTest {
+
+  public static void main(String[] args) {
+
+    long recursiveTime = 0, loopTime = 0;
+    
+    for (int i = 0; i < 10; i++) {
+      {
+        final long start = System.nanoTime();
+        System.out.println(Binomial.binomial(90, 6));
+        final long duration = (System.nanoTime() - start);
+        recursiveTime += duration;
+        System.out.println("Recursive: Elapsed time:" + duration);
+      }
+      {
+        final long start = System.nanoTime();
+        System.out.println(Binomial.binomialLoop(90, 6));
+        final long duration = (System.nanoTime() - start);
+        loopTime += duration;
+        System.out.println("Loop: Elapsed time:" + duration);
+      }
+      System.out.println("           End of run #" + i + " -------------------------------");
+    }
+    System.out.println("Aggregated loop time: " + loopTime);
+    System.out.println("Aggregated recursion time: " + recursiveTime);
+    System.out.println("Ratio Recursive / Loop: " + (recursiveTime / loopTime));
+  }
+}
diff --git a/P/Sd1/Binomial/V3/src/test/java/de/hdm_stuttgart/mi/sd1/binomial/test/BinomTest.java b/P/Sd1/Binomial/V3/src/test/java/de/hdm_stuttgart/mi/sd1/binomial/test/BinomTest.java
new file mode 100644
index 000000000..fa8c806ab
--- /dev/null
+++ b/P/Sd1/Binomial/V3/src/test/java/de/hdm_stuttgart/mi/sd1/binomial/test/BinomTest.java
@@ -0,0 +1,60 @@
+package de.hdm_stuttgart.mi.sd1.binomial.test;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import de.hdm_stuttgart.mi.sd1.binomial.Binomial;
+
+public class BinomTest {
+
+  @Test
+  public void test_0_0() {
+    Assert.assertEquals(1, Binomial.binomial(0, 0));
+  }
+  
+  @Test
+  public void test_1_0() {
+    Assert.assertEquals(1, Binomial.binomial(1, 0));
+  }
+  
+  @Test
+  public void test_1_1() {
+    Assert.assertEquals(1, Binomial.binomial(1, 1));
+  }
+  
+  @Test
+  public void test_4_3() {
+    Assert.assertEquals(4, Binomial.binomial(4, 3));
+  }
+  
+  @Test
+  public void test_5_3() {
+    Assert.assertEquals(10, Binomial.binomial(5, 3));
+  }
+  
+  @Test
+  public void test_20_20() {
+    Assert.assertEquals(1, Binomial.binomial(20, 20));
+  }
+
+  // Possible arithmetic overflow situations.
+  @Test
+  public void test_22_1() {
+    Assert.assertEquals(22, Binomial.binomial(22, 1));
+  }
+
+  @Test
+  public void test_22_21() {
+    Assert.assertEquals(22, Binomial.binomial(22, 21));
+  }
+
+  @Test
+  public void test_22_2() {
+    Assert.assertEquals(231, Binomial.binomial(22, 2));
+  }
+
+  @Test
+  public void test_22_20() {
+    Assert.assertEquals(231, Binomial.binomial(22, 20));
+  }
+}
diff --git a/P/pom.xml b/P/pom.xml
index 110347e76..5c2bdc652 100644
--- a/P/pom.xml
+++ b/P/pom.xml
@@ -31,6 +31,9 @@
     <module>Sd1/Array/integerStore</module>
     <module>Sd1/Array/integerStoreMedianAnswer</module>
 
+    <module>Sd1/Binomial/V1</module>
+    <module>Sd1/Binomial/V3</module>
+
     <module>Sd1/CarJump/V1</module>
     <module>Sd1/CarJump/V2</module>
     <module>Sd1/CarJump/V5</module>
-- 
GitLab