<?xml version="1.0" encoding="UTF-8"?> <chapter annotations="slide" version="5.1" xml:id="sw1ChapterArrays" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xila="http://www.w3.org/2001/XInclude/local-attributes" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:svg="http://www.w3.org/2000/svg" xmlns:ns="http://docbook.org/ns/transclusion" xmlns:m="http://www.w3.org/1998/Math/MathML" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:db="http://docbook.org/ns/docbook"> <title>Arrays</title> <info> <abstract> <para>Multiple values of common type.</para> <para>Loop style handling.</para> </abstract> </info> <figure xml:id="sd1_array_fig_arrayMotivate"> <title>Motivating Arrays</title> <programlisting language="java">final String karen = "Karen Smith", john = "John Duncan", paul = "Paul Jacobs", suzanne = "Suzanne Enders", peter = "Peter Phillips"; // 10 more to come ... System.out.println(karen); System.out.println(john); ...</programlisting> </figure> <figure xml:id="sd1_array_fig_arrayRepeatingTasks"> <title>Per member repeating tasks</title> <itemizedlist> <listitem> <para>Generate Comma separated list:</para> <screen>Karen Smith, John Duncan, Paul Jacobs, Suzanne Enders, Peter Phillips</screen> </listitem> <listitem> <para>Generate HTML list emphasizing family names:</para> <programlisting language="xml"><ul> <li>Karen <emph>Smith</emph></li> <li>John <emph>Duncan</emph></li> <li>Paul <emph>Jacobs</emph></li> <li>Suzanne <emph>Enders</emph></li> <li>Peter <emph>Phillips</emph></li> </ul></programlisting> </listitem> </itemizedlist> </figure> <figure xml:id="sd1_array_fig_arrayStringExample"> <title>Example: <code language="java">int</code> array of primes</title> <programlisting language="java">final int[] primes <co linkends="sd1_array_fig_arrayStringExample-1.2" xml:id="sd1_array_fig_arrayStringExample-1.2-co"/> = new int[5]; <co linkends="sd1_array_fig_arrayStringExample-2.2" xml:id="sd1_array_fig_arrayStringExample-2.2-co"/> primes[0] = 2; <co linkends="sd1_array_fig_arrayStringExample-3" xml:id="sd1_array_fig_arrayStringExample-3-co"/> primes[1] = 3; primes[2] = 5; primes[3] = 7; primes[4] = 11;</programlisting> <calloutlist role="slideExclude"> <callout arearefs="sd1_array_fig_arrayStringExample-1.2-co" xml:id="sd1_array_fig_arrayStringExample-1.2"> <para><code language="java">int</code> array reference variable <code language="java">primes</code>.</para> </callout> <callout arearefs="sd1_array_fig_arrayStringExample-2.2-co" xml:id="sd1_array_fig_arrayStringExample-2.2"> <para><code language="java">int</code> array allocation capable to store five values and assigning its reference to variable <code language="java">primes</code>.</para> </callout> <callout arearefs="sd1_array_fig_arrayStringExample-3-co" xml:id="sd1_array_fig_arrayStringExample-3"> <para>Assigning values referencing array positions by index values from {0,1,2,3,4}.</para> </callout> </calloutlist> </figure> <qandaset defaultlabel="qanda" xml:id="sd1_array_qanda_arrayAndFinal"> <title>Assignment to final variable?</title> <qandadiv> <qandaentry> <question> <para>In <xref linkend="sd1_array_fig_arrayStringExample"/> a <code language="java">final</code> variable <code language="java">primes</code> is being declared. Despite the <code language="java">final</code> modifier denoting constant values we see a whole bunch of assignments i.e. <code language="java">primes[0] = 2</code>. Give an explanation.</para> </question> <answer> <para>The variable <code language="java">primes</code> carries a reference to an array. The final modifier declares this reference to become non-modifiable. Changing the array's values themselves is not being restricted. Consider:</para> <programlisting language="java">final int[] primes = new int[5]; primes[0] = 0; // O.k.: Changing first array value primes = new int[3]; // Error: Cannot assign a value to final variable 'primes'</programlisting> </answer> </qandaentry> </qandadiv> </qandaset> <figure xml:id="sd1_array_fig_arrayPrimeLoop"> <title>Loop prime values</title> <programlisting language="java">for (int i = 0; i < 5; i++) { System.out.println("At index " + i + ": value == " + primes[i]); }</programlisting> <para>Result:</para> <screen>At index 0: value == 2 At index 1: value == 3 At index 2: value == 5 At index 3: value == 7 At index 4: value == 11</screen> </figure> <figure xml:id="sd1_array_fig_arrayPrimeMindLimit"> <title>Mind the limit!</title> <informaltable border="0"> <tr> <td valign="top"><programlisting language="none">for (int i = 0; <emphasis role="red">i < 6</emphasis>; i++) { System.out.println("At index " + i + ": value == " + primes[i]); }</programlisting></td> </tr> <tr> <td valign="top">Result:</td> </tr> <tr> <td valign="top"><screen>At index 0: value == 2 At index 1: value == 3 At index 2: value == 5 At index 3: value == 7 At index 4: value == 11 Exception in thread "main" java.lang.<emphasis role="red">ArrayIndexOutOfBoundsException</emphasis>: 5 at qq.arrayex.Motivate.main(Motivate.java:27)</screen></td> </tr> </informaltable> </figure> <figure xml:id="sd1_array_fig_arrayPrimeArrayLength"> <title>Safer: Using <parameter>length</parameter></title> <informaltable border="0"> <colgroup width="8%"/> <colgroup width="92%"/> <tr> <td colspan="2" valign="top"><programlisting language="none">System.out.println("primes.length == " + <emphasis role="red">primes.length</emphasis>); for (int i = 0; <emphasis role="red">i < primes.length</emphasis>; i++) { System.out.println("At index " + i + ": value == " + primes[i]); }</programlisting></td> </tr> <tr> <td valign="top">Result:</td> <td valign="top"><screen>primes.length == 5 At index 0: value == 2 At index 1: value == 3 At index 2: value == 5 At index 3: value == 7 At index 4: value == 11</screen></td> </tr> </informaltable> </figure> <figure xml:id="sd1_array_fig_arrayForEachLoop"> <title>Even better: <quote>for-each</quote> style loop</title> <informaltable border="0"> <colgroup width="8%"/> <colgroup width="92%"/> <tr> <td colspan="2" valign="top"><programlisting language="java">for (final int p: primes) { System.out.println("value == " + p); }</programlisting></td> </tr> <tr> <td valign="top">Result:</td> <td valign="top"><screen>value == 2 value == 3 value == 5 value == 7 value == 11</screen></td> </tr> </informaltable> </figure> <figure xml:id="sd1_array_fig_arraySizeInit"> <title>Mind the limit, part two</title> <informaltable border="0"> <colgroup width="8%"/> <colgroup width="92%"/> <tr> <td valign="top"><programlisting language="none">final int[] primes = new int[<emphasis role="red">5</emphasis>]; // Last index is <emphasis role="red">4</emphasis> rather than <emphasis role="red">5</emphasis>! primes[0] = 2; primes[1] = 3; primes[2] = 5; primes[3] = 7; primes[4] = 11; <emphasis role="red">primes[5]</emphasis> = 13; // Excessing array limit</programlisting></td> </tr> <tr> <td valign="top">Result:</td> </tr> <tr> <td valign="top"><screen>Exception in thread "main" java.lang.<emphasis role="red">ArrayIndexOutOfBoundsException</emphasis>: 5 at qq.arrayex.Motivate.main(Motivate.java:25)</screen></td> </tr> </informaltable> </figure> <figure xml:id="sd1_array_fig_arrayInitByValueSet"> <title>One step initialization</title> <para>Combining array allocation and value assignment:</para> <informaltable border="0"> <colgroup width="45%"/> <colgroup width="55%"/> <tr> <td valign="top"><programlisting language="java">final int[] primes = {2, 3, 5, 7, 11};</programlisting></td> <td valign="top"><programlisting language="java">final int[] primes = new int[5]; primes[0] = 2; primes[1] = 3; primes[2] = 5; primes[3] = 7; primes[4] = 11;</programlisting></td> </tr> </informaltable> </figure> <qandaset defaultlabel="qanda" xml:id="sd1QandaArray2html"> <title>Converting string arrays to <xref linkend="glo_HTML"/>.</title> <qandadiv> <qandaentry> <question> <para>Consider an array of strings. As an example we provide a list of country names:</para> <programlisting language="java">final String[] countries = { "England" ,"France" ,"Germany" };</programlisting> <para>An application is supposed to generate the following output:</para> <programlisting language="xml"><ul> <li>England</li> <li>France</li> <li>Germany</li> </ul></programlisting> <para>Implement A class method <methodname>strings2html(final String [] strings)</methodname> as in:</para> <programlisting language="java">public class Stringarray2Html { /** * Create an unordered ... * ... */ static public String strings2html(final String [] strings) { ... return ...; } }</programlisting> <para>Do not forget to provide appropriate <xref linkend="glo_Javadoc"/> method and class documentation. You may want to reconsider <xref linkend="sd1_fig_mavenJavadoc"/>.</para> <para>Generating <xref linkend="glo_Javadoc"/> HTML documentation from your project should yield a result like:</para> <mediaobject> <imageobject> <imagedata fileref="Fig/strings2html.png"/> </imageobject> </mediaobject> <para>Provide appropriate unit tests covering at least:</para> <itemizedlist> <listitem> <para>An empty input array.</para> </listitem> <listitem> <para>An input array containing at least two strings.</para> </listitem> </itemizedlist> </question> <answer> <annotation role="make"> <para role="eclipse">P/Sd1/Array/StringArray2Html</para> </annotation> </answer> </qandaentry> </qandadiv> </qandaset> <qandaset defaultlabel="qanda" xml:id="sd1QandaNavigation"> <title>Route navigation</title> <qandadiv> <qandaentry> <question> <para>We want to estimate the amount of time being required driving a particular route. Consider the following example:</para> <informalfigure> <mediaobject> <imageobject> <imagedata fileref="Fig/navigationSections.png"/> </imageobject> </mediaobject> </informalfigure> <para>The route above may be dissected into several legs:</para> <orderedlist> <listitem> <para>From starting point to motorway</para> </listitem> <listitem> <para>Motorway till through road</para> </listitem> <listitem> <para>Through road till junction</para> </listitem> <listitem> <para>Junction till destination</para> </listitem> </orderedlist> <para>Each leg may have a different speed limit. We thus define:</para> <programlisting language="java">public class Segment { /** * Indication a segment does not have any speed limit. */ static public final int NO_SPEED_LIMIT = 0; /** * The distance of the current leg in km. */ public final double distance; /** * The current leg's speed limit in km / h. */ public final int speedLimit; /** * Creating an (immutable) leg * @param distance {@link #distance} * @param speedLimit {@link #speedLimit} */ public Segment(final double distance, final int speedLimit) { this.distance = distance; this.speedLimit = speedLimit; } }</programlisting> <para>A given route will be defined by an array of segments:</para> <programlisting language="java">final Segment[] route = new Segment[] { new Segment(2.4, 50) ,new Segment(5, 100) ,new Segment(3.1, 50) ,new Segment(0.8, 30) };</programlisting> <para>Implement a method <methodname>duration(...)</methodname> which allows for calculation the minimum expected time required with respect to speed limits along a given route.</para> <programlisting language="java">/** * Minimal time required when consequently traveling with the minimum of * official speed limits and the driver's personal maximum speed. If a * leg does not have any speed limit the value of personalSpeedLimit will * be used for calculation instead. * * @param route The array of segments composing a route. * * @param personalSpeedLimit The drivers personal speed limit whether or * not official limits apply. Must be greater than 0. * * @return The minimal duration in (rounded) minutes with respect to all * speed limits. Must be a positive (non-zero) value. */ static public long duration(Segment[] route, int personalSpeedLimit) { return 0; // TODO } </programlisting> <para>Write <xref linkend="glo_Junit"/> tests to cover different situations.</para> <tip> <para>You may want to start implementing a main() method example first to gain some experience:</para> <programlisting language="java">public class Driver { /** * @param args unused */ public static void main(String[] args) { final Segment[] route = new Segment[] { new Segment(2.4, 50) ,new Segment(5, 100) ,new Segment(3.1, 50) ,new Segment(0.8, 30) }; ... final long fullMinutes = ...; System.out.println("Minimal duration:" + fullMinutes); }</programlisting> </tip> </question> <answer> <annotation role="make"> <para role="eclipse">P/Sd1/Navigation/V2</para> </annotation> </answer> </qandaentry> </qandadiv> </qandaset> <qandaset defaultlabel="qanda" xml:id="sd1QandaMarkFrequencies"> <title>Examinations and mark frequencies</title> <qandadiv> <qandaentry> <question> <para>Consider an examination resulting in the following list of marks:</para> <informaltable border="1"> <tr> <th>Participant no.</th> <td>1</td> <td>2</td> <td>3</td> <td>4</td> <td>5</td> <td>6</td> <td>7</td> <td>8</td> <td>9</td> <td>10</td> <td>11</td> <td>12</td> <td>13</td> <td>14</td> <td>15</td> <td>16</td> <td>17</td> <td>18</td> </tr> <tr> <th>Mark</th> <td>2</td> <td>1</td> <td>3</td> <td>3</td> <td>5</td> <td>4</td> <td>1</td> <td>2</td> <td>2</td> <td>4</td> <td>3</td> <td>2</td> <td>3</td> <td>3</td> <td>1</td> <td>5</td> <td>3</td> <td>4</td> </tr> </informaltable> <para>You may represent this examination result by:</para> <programlisting language="java">final int[] marks = {2,1,3,3,5,4,1,2,2,4,3,2,3,3,1,5,3,4};</programlisting> <para>Lecturers and participants may be interested in the distribution of marks <abbrev>i.e.</abbrev> their frequencies. Thus having marks in a range from 1 to 5 in the given example we'd like to create the following overview of marks:</para> <informaltable border="1"> <tr> <th>Mark</th> <th>Frequency</th> </tr> <tr> <td>1</td> <td>3</td> </tr> <tr> <td>2</td> <td>4</td> </tr> <tr> <td>3</td> <td>6</td> </tr> <tr> <td>4</td> <td>3</td> </tr> <tr> <td>5</td> <td>2</td> </tr> </informaltable> <para>Write a <xref linkend="glo_Java"/> application turning an array of participants' marks into the above table of marks among with their respective frequencies. For the given example the intended terminal output reads:</para> <screen>Mark|frequency ----+--------- 1|3 2|4 3|6 4|3 5|2</screen> <para>Your application shall work for other marking schemes (<abbrev>i.e.</abbrev> marks ranging from -2 to 10) as well. Define a suitable class like:</para> <programlisting language="java">public class MarkFrequencies { public final int[] frequencyByMark; public final int lowestMarkValue; public MarkFrequencies(final int[] markValues) { ... } }</programlisting> <para>The constructor assigning values to both <code language="java">lowestMarkValue</code> and <code language="java">frequencyByMark</code> and is not yet implemented. Upon completion you may use class <classname>MarkFrequencies</classname> for producing the previously detailed terminal output:</para> <programlisting language="java">final MarkFrequencies markFrequencies = new MarkFrequencies(new int[]{2,1,3,3,5,4,1,2,2,4,3,2,3,3,1,5,3,4}); // Create overview of marks: // System.out.println("Mark|frequency"); System.out.println("----+---------"); for (int i = 0; i < markFrequencies.frequencyByMark.length ; i++) { System.out.println(" " + (markFrequencies.lowestMark + i) + "|" + markFrequencies.frequencyByMark[i]); }</programlisting> <para>Provide appropriate unit tests beforehand.</para> <tip> <orderedlist> <listitem> <para>Get the minimum and maximum mark of all participants beforehand.</para> </listitem> <listitem> <para>Create the <code language="java">int[] frequencyByMark</code> array. Since you already know both your mark list's minimum and maximum the frequencies array's size is thus determined. Shift each mark by the mark list's minimum and regard each mark as an index value. Example:</para> <itemizedlist> <listitem> <para>The list of marks is {-2, -1, 0, 1, 2, 3}.</para> </listitem> <listitem> <para>The minimum mark is -2 and the maximum equals 3.</para> </listitem> <listitem> <para>The list of marks shifted by -2 will start with 0:</para> </listitem> <listitem> <para>{0, 1, 2, 3, 4, 5}</para> </listitem> <listitem> <para>The array of mark frequencies thus contains 6 elements.</para> </listitem> </itemizedlist> </listitem> </orderedlist> </tip> <para>After implementing your method extend your application to allow for being called from the command line like:</para> <screen>marking> mvn package .... marking> <emphasis role="bold">java -jar target/marking-0.9.jar</emphasis> 2 1 3 3 5 4 1 2 2 4 3 2 3 3 1 5 3 4 Mark|frequency ----+--------- 1|3 2|4 3|6 4|3 5|2</screen> <para>This requires evaluating the <emphasis role="red">args</emphasis> parameter from your <methodname>main(String[] <emphasis role="red">args</emphasis>)</methodname> method.</para> <tip> <orderedlist> <listitem> <para>Converting a string like "5" into an int value of 5 may be achieved using:</para> <para><programlisting language="java">int value = <link xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Integer.html#valueOf(java.lang.String)">Integer.valueOf()</link></programlisting></para> </listitem> <listitem> <para>The <productname>maven-shade-plugin</productname> inside your project's <filename>pom.xml</filename> allows for creating executable jar archives. If your <methodname>main(...)</methodname> method is being defined in a class <package>de.hdm_stuttgart.mi.marking</package>.<classname>Marks</classname> . You may define this class to become the overall execution entry point by virtue of a corresponding <filename>pom.xml</filename> entry:</para> <programlisting language="none">... <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.1.0</version> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <manifestEntries> <Main-Class><emphasis role="red">de.hdm_stuttgart.mi.marking.Marks</emphasis></Main-Class> </manifestEntries> </transformer> </transformers> </configuration> <executions> <execution> <phase><emphasis role="red">package</emphasis></phase> <goals> <goal>shade</goal> </goals> </execution> </executions> </plugin> ...</programlisting> <para>Executing <command>mvn</command> <option xlink:href="https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html#A_Build_Lifecycle_is_Made_Up_of_Phases">package</option> will then create an executable jar archive as outlined above.</para> </listitem> </orderedlist> </tip> </question> <answer> <annotation role="make"> <para role="eclipse">P/Sd1/Array/marking</para> </annotation> <para>The method <methodname>int[] de.hdm_stuttgart.mi.marking.Marks.getFrequencies(int[] values)</methodname> is being defined in a slightly more general way possibly being useful in similar situations as well. This way it becomes subject to unit testing:</para> <programlisting language="java">public class AppTest { @Test public void testSingle() { Assert.assertArrayEquals( new int[]{1}, Marks.getFrequencies(new int[]{-3})); } @Test public void testMultiple() { Assert.assertArrayEquals( new int[]{2, 1, 0, 0, 0, 2, 0, 3}, Marks.getFrequencies(new int[]{-3, 4 , 2, -2, 4, -3, 2, 4})); } }</programlisting> </answer> </qandaentry> </qandadiv> </qandaset> <qandaset defaultlabel="qanda" xml:id="sd1QandaPangram"> <title><acronym>Pangram</acronym> checker</title> <qandadiv> <qandaentry> <question> <para>A <acronym>pangram</acronym> is a string containing all letters of a given alphabet at least once. As an example we consider the alphabet of <xref linkend="glo_ASCII"/> letters <code>{'a', 'b', ..., 'z'}</code> ignoring case. Then the following string is a <acronym>pangram</acronym>:</para> <blockquote> <para>The quick brown fox jumps over the lazy dog</para> </blockquote> <tip> <orderedlist> <listitem> <para>Like in <xref linkend="sd1QandaMarkFrequencies"/> create an array of sufficient size regarding each character as an index value.</para> </listitem> <listitem> <para>According to the <xref linkend="glo_ASCII"/> table all characters <code>{'a', 'b', ..., 'z'}</code> form a gapless sequence of integer values {97, 98,..., 122}.</para> </listitem> <listitem> <para><methodname xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html#toCharArray()">toCharArray()</methodname> allows for de-composing a String into a corresponding array of char values.</para> </listitem> <listitem> <para>Normalize strings with respect to case using <methodname xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html#toLowerCase()">toLowerCase(...)</methodname>.</para> </listitem> </orderedlist> </tip> </question> <answer> <annotation role="make"> <para role="eclipse">P/Sd1/Array/pangram</para> </annotation> <para>In addition to the above <quote>regular</quote> solution we also provide an approach featuring <xref linkend="glo_Java"/> streams with respect to the upcoming <quote>Software development 2</quote> lecture:</para> <programlisting language="java">static public boolean isPangram2(final String s) { return 26 == s.toLowerCase().chars() .filter(i -> i >= 'a' && i <= 'z') .distinct() .count(); }</programlisting> </answer> </qandaentry> </qandadiv> </qandaset> <figure xml:id="sd1_array_fig_arrayDefinition"> <title>Array</title> <itemizedlist> <listitem> <para>Series of objects having identical type.</para> </listitem> <listitem> <para>Array consists of array elements.</para> </listitem> <listitem> <para>Element access by index value.</para> </listitem> <listitem> <para>Holding either primitive types or object references.</para> </listitem> <listitem> <para>Contiguous storage in memory.</para> </listitem> <listitem> <para>Arbitrary dimensions: One-dimensional, two-dimensional etc.</para> </listitem> </itemizedlist> </figure> <figure xml:id="sd1_array_fig_arraySyntax"> <title>Two syntax variants</title> <orderedlist> <listitem> <programlisting language="java">type[] arrayName; // preferred</programlisting> </listitem> <listitem> <programlisting language="java">type arrayName[];</programlisting> </listitem> </orderedlist> </figure> <figure xml:id="sd1_array_fig_arrayTypeDefinition"> <title>Array instances are special!</title> <programlisting language="java">...println(" String: " + "".getClass().getName()); ...println(" int[]: " + new int[]{}.getClass().getName()); ...println(" double[]: " + new double[]{}.getClass().getName()); ...println(" boolean[]: " + new boolean[]{}.getClass().getName()); ...println(" String[]: " + new String[]{}.getClass().getName()); ...println("StringBuffer[]: " + new StringBuffer[]{}.getClass().getName());</programlisting> <screen> String: java.lang.String int[]: [I double[]: [D boolean[]: [Z String[]: [Ljava.lang.String; StringBuffer[]: [Ljava.lang.StringBuffer;</screen> </figure> <figure xml:id="sd1_array_fig_arrayDefMemoryDetails"> <title>Array creation details</title> <mediaobject> <imageobject> <imagedata fileref="Fig/intArray.multi.svg"/> </imageobject> </mediaobject> </figure> <figure xml:id="sd1_array_fig_arrayMethodCall"> <title>Array parameter passing</title> <programlisting language="java">public static void main(String[] args) { final int [] lectures = new int[3]; // Three lectures fill(lectures, 25); // Default lecture having 25 participants System.out.println("Second lecture has got " + lectures[1] + " participants"); } /** * Initialize array with default value. * * @param values Array to be initialized. * @param common Common value for all array elements. */ static void fill(final int[] values, final int common) { for (int i = 0; i < values.length; i++) { values[i] = common; } }</programlisting> <screen>Second lecture has got 25 participants</screen> </figure> <figure xml:id="sd1_array_fig_arrayMethodCallMemory"> <title>Parameter passing details</title> <mediaobject> <imageobject> <imagedata fileref="Fig/initArrayDefault.multi.svg"/> </imageobject> </mediaobject> </figure> <figure xml:id="sd1_array_fig_arrayValueReferenceType"> <title>Value and reference types</title> <programlisting language="java">// Value type final boolean values[] = new boolean[]{true, true, false, true}; // Reference type final String shapes[] = new String[]{"Triangle", "Circle"};</programlisting> <para>Same result:</para> <programlisting language="java">final boolean values[] = {true, true, false, true}; final String shapes[] = {"Triangle", "Circle"};</programlisting> </figure> <section xml:id="sd1SectVarargsFormat"> <title>Reconsidering System.out.format().</title> <qandaset defaultlabel="qanda" xml:id="sd1QandaVarargsFormat"> <qandadiv> <qandaentry> <question> <para>This exercise aims at a better understanding of <code language="java">System.out.<link xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/PrintStream.html#format(java.lang.String,java.lang.Object...)">format()</link></code> already being used in <xref linkend="sd1QandaSquareNumberTableFormatted"/> and other exercises. Consider the following snippet:</para> <programlisting language="java">int value = 33; double secondValue = 114.317; System.out.format("Just a single integer %3d\n", value /* Just a single value to be printed */); System.out.format("An integer %3d and a double value %6.2f\n", value, secondValue);</programlisting> <para>Something seems to be odd here: The format() method is being called with a different number of arguments. Actually we may call it with an arbitrary number of one or more arguments. Answer the following two questions:</para> <orderedlist> <listitem> <para>How does this work (syntactically) ?</para> <tip> <para>The underlying mechanism is called <quote>varargs</quote> or <quote>ellipsis</quote> being closely related to arrays. Read either of (or all):</para> <itemizedlist> <listitem> <para><link xlink:href="https://dzone.com/articles/uncommon-java-syntax-the-ellipses">Uncommon Java Syntax: Ellipses…</link></para> </listitem> <listitem> <para><link xlink:href="https://www.baeldung.com/java-varargs">Varargs in Java</link></para> </listitem> <listitem> <para>The <code>varargs</code> section in chapter 4 of <xref linkend="bib_Kurniawan"/>.</para> </listitem> </itemizedlist> </tip> </listitem> <listitem> <para>What is the role of the <quote>%...</quote> format strings?</para> </listitem> </orderedlist> </question> <answer> <orderedlist> <listitem> <para>At first sight these method calls appear as if the format() method had been multiply overloaded. This observation is misleading despite the fact that a related <link xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/PrintStream.html#format(java.util.Locale,java.lang.String,java.lang.Object...)">overloaded method</link> providing an additional locale argument does indeed exist.</para> <para>According to <code language="java">System.out.<methodname xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/PrintStream.html#format(java.lang.String,java.lang.Object...)">format(...)</methodname></code> the first argument must be of type <code language="java" xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html">String</code>. Additional arguments of <emphasis>arbitrary</emphasis> type may be added in accordance with the <quote>%...</quote> <link xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Formatter.html#syntax">format strings</link> inside the first argument. These arguments are being passed as instances of <classname>Object</classname>. The <methodname>format(...)</methodname> method uses the <acronym>varargs</acronym> mechanism.</para> <para>Albeit being different you may compare this mechanism to the following hypothetic implementation using an array instead:</para> <programlisting language="java">public PrintStream format (String format, Object[] args)</programlisting> <para>Corresponding code using this hypothetic method would read:</para> <programlisting language="java">System.out.format("An integer %3d and a double value %6.2f\n", new Object[]{Integer.valueOf(value), /**/ Integer.valueOf(secondValue)};</programlisting> <para>As you can see this code is clumsy in comparison to the <quote>varargs</quote> mechanism. </para> </listitem> <listitem> <para>There is a one to one correspondence between each <code language="java">%...</code> format string and its corresponding argument: If n further arguments exist the format string must contain n <quote>%</quote> format specifiers.</para> </listitem> </orderedlist> <para>Consider the following snippet:</para> <programlisting language="java">final int v = 33; final double d = 114.317; final short color = 255; System.out.format("v=%d, d=%5.2f, color=%2x\n", v, d, color);</programlisting> <para>This generates the following output:</para> <screen>v=33, d=114.32, color=ff</screen> <para>We may prettify our code to better reflect the one to one correspondence between format strings and variables:</para> <programlisting language="java">System.out.format("v=%d, d=%5.2f, color=%2x\n", v, d, color);</programlisting> <caution> <para>A failure in providing appropriate numbers of arguments having appropriate types likely results in a runtime exception:</para> <programlisting language="java">System.out.format("v=%d, d=%d, color=%2x\n", // Error: Using %s // rather than %f. v, d, color);</programlisting> <screen>v=33, d=Exception in thread "main" java.util.IllegalFormatConversionException: <emphasis role="bold">d != java.lang.Double</emphasis> at java.util.Formatter$FormatSpecifier.failConversion(...</screen> </caution> </answer> </qandaentry> </qandadiv> </qandaset> </section> <section xml:id="sd1_array_sect_classArraysHelper"> <title><classname xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Arrays.html">java.util.Arrays</classname> helpers</title> <info> <abstract> <para>Sorting and searching arrays.</para> <para>Fill in values.</para> <para>Compare array contents.</para> </abstract> </info> <figure xml:id="sd1_array_fig_arraysToStringSort"> <title><classname xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Arrays.html">Arrays</classname>.<methodname xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Arrays.html#toString(java.lang.Object%5B%5D)">toString(...)</methodname> and <classname xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Arrays.html">Arrays</classname>.<methodname xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Arrays.html#sort(java.lang.Object%5B%5D)">sort(...)</methodname></title> <programlisting language="java">final String[] names = {"Eve", "Aaron", "Paul", "Mandy"}; System.out.println(" toString: " + Arrays.toString(names)); Arrays.sort(names); System.out.println("sort|toString: " + Arrays.toString(names));</programlisting> <para>Result:</para> <screen> toString: [Eve, Aaron, Paul, Mandy] sort|toString: [Aaron, Eve, Mandy, Paul]</screen> </figure> <figure xml:id="sd1_array_fig_arraysBinarySearch"> <title><classname xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Arrays.html">Arrays</classname>.<methodname xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Arrays.html#binarySearch(java.lang.Object%5B%5D,java.lang.Object)">binarySearch(...)</methodname></title> <programlisting language="java">final String[] names = {"Aaron", "Eve", "Mandy", "Paul"}; // Precondition: Array must be ordered! ...println("sort|find(Mand): " + Arrays.binarySearch(names, "Mand")); ...println("sort|find(Mandy): " + Arrays.binarySearch(names, "Mandy")); ...println("sort|find(Mandyer): " + Arrays.binarySearch(names, "Mandyer"));</programlisting> <para>Result:</para> <screen>sort|find(Mand): -3 sort|find(Mandy): 2 sort|find(Mandyer): -4</screen> </figure> <qandaset defaultlabel="qanda" xml:id="sd1_coreClasses_array_qanda_searchNegResult"> <title>Understanding search results</title> <qandadiv> <qandaentry> <question> <para>Read the <xref linkend="glo_Javadoc"/> of <classname xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Arrays.html">Arrays</classname>.<methodname xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Arrays.html#binarySearch(java.lang.Object%5B%5D,java.lang.Object)">binarySearch(...)</methodname>and explain the three integer search result values in <xref linkend="sd1_array_fig_arraysBinarySearch"/>.</para> <para>In particular give a detailed account explaining the two negative values -3 and -4.</para> </question> <answer> <para>The input array reads <code language="java">{"Aaron", "Eva", "Mandy", "Paul"}</code>.</para> <informaltable border="1"> <tr> <th>Array element</th> <th>Index</th> </tr> <tr> <td valign="top"><code language="java">"Aaron"</code></td> <td valign="top">0</td> </tr> <tr> <td valign="top"><code language="java">"Eve"</code></td> <td valign="top">1</td> </tr> <tr> <td valign="top"><emphasis role="red">"Mandy"</emphasis></td> <td valign="top"><emphasis role="red">2</emphasis></td> </tr> <tr> <td valign="top"><code language="java">"Paul"</code></td> <td valign="top">3</td> </tr> </informaltable> <para>A positive return value conveys:</para> <orderedlist> <listitem> <para>The value is present within the array.</para> </listitem> <listitem> <para>The return value is equal to the array element's index.</para> </listitem> </orderedlist> <para>Searching for <code language="java">"Mandy"</code> thus returns the index value 2 corresponding to the third array element.</para> <para>Negative return values actually also provide two types of information:</para> <orderedlist> <listitem> <para>The value is not present in the given array.</para> </listitem> <listitem> <para>The position where the element would be inserted to become part of an ordered list.</para> </listitem> </orderedlist> <para>In the given example hypothetically inserting the string <code language="java"><emphasis role="red">"Mand"</emphasis></code> retaining a sorted list results in:</para> <programlisting language="none">{"Aaron", "Eva", <emphasis role="red">"Mand"</emphasis>, "Mandy", "Paul"}</programlisting> <para>This insertion point's index is 2 corresponding to the third array element. According to the <methodname xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Arrays.html#binarySearch(java.lang.Object%5B%5D,java.lang.Object)">binarySearch(...)</methodname> method's documentation this corresponds to a return value of -2 - 1 == -3.</para> <para>The observed return value of -4 when searching for <emphasis role="red">"Mandyer"</emphasis> corresponds to insertion index 3:</para> <programlisting language="none">{"Aaron", "Eva", "Mandy", <emphasis role="red">"Mandyer"</emphasis>, "Paul"}</programlisting> <remark>Subtracting -1 is being required for conveying the «not in list» information under all circumstances. Otherwise not finding and hypothetically inserting e.g. <code language="java">"A"</code> at the list's beginning would result in 0. This could not be disambiguated from an array featuring <code language="java">"A"</code> at its front position.</remark> </answer> </qandaentry> </qandadiv> </qandaset> <figure xml:id="sd1_array_fig_arraysFill"> <title><classname xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Arrays.html">Arrays</classname>.<methodname xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Arrays.html#fill(java.lang.Object%5B%5D,int,int,java.lang.Object)">fill(...)</methodname></title> <informaltable border="0"> <colgroup width="48%"/> <colgroup width="52%"/> <tr> <td valign="top"><programlisting language="none">final String[] names = {"Eve", "Aaron", "Paul", "Mandy"}; System.out.println("toString: " + Arrays.toString(names)); Arrays.<emphasis role="red">fill(names, "N.N")</emphasis>; System.out.println("toString: " + Arrays.toString(names));</programlisting></td> <td valign="top"><screen>toString: [Eve, Aaron, Paul, Mandy] toString: [N.N, N.N, N.N, N.N]</screen></td> </tr> </informaltable> </figure> <figure xml:id="sd1_array_fig_arraysCopyOf"> <title><classname xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Arrays.html">Arrays</classname>.<methodname xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Arrays.html#copyOfRange(T%5B%5D,int,int)">copyOfRange(...)</methodname></title> <programlisting language="none">final String[] names = {"Eve", "Aaron", "Paul", "Mandy"}; final String[] lastTwoNames = Arrays.<emphasis role="red">copyOfRange(names, 2, 6)</emphasis>; System.out.println("toString: " + Arrays.toString(lastTwoNames));</programlisting> <para>Result:</para> <screen>toString: [Paul, Mandy, <emphasis role="red">null</emphasis>, <emphasis role="red">null</emphasis>]</screen> </figure> <figure xml:id="sd1_array_fig_arraysEquals"> <title><classname xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Arrays.html">Arrays</classname>.<methodname xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Arrays.html#equals(java.lang.Object%5B%5D,java.lang.Object%5B%5D)">equals(...)</methodname></title> <programlisting language="java">final String[] l1 = {new String("Eve"), new String("Aaron"), new String("Paul"), new String("Mandy")}, l2 = {new String("Eve"), new String("Aaron"), new String("Paul"), new String("Mandy")}, l3 = {new String("Eve"), new String("Aaron"), new String("Paul"), new String("<emphasis role="red">Mobile</emphasis>")}; System.out.println("l1.equals(l2):" + Arrays.equals(l1, l2)); System.out.println("l1.equals(l3):" + Arrays.equals(l1, l3));</programlisting> <para>Result:</para> <screen>l1.equals(l2):true l1.equals(l3):false</screen> </figure> </section> <section xml:id="sd1_array_sect_extend"> <title>Extending arrays</title> <info> <abstract> <para>Dealing with fixed size.</para> </abstract> </info> <figure xml:id="sd1_array_fig_arraysExtendArrayProblem"> <title>Lack of extendability</title> <programlisting language="none">final String[] member = {"Eve", "John", "Peter", "Jill"}; final String newCourseMember = "Ernest"; <emphasis role="red">member.length = 5</emphasis>; // Error: Size unchangeable member[4] = newCourseMember;</programlisting> </figure> <figure xml:id="sd1_array_fig_manualExtendArray"> <title>Extending an array</title> <programlisting language="java">public static void main(String[] args) { <co linkends="sd1_array_fig_manualExtendArray-1" xml:id="sd1_array_fig_manualExtendArray-1-co"/> String[] member = {"Eve", "John", "Peter", "Jill"}; final String newMember = "Ernest"; member <co linkends="sd1_array_fig_manualExtendArray-2" xml:id="sd1_array_fig_manualExtendArray-2-co"/>= append(member, newMember); } static String[] append (final String[] values, final String newValue) { final String[] copy = <co linkends="sd1_array_fig_manualExtendArray-3" xml:id="sd1_array_fig_manualExtendArray-3-co"/> new String[values.length + 1]; for (int i = 0; i < values.length; i++) { <co linkends="sd1_array_fig_manualExtendArray-4" xml:id="sd1_array_fig_manualExtendArray-4-co"/> copy[i] = values[i]; <co linkends="sd1_array_fig_manualExtendArray-5" xml:id="sd1_array_fig_manualExtendArray-5-co"/> } copy[copy.length - 1] = newValue; <co linkends="sd1_array_fig_manualExtendArray-6" xml:id="sd1_array_fig_manualExtendArray-6-co"/> return copy; }</programlisting> <calloutlist role="slideExclude"> <callout arearefs="sd1_array_fig_manualExtendArray-1-co" xml:id="sd1_array_fig_manualExtendArray-1"> <para>No final here: Reference will be re-assigned.</para> </callout> <callout arearefs="sd1_array_fig_manualExtendArray-2-co" xml:id="sd1_array_fig_manualExtendArray-2"> <para>Assigning reference to enlarged array.</para> </callout> <callout arearefs="sd1_array_fig_manualExtendArray-3-co" xml:id="sd1_array_fig_manualExtendArray-3"> <para>Creating an empty array capable of holding one more value.</para> </callout> <callout arearefs="sd1_array_fig_manualExtendArray-4-co" xml:id="sd1_array_fig_manualExtendArray-4"> <para>Looping over existing values.</para> </callout> <callout arearefs="sd1_array_fig_manualExtendArray-5-co" xml:id="sd1_array_fig_manualExtendArray-5"> <para>Assigning old values one by one to corresponding index positions.</para> </callout> <callout arearefs="sd1_array_fig_manualExtendArray-6-co" xml:id="sd1_array_fig_manualExtendArray-6"> <para>Assigning new value to last index position before returning newly created array's reference.</para> </callout> </calloutlist> </figure> <figure xml:id="sd1_array_fig_manualExtendArrayResult"> <title>Extension result</title> <programlisting language="none">final String[] member = {"Eve", "John", "Peter", "Jill"}; System.out.println("Original array: " + Arrays.toString(member)); final String <emphasis role="red">newMember</emphasis> = "<emphasis role="red">Ernest</emphasis>"; member = append(member, <emphasis role="red">newMember</emphasis>); System.out.println("Extended array: " + Arrays.toString(member));</programlisting> <screen>Original array: [Eve, John, Peter, Jill] Extended array: [Eve, John, Peter, Jill, <emphasis role="red">Ernest</emphasis>]</screen> </figure> <figure xml:id="sd1_array_fig_arraysExtendArrayHelper"> <title>Using <methodname xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Arrays.html#copyOf(int%5B%5D,int)">Arrays.copyOf()</methodname></title> <programlisting language="none">public static void main(String[] args) { final int [] start = {1,7,-4}, added = append(start, 77); System.out.println("added: " + Arrays.toString(added)); } static public int[] append(final int[] values, final int newValue) { final int[] result = Arrays.<emphasis role="red">copyOf(values, values.length + 1)</emphasis>; <emphasis role="red">result[values.length]</emphasis> = newValue; return result;}</programlisting> <para>Result:</para> <screen>added: [1, 7, -4, 77]</screen> </figure> <qandaset defaultlabel="qanda" xml:id="sd1_core_array_qanda_extendArray"> <title>Implementing append directly</title> <qandadiv> <qandaentry> <question> <para>We reconsider our <methodname>append(...)</methodname> method:</para> <programlisting language="java">/** * <p>Create a new array consisting of given array values and new value at its end. Example:</p> * * <p>Given Array {1, 3, 0} and new value 77 results in {1, 3, 0, 77}. </p> * * @param values Given values * @param newValue Value to be appended * @return A new array prepending the input array values to the new value . */ static public int[] append(final int[] values, final int newValue) { final int[] result = Arrays.copyOf(values, values.length + 1); result[values.length] = newValue; return result; }</programlisting> <para>Change the implementation. Do not use methods from <classname>Arrays</classname> but just <code language="java">for</code> loops and other elementary <xref linkend="glo_Java"/> constructs. Employ the following (minimal) unit test:</para> <programlisting language="java">public class AppendTest { @Test public void appendTest() { Assert.assertArrayEquals(new int[]{1, 2, 5}, MyArray.append(new int[]{1, 2}, 5)); Assert.assertArrayEquals(new int[]{6}, MyArray.append(new int[]{}, 6)); } }</programlisting> </question> <answer> <programlisting language="none">/** * <p>Create a new array consisting of given array values and new value at its end. Example:</p> * * <p>Given Array {1, 3, 0} and new value 77 results in {1, 3, 0, 77}. </p> * * @param values Given values * @param newValue Value to be appended * @return A new array prepending the input array values to the new value . */ static public int[] append(final int[] values, final int newValue) { final int[] result = new int[values.length + <emphasis role="red">1</emphasis>]; <co linkends="sd1_core_array_qanda_extendArrayCalloutSolution-1" xml:id="sd1_core_array_qanda_extendArrayCalloutSolution-1-co"/> for (int i = 0; i < values.length; i++) { <co linkends="sd1_core_array_qanda_extendArrayCalloutSolution-2" xml:id="sd1_core_array_qanda_extendArrayCalloutSolution-2-co"/> result[i] = values[i]; } result[values.length] = newValue; <co linkends="sd1_core_array_qanda_extendArrayCalloutSolution-3" xml:id="sd1_core_array_qanda_extendArrayCalloutSolution-3-co"/> return result; }</programlisting> <calloutlist> <callout arearefs="sd1_core_array_qanda_extendArrayCalloutSolution-1-co" xml:id="sd1_core_array_qanda_extendArrayCalloutSolution-1"> <para>Create a new array by extending the given array's size by 1.</para> </callout> <callout arearefs="sd1_core_array_qanda_extendArrayCalloutSolution-2-co" xml:id="sd1_core_array_qanda_extendArrayCalloutSolution-2"> <para>Copy the given array's values into the new array.</para> </callout> <callout arearefs="sd1_core_array_qanda_extendArrayCalloutSolution-3-co" xml:id="sd1_core_array_qanda_extendArrayCalloutSolution-3"> <para>Copy the new <code language="java">int</code> value to the last array element.</para> </callout> </calloutlist> </answer> </qandaentry> </qandadiv> </qandaset> <qandaset defaultlabel="qanda" xml:id="sd1_core_array_qanda_distinct"> <title>Purge duplicates</title> <qandadiv> <qandaentry> <question> <para>Consider the following <code language="java">int[]</code> array:</para> <programlisting language="java">final int[] values = {6, 1, 5, 1, 6, 1}</programlisting> <para>This array contains duplicates to be purged leaving us with a sorted result containing distinct values:</para> <programlisting language="java">int[] result={1, 5, 6}</programlisting> <para>Implement a corresponding <methodname>distinct(...)</methodname> method:</para> <programlisting language="java">/** * <p>Turn a list of value into a sorted set not containing any duplicates. Example:</p> * * <pre>{6, 1, 5, 1, 6, 1} to {1, 5, 6}</pre> * * <p>The array of input values is to be left untouched.</p> * * @param values Unsorted values possibly containing duplicates. * @return An ordered set of distinct values. */ public static int[] distinct (final int[] values) { ... return ...; // TODO: Implement me! }</programlisting> <para>Use (at least) these unit tests:</para> <programlisting language="java">@Test public void testUnique() { unique(new int[]{}); unique(new int[]{-11}); unique(new int[]{1, 4}); unique(new int[]{6, 1, 4}); unique(new int[]{12, 6, 1, 4}); unique(new int[]{-99, 4, 333, 17, 0, 3, 55}); } @Test public void testTwoDuplicate() { Assert.assertArrayEquals(new int[]{6}, MyArray.distinct(new int[]{6, 6})); } @Test public void testThreeDuplicate() { Assert.assertArrayEquals(new int[]{-1, 6}, MyArray.distinct(new int[]{-1, 6, 6})); Assert.assertArrayEquals(new int[]{-1, 6}, MyArray.distinct(new int[]{6, -1, 6})); Assert.assertArrayEquals(new int[]{-1, 6}, MyArray.distinct(new int[]{6, 6, -1})); } @Test public void testFourDuplicate() { Assert.assertArrayEquals(new int[]{-1, 3, 6}, MyArray.distinct(new int[]{-1, 6, 6, 3})); Assert.assertArrayEquals(new int[]{-1, 3, 6}, MyArray.distinct(new int[]{3, 6, -1, 6})); Assert.assertArrayEquals(new int[]{-1, 3, 6}, MyArray.distinct(new int[]{6, 6, 3, -1})); Assert.assertArrayEquals(new int[]{1, 6}, MyArray.distinct(new int[]{1, 6, 1, 6})); Assert.assertArrayEquals(new int[]{1, 6}, MyArray.distinct(new int[]{1, 6, 1, 6, 6, 6, 1 ,1, 6})); } static void unique(final int[] values) { final int[] sortedValues = Arrays.copyOf(values, values.length); Arrays.sort(sortedValues); Assert.assertArrayEquals(sortedValues, MyArray.distinct(values)); }</programlisting> <tip> <para>You may follow these steps:</para> <orderedlist> <listitem> <para>Create a copy of incoming array.</para> </listitem> <listitem> <para>Sort the copied array.</para> </listitem> <listitem> <para>Loop over the sorted values. Due to sorting duplicates now appear in sequence:</para> <programlisting language="java">{1, 1, 1, 5, 6, 6}</programlisting> <para>You may create a secondary array holding only distinct index values. In the given example this would contain index values {0, 3, 4} with respect to above array example.</para> </listitem> <listitem> <para>Create a result array containing only distinct values:</para> <programlisting language="java">{1, 5, 6}</programlisting> </listitem> </orderedlist> </tip> </question> <answer> <annotation role="make"> <para role="eclipse">P/Sd1/Array/Distinct</para> </annotation> <para>Following the steps outlined in the hints we may:</para> <programlisting language="java">public class MyArray { /** * <p>Turn a list of values into a sorted set not containing any duplicates. Example:</p> * * <pre>{6, 1, 5, 1, 6, 1} to {1, 5, 6}</pre> * * <p>The array of input values is to be left untouched.</p> * * @param values Unsorted values possibly containing duplicates. * @return An ordered set of distinct values. */ public static int[] distinct (final int[] values) { if (0 == values.length) { return values; // Special case: Empty array } // Step 1: Cloning incoming array final int[] sortedValues = Arrays.copyOf(values, values.length); // Step 2: Sort copied array. Arrays.sort(sortedValues); // Step 3: Create helper array containing distinct index positions final int[] uniqueValuesIndex = new int[values.length]; int uniqueValueIndexTop = 0; uniqueValuesIndex[uniqueValueIndexTop++] = 0; // Include first array element unconditionally for (int i = 1; i < sortedValues.length; i++) { if (sortedValues[i - 1] != sortedValues[i]) { // current value different from predecessor? uniqueValuesIndex[uniqueValueIndexTop++] = i; // Add to set of distinct index values } } // Step 4: Create and copy to result array final int[] result = new int[uniqueValueIndexTop]; // We found uniqueValueIndexTop distinct values for (int i = 0; i < uniqueValueIndexTop; i++) { // Copy distinct values to result array result[i] = sortedValues[uniqueValuesIndex[i]]; } return result; } }</programlisting> </answer> </qandaentry> </qandadiv> </qandaset> <section xml:id="sd1IntStore"> <title>Storing integer values</title> <qandaset defaultlabel="qanda" xml:id="sd1QandaIntStore"> <title>A container of fixed capacity holding integer values</title> <qandadiv> <qandaentry> <question> <para>You may feel tired of bothering about fixed array sizes. This exercise set is about automating the process of enlarging arrays to accommodate new values.</para> <para>Implement a class <classname>BoundedIntegerStore</classname> being able to hold a fixed number of integer values. Internally these values will be stored in an array. The design has been chosen to be extended in later exercises.</para> <para>A skeleton project archive is available at:</para> <annotation role="make"> <para role="eclipse">P/Sd1/Array/integerStoreSkeleton</para> </annotation> <para>Like in the previous exercise <xref linkend="glo_Junit"/> tests are being prepared but masked by a <interfacename xlink:href="https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/Disabled.html">@Disabled</interfacename> annotation.</para> <para>This skeleton project contains:</para> <itemizedlist> <listitem> <para>A class <classname>Driver</classname> which allows you to execute some output generating tests.</para> </listitem> <listitem> <para>A <xref linkend="glo_Junit"/> test <classname>IntStoreTest</classname> which allows you to test your ongoing implementation of <classname>BoundedIntegerStore</classname>. This class contains several <code language="java">// TODO</code> comments indicating positions to be completed.</para> </listitem> <listitem> <para>Like in the previous exercise the <xref linkend="glo_Junit"/> tests are being masked by a <interfacename xlink:href="https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/Disabled.html">@Disabled</interfacename> annotation. After successful implementation its removal allows for test execution.</para> </listitem> </itemizedlist> </question> <answer> <para>See <link xlink:href="https://gitlab.mi.hdm-stuttgart.de/goik/GoikLectures/-/tree/master/P/Sd1/Array/integerStore">integer store project</link>.</para> </answer> </qandaentry> </qandadiv> </qandaset> <qandaset defaultlabel="qanda" xml:id="sd1QandaIntStoreUnbounded"> <title>Allow for variable capacity holding integer values</title> <qandadiv> <qandaentry> <question> <para>In <xref linkend="sd1QandaIntStore"/> once a store has been created its capacity is fixed. We'd like to extend our class to support dynamic growth while adding new values. To achieve this goal follow the following steps:</para> <orderedlist> <listitem> <para>Copy the completed project to a new one <abbrev>e.g.</abbrev> named <quote>UnboundedContainer</quote>. This way you still have the bounded implementation available.</para> </listitem> <listitem> <para>Alter the both artifact and project name in your <filename>pom.xml</filename> file. Rename your class <classname>BoundedIntegerStore</classname> to <classname>IntegerStore</classname> indicating the now missing restriction and thus the possibility of dynamic growth.</para> </listitem> <listitem> <para>Read section <quote>Changing an Array Size</quote> in chapter 6.</para> </listitem> <listitem> <para>You have to modify the <code language="java">void addValue(int value)</code> method's implementation: If the array's size gets exceeded (e.g. adding the fifth value while still having array size of 4) provide the following actions:</para> <itemizedlist> <listitem> <para>Create a second array offering twice the current capacity. This technique is referred to as <quote>amortized doubling</quote>.</para> </listitem> <listitem> <para>Copy all existing values from the current array to the new array</para> </listitem> <listitem> <para>Assign the new array to your <code language="java">int[] values</code> variable. You thereby implicitly discard the old array which become subject to be garbage collected.</para> </listitem> <listitem> <para>copy the latest argument to the array as usual.</para> </listitem> </itemizedlist> <para>Basically you have to compare the number of already inserted elements and the current capacity prior to inserting any new value.</para> </listitem> <listitem> <para>Add a default constructor providing an initial default capacity of 4.</para> </listitem> </orderedlist> <para>Modify and add <xref linkend="glo_Junit"/> tests accordingly to reflect the new behaviour. In particular you should test for correct capacity reallocation handling when adding larger numbers of values being added.</para> </question> <answer> <annotation role="make"> <para role="eclipse">P/Sd1/Array/integerStoreUnbounded</para> </annotation> </answer> </qandaentry> </qandadiv> </qandaset> </section> </section> <section xml:id="sd1_array_sect_understandingMainMethod"> <title>Understanding <methodname>static public int main(String[] args)</methodname></title> <info> <abstract> <para><methodname>main(...)</methodname> and its array argument.</para> <para>Implementing parameter passing.</para> </abstract> </info> <figure xml:id="sd1_array_fig_understandingMain"> <title><methodname>public static void main(String[] args)</methodname></title> <programlisting language="java">package myapp; public class Cmd { public static void main(String[] args) { for (int i = 0; i < args.length; i++) { System.out.println("Parameter " + (i + 1) + ": " + args[i]); } } }</programlisting> <screen>java myapp.Cmd 21 334 -13 Parameter 1: 21 Parameter 2: 334 Parameter 3: -13</screen> </figure> <figure xml:id="sd1_array_fig_ideaRunConfig"> <title><xref linkend="glo_Soft_IntellijIDEA"/> run configuration</title> <mediaobject> <imageobjectco> <areaspec otherunits="imagemap" units="other"> <area units="calspair" coords="407,98,521,139" linkends="sd1_array_fig_ideaRunConfig-1" xml:id="__area-ypcokm"/> <area units="calspair" coords="410,161,526,202" linkends="sd1_array_fig_ideaRunConfig-2" xml:id="__area-qny3zv"/> </areaspec> <imageobject> <imagedata fileref="Fig/ideaRunConfig.png.marked.svg"/> </imageobject> </imageobjectco> </mediaobject> <calloutlist> <callout arearefs="__area-ypcokm" xml:id="sd1_array_fig_ideaRunConfig-1"> <para>Entry class <classname>myapp.Cmd</classname> containing <methodname>... main(String[] args)</methodname>.</para> </callout> <callout arearefs="__area-qny3zv" xml:id="sd1_array_fig_ideaRunConfig-2"> <para>Parameters <option>21</option>, <option>334</option> and <option>-13</option> being passed to <code language="java">String[] args</code>.</para> </callout> </calloutlist> </figure> <figure xml:id="sd1_array_fig_ideaRunConfigResult"> <title><xref linkend="glo_Soft_IntellijIDEA"/> run configuration</title> <mediaobject> <imageobject> <imagedata fileref="Fig/ideaRunResult.png"/> </imageobject> </mediaobject> </figure> <figure xml:id="sd1_array_fig_understandingMainExecJar"> <title><methodname>Creating executable jar</methodname></title> <informaltable border="0"> <tr> <td valign="top"><programlisting language="none"><artifactId>maven-shade-plugin</artifactId> ... <transformer ...> <manifestEntries> <Main-Class><emphasis role="red">myapp.Cmd</emphasis></Main-Class> </manifestEntries>...</programlisting></td> <td valign="top"><screen>unzip ww-1.0-SNAPSHOT.jar cat tmp/META-INF/MANIFEST.MF ... Created-By: Apache Maven 3.5.0 Build-Jdk: 1.8.0_151 Main-Class: <emphasis role="red">myapp.Cmd</emphasis></screen></td> </tr> </informaltable> <screen>mvn package ... java -jar target/ww-1.0-SNAPSHOT.jar <emphasis role="red">21 334 -13</emphasis> Parameter 1: <emphasis role="red">21</emphasis> Parameter 2: <emphasis role="red">334</emphasis> Parameter 3: <emphasis role="red">-13</emphasis></screen> </figure> <qandaset defaultlabel="qanda" xml:id="sd1QandaConsoleInput"> <title>Reading console input</title> <qandadiv> <qandaentry> <question> <para>Consider the following code example computing the sum of an arbitrary number of integer values:</para> <programlisting language="java">import java.util.Scanner; public class Driver { public static void main(String[] args) { final Scanner scanner = new Scanner(System.in); System.out.print("How many values do you want to summ up? "); final int numValues = scanner.nextInt(); int sum = 0; for (int i = 0; i < numValues; i++) { System.out.print("Enter value #" + (i + 1) + " of " + numValues + ": "); sum += scanner.nextInt(); } System.out.println("Sum=" + sum); scanner.close(); } }</programlisting> <para>This program:</para> <orderedlist> <listitem> <para>Asks a user how many integer numbers shall be processed. A user may enter e.g. 4 indicating his intention to subsequently enter 4 values.</para> </listitem> <listitem> <para>Actually reads e.g. 4 input numbers and calculates their sum.</para> </listitem> </orderedlist> <para>The result might look like:</para> <screen>How many values do you want to summ up? 4 Enter value #1 of 4: 11 Enter value #2 of 4: 22 Enter value #3 of 4: -33 Enter value #4 of 4: 1 Sum=1</screen> <para>Modify this program to output not just the desired sum but the complete arithmetic expression:</para> <screen>How many values do you want to summ up? 4 Enter value #1 of 4: 1 ... <emphasis role="bold">1+2+3-5 = 1</emphasis></screen> <para>Hints:</para> <orderedlist> <listitem> <para>Use an integer array to store the entered input values.</para> </listitem> <listitem> <para>Mind the input values' signs: While positive or zero values are not being represented with a leading <quote>+</quote> sign negative values already do have a preceding <quote>-</quote> sign. With respect to the above example output representations like <quote>22+-33</quote> are discouraged.</para> </listitem> </orderedlist> </question> <answer> <annotation role="make"> <para role="eclipse">P/Sd1/ConsoleSum/V1</para> </annotation> </answer> </qandaentry> </qandadiv> </qandaset> <qandaset defaultlabel="qanda" xml:id="sd1QandaSumPrettifyOutput"> <title>Prettifying output representation</title> <qandadiv> <qandaentry> <question> <para>The output representation of <xref linkend="sd1QandaConsoleInput"/> shall be altered by the following rules:</para> <orderedlist> <listitem> <para>A empty set of input values shall produce just 0 (zero) avoiding the <quote>=</quote> sign:</para> <para>{} → 0.</para> </listitem> <listitem> <para>A list containing just one input value shall be represented by just this value avoiding the <quote>=</quote> sign:</para> <para>{-4} → -4.</para> </listitem> <listitem> <para>Zero values shall be excluded completely:</para> <itemizedlist> <listitem> <para>{0,1,0,4} → <code language="java">1+4=5</code>.</para> </listitem> <listitem> <para>{0,0,0} → <code language="java">0</code>. (By virtue of rule 1)</para> </listitem> <listitem> <para>{0,1,0} → <code language="java">1</code>. (By virtue of rule 2)</para> </listitem> </itemizedlist> </listitem> <listitem> <para>If possible a sum shall not start with a negative value. The list {-1, -2, 5} for example will generate <code language="java">-1-2+5=2</code>. Instead the first negative value shall be swapped with the first positive value (if existent). The current example will thus result in <code language="java">5-2-1=2</code>.</para> </listitem> </orderedlist> <para>Write your application in a unit testable fashion.</para> <tip> <itemizedlist> <listitem> <para>Apply these rules in order 3-4-2/1</para> </listitem> <listitem> <para>The following Maven project skeleton contains both a yet not implemented class method <methodname>de.hdm_stuttgart.mi.sda1.console_sum.App.prettifyOutput(int[] values)</methodname> and a corresponding <xref linkend="glo_Junit"/> test suite being defined in <package>de.hdm_stuttgart.mi.sda1.console_sum</package>.<classname>AppTest</classname>:</para> <annotation role="make"> <para role="eclipse">P/Sd1/ConsoleSum/V1</para> </annotation> <para>All tests would currently fail. Therefore the test class <classname>de.hdm_stuttgart.mi.sda1.console_sum.AppTest</classname> is being masked by an <interfacename xlink:href="https://junit.org/junit5/docs/current/api/org/junit/jupiter/api/Disabled.html">@Disabled</interfacename> annotation:</para> <programlisting language="java">... <emphasis role="bold" xlink:href="https://junit.org/junit5/docs/current/api/org/junit/jupiter/api/Disabled.html">@Disabled</emphasis> public class AppTest { /** * empty list */ @Test public void testEmptyList() { Assert.assertEquals("0", App.prettifyOutput(new int[0])); } ...</programlisting> <para>Import this project into your <xref linkend="glo_IDE"/> and complete its implementation of <methodname>de.hdm_stuttgart.mi.sda1.console_sum.App.prettifyOutput(int[] values)</methodname> until all <xref linkend="glo_Junit"/> tests do succeed. Removing the <interfacename xlink:href="https://junit.org/junit5/docs/current/api/org/junit/jupiter/api/Disabled.html">@Disabled</interfacename> line will allow for testing your implementation.</para> </listitem> </itemizedlist> </tip> </question> <answer> <annotation role="make"> <para role="eclipse">P/Sd1/ConsoleSum/V3</para> </annotation> </answer> </qandaentry> </qandadiv> </qandaset> </section> <section xml:id="sd1_array_sect_multidim"> <title>Multi-dimensional arrays</title> <info> <abstract> <para>Multiple dimensions by nesting of arrays.</para> </abstract> </info> <figure xml:id="sd1_array_fig_multidimArray"> <title><methodname>Two-dimensional arrays</methodname></title> <programlisting language="java">final int[][] matrix = new int[2][3]; for (int row = 0; row < 2; row++) { for (int col = 0; col < 3; col++) { matrix[row][col] = col + row; } } for (int row = 0; row < 2; row++) { System.out.println(Arrays.toString(matrix[row])); }</programlisting> </figure> <figure xml:id="sd1_array_fig_multidimBehindTheScenes"> <title><methodname>Behind the scenes</methodname></title> <programlisting language="java">final int[][] matrix = new int[2][]; // Array containing two int arrays matrix[0] = new int[3]; // first int array matrix[1] = new int[3]; // second int array</programlisting> </figure> <figure xml:id="sd1_array_fig_multidimMemory"> <title><methodname>Memory allocation</methodname></title> <mediaobject> <imageobject> <imagedata fileref="Fig/array2dim.multi.svg"/> </imageobject> </mediaobject> </figure> <qandaset defaultlabel="qanda" xml:id="sd1_array_qanda_array2dimConstLength"> <title>2-dimensional arrays and <code language="java">.length</code></title> <qandadiv> <qandaentry> <question> <orderedlist> <listitem> <para>In <xref linkend="sd1_array_fig_arrayPrimeArrayLength"/> you were advised to favour <code language="java">.length</code> over hard coded int values like e.g. <quote>5</quote>. Replace the error prone limits 2 and 3 in <xref linkend="sd1_array_fig_multidimArray"/> accordingly.</para> </listitem> <listitem> <para>Replace the second loop in <xref linkend="sd1_array_fig_multidimArray"/> by a <link linkend="sd1_array_fig_arrayForEachLoop">for-each style</link> loop.</para> <tip> <para><code language="java">matrix[0]</code> and <code language="java">matrix[1]</code> are of type <code language="java">int[]</code>.</para> </tip> </listitem> </orderedlist> </question> <answer> <para>Two-dimensional arrays in <xref linkend="glo_Java"/> are nested arrays of arrays. We thus choose appropriate data types:</para> <programlisting language="java">final int[][] matrix = new int[2][3]; for (int row = 0; row < matrix.length <co linkends="sd1_array_qanda_array2dimConstLength-1" xml:id="sd1_array_qanda_array2dimConstLength-1-co"/>; row++) { for (int col = 0; col < matrix[row].length <co linkends="sd1_array_qanda_array2dimConstLength-2" xml:id="sd1_array_qanda_array2dimConstLength-2-co"/>; col++) { matrix[row][col] = col + row; } } for (final int[] <co linkends="sd1_array_qanda_array2dimConstLength-3" xml:id="sd1_array_qanda_array2dimConstLength-3-co"/> row : matrix) { System.out.println(Arrays.toString(row)); }</programlisting> <calloutlist> <callout arearefs="sd1_array_qanda_array2dimConstLength-1-co" xml:id="sd1_array_qanda_array2dimConstLength-1"> <para>The «outer» array's dimension: This <code language="java">int[][]</code> array is the visible entry point containing references to rows each being implemented as a «simple» <code language="java">int[]</code> array.</para> </callout> <callout arearefs="sd1_array_qanda_array2dimConstLength-2-co" xml:id="sd1_array_qanda_array2dimConstLength-2"> <para>All rows are having identical length. We could thus use either representative <code language="java">matrix[0].length</code> or <code language="java">matrix[1].length</code> as well. However choosing <code language="java">matrix[row].length</code> also works in case of different row lengths.</para> </callout> <callout arearefs="sd1_array_qanda_array2dimConstLength-3-co" xml:id="sd1_array_qanda_array2dimConstLength-3"> <para>The variable <code language="java">matrix</code> is of type <code language="java">int[][]</code>. Each <code language="java">matrix[row]</code> entry thus represents a reference to an «ordinary» <code language="java">int[]</code> array. So row iteration requires a loop variable of type <code language="java">int[]</code>.</para> </callout> </calloutlist> </answer> </qandaentry> </qandadiv> </qandaset> <figure xml:id="sd1_array_fig_multiArrayInit"> <title><methodname>Static array initialization</methodname></title> <programlisting language="java">final int[][] matrix = new int[][] { {0, 1, 2}, {1, 2, 3} };</programlisting> </figure> <figure xml:id="sd1_array_fig_multiArrayInitDynLength"> <title><methodname>Static array initialization, variable lengths</methodname></title> <informaltable border="0"> <colgroup width="72%"/> <colgroup width="28%"/> <tr> <td valign="top"><programlisting language="java">final String[][] groups = new String[][] { {"Jill", "Tom"}, {"Jane", "Smith", "Joe"}, {"Jeff"} }; for (int row = 0; row < groups.length; row++) { System.out.println(Arrays.toString(groups[row])); }</programlisting></td> <td valign="top"><screen>[Jill, Tom] [Jane, Smith, Joe] [Jeff]</screen></td> </tr> </informaltable> </figure> <qandaset defaultlabel="qanda" xml:id="sw1QandaExternalHarderString"> <title>External array and string exercises</title> <qandadiv> <qandaentry> <question> <para>Solve all examples from the following sections:</para> <itemizedlist> <listitem> <para><link xlink:href="http://codingbat.com/java/String-3">String-3</link></para> </listitem> <listitem> <para><link xlink:href="http://codingbat.com/java/Array-1">Array-1</link></para> </listitem> <listitem> <para><link xlink:href="http://codingbat.com/java/Array-1">Array-2</link></para> </listitem> <listitem> <para><link xlink:href="http://codingbat.com/java/Array-3">Array-3</link></para> </listitem> </itemizedlist> </question> </qandaentry> </qandadiv> </qandaset> </section> <section xml:id="sd1SectTicTacToePart"> <title>Tic-tac-toe</title> <section xml:id="sd1SectTicTacToeTwodimensional"> <title>Tic-tac-toe using a two-dimensional array</title> <qandaset defaultlabel="qanda" xml:id="sd1QandaTicTacToeTwodimensional"> <qandadiv> <qandaentry> <question> <para>This exercise exclusively deals with the visualization and bookkeeping of two humans playing <link xlink:href="https://en.wikipedia.org/wiki/Tic-tac-toe">Tic-tac-toe</link> against each other. For the sake of clarification: It is not about humans playing a computer. So you do not (yet) have to implement an algorithm finding a player's best possible moves. The following video shows the intended behaviour:</para> <figure xml:id="sd1FigTicTacToe"> <title>Two Tic-tac-toe players fighting each other.</title> <mediaobject> <videoobject> <videodata fileref="Fig/tttEclipse.webm"/> </videoobject> </mediaobject> </figure> <para>Use a two-dimensional array to represent a game's state:</para> <programlisting language="java">final char[][] board = new char[3][3];</programlisting> <para>Depending on your choice you may also use a class <classname>Player</classname> containing additional information like the player's name. In this case you'll probably need two instances representing both players and in turn a 3 x 3 array holding references to them:</para> <programlisting language="java">final Player[][] board = new Player[3][3];</programlisting> <para>Discovering a <quote>win</quote> situation will be an essential part of this exercise. The following situations define a <quote>win</quote> state:</para> <informaltable border="1"> <col width="7%"/> <col width="2%"/> <col width="7%"/> <col width="2%"/> <col width="7%"/> <col width="2%"/> <col width="7%"/> <col width="2%"/> <col width="7%"/> <col width="2%"/> <col width="7%"/> <col width="2%"/> <col width="7%"/> <col width="2%"/> <col width="7%"/> <tr> <td><screen>xxx ... ...</screen></td> <td/> <td><screen>... xxx ...</screen></td> <td/> <td><screen>... ... xxx</screen></td> <td/> <td><screen>x.. x.. x..</screen></td> <td/> <td><screen>.x. .x. .x.</screen></td> <td/> <td><screen>..x ..x ..x</screen></td> <td/> <td><screen>x.. .x. ..x</screen></td> <td/> <td><screen>..x .x. x..</screen></td> </tr> </informaltable> </question> <answer> <para>Consider the following Maven project:</para> <annotation role="make"> <para role="eclipse">P/Sd1/TicTacToe/V1</para> </annotation> <para>This implementation already uses a so called <code language="java">enum</code> to be discussed later during an upcoming lecture:</para> <programlisting language="java">public enum Player { PLAYER1("Jim", 'O'), PLAYER2("Eve", 'X'); public final String nickname; public final char representation; Player(final String nickname, final char representation) { this.nickname = nickname; this.representation = representation; } public Player getOtherPlayer() { switch (this) { case PLAYER1: return PLAYER2; case PLAYER2: return PLAYER1; default: return null; } } @Override public String toString() { return "" + representation; } }</programlisting> <para>A <xref linkend="glo_Java"/> <code language="java">enum</code> essentially is a specialized class. If you don't like this yet you may safely replace the given <code language="java">enum</code> by the following class:</para> <programlisting language="java">public class Player { final public static Player PLAYER1 = new Player ("Jim", 'O'), PLAYER2 = new Player("Eve", 'X'); public final String nickname; public final char representation; Player(final String nickname, final char representation) { this.nickname = nickname; this.representation = representation; } public Player getOtherPlayer() { if (PLAYER1 == this) { return PLAYER2; } else if (PLAYER2 == this) { return PLAYER1; } else { return null; } } @Override public String toString() { return "" + representation; } }</programlisting> <para>It is possible to wrap this solution into an executable <xref linkend="glo_Jar"/> archive by adding:</para> <programlisting language="xml"><plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>2.6</version> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <!-- Class containing desired entry method public static void main(String[] args) --> <mainClass>de.hdm_stuttgart.mi.sd1.tictactoe.TicTacToe</mainClass> </manifest> </archive> </configuration> </plugin></programlisting> <para>This allows for console execution rather than using your <xref linkend="glo_IDE"/>:</para> <screen>goik@mi-ESPRIMO-P910 V1> mvn install [INFO] Scanning for projects... ... ------------------------------------------------------- T E S T S ------------------------------------------------------- Running de.hdm_stuttgart.mi.sd1.connectfour.AppTest Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.051 sec Results : Tests run: 2, Failures: 0, Errors: 0, Skipped: 0 [INFO] <emphasis role="bold">[INFO] --- maven-jar-plugin:2.6:jar (default-jar) @ tictactoe --- [INFO] Building jar: /.../P/Sd1/TicTacToe/V1/target/tictactoe-0.9.jar [INFO] [INFO] --- maven-install-plugin:2.5.2:install (default-install) @ tictactoe --- [INFO] Installing /.../de/hdm-stuttgart/mi/sd1/tictactoe/0.9/tictactoe-0.9.jar </emphasis>[INFO] Installing /ma/.../de/hdm-stuttgart/mi/sd1/tictactoe/0.9/tictactoe-0.9.pom [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 2.242s [INFO] Finished at: Wed Sep 23 12:54:34 CEST 2015 [INFO] Final Memory: 18M/196M [INFO] ------------------------------------------------------------------------ </screen> <para>As you can see this creates <filename>/ma/goik/.m2/repository/de/hdm-stuttgart/mi/sd1/tictactoe/0.9/tictactoe-0.9.jar</filename>. This may be executed similar to a <quote>true</quote> binary executable:</para> <screen>goik@mi-ESPRIMO-P910 ~> java -jar /ma/goik/.m2/.../tictactoe-0.9.jar Numbering scheme: 0|1|2 -+-+- 3|4|5 -+-+- 6|7|8 Jim, please enter next field's number:</screen> </answer> </qandaentry> </qandadiv> </qandaset> </section> <section xml:id="sd1SectTicTacToeOnedimensional"> <title>Changing the game's internal representation</title> <qandaset defaultlabel="qanda" xml:id="sd1QandaTicTacToeOnedimensional"> <qandadiv> <qandaentry> <question> <para>This exercise aims at changing the subsequent items with respect to the previous Tic-tac-toe solution:</para> <glosslist> <glossentry> <glossterm>End user perspective</glossterm> <glossdef> <orderedlist> <listitem> <para>End users are used to count from 1 to 9 rather than from 0 to 8. Consequently we should supply a different hint regarding the fields' numbering scheme:</para> <informaltable border="1"> <tr> <td><screen>012 345 678</screen></td> <td>⇒</td> <td><screen>123 456 789</screen></td> </tr> </informaltable> </listitem> <listitem> <para>The two players should have a choice about who is to start a game:</para> <screen>Numbering scheme: 1|2|3 -+-+- 4|5|6 -+-+- 7|8|9 Who is going to start? 0 = June, other = Bill 0 June, please enter next field's number:</screen> </listitem> <listitem> <para>The numbering hints should appear <quote>right</quote> to the current tic-tac-toe board rather than on top of it. Furthermore only the remaining free fields shall be on offer. In the next example this restriction excludes position <quote>4</quote>:</para> <screen>Player June(O) vs. Bill(X) Free fields | | 1|2|3 -+-+- -+-+- O| | |5|6 -+-+- -+-+- | | 7|8|9 Bill, please enter next field's number:</screen> </listitem> </orderedlist> </glossdef> </glossentry> </glosslist> </question> <answer> <annotation role="make"> <para role="eclipse">P/Sd1/TicTacToe/V2</para> </annotation> </answer> </qandaentry> </qandadiv> </qandaset> </section> <section xml:id="sd1SectTicTacToeComputerVsHuman"> <title>Tic-tac-toe, Computer vs. human</title> <qandaset defaultlabel="qanda" xml:id="sd1QandaTicTacToeComputerVsHuman"> <qandadiv> <qandaentry> <question> <para>This exercise is beyond the current lecture's scope. Feel free to solve it at your own discretion if you are desperately searching for a more challenging problem.</para> <para>Your solution should allow for humans playing <productname>tic-tac-toe</productname> against a computer:</para> <figure xml:id="sd1FigTicTacToeHumanVsComputer"> <title>Two Tic-tac-toe players fighting each other.</title> <mediaobject> <videoobject> <videodata fileref="Fig/tttHumanVsComputer.webm"/> </videoobject> </mediaobject> </figure> <para>The underlying logic is considerately more difficult to implement and requires recursion as being introduced in <xref linkend="sd1SectFactorialRecursive"/>. You may want to read:</para> <itemizedlist> <listitem> <para><link xlink:href="http://www.flyingmachinestudios.com/programming/minimax">An Exhaustive Explanation of Minimax, a Staple AI Algorithm</link></para> </listitem> <listitem> <para><link xlink:href="http://neverstopbuilding.com/minimax">Tic Tac Toe: Understanding The Minimax Algorithm</link></para> </listitem> </itemizedlist> </question> <answer> <annotation role="make"> <para role="eclipse">P/Sd1/TicTacToe/V4</para> </annotation> </answer> </qandaentry> </qandadiv> </qandaset> </section> </section> <section xml:id="sd1StoreStatistics"> <title>Providing statistical data</title> <qandaset defaultlabel="qanda" xml:id="sd1QandaIntStoreStat"> <title>Adding support to retrieve statistical data.</title> <qandadiv> <qandaentry> <question> <para>Extend <xref linkend="sd1QandaIntStoreUnbounded"/> by providing a method <methodname>double getAverage()</methodname> to provide statistical data on a given set of integer values. In addition provide a method <methodname>void clear()</methodname> enabling a user to support different sets of values.</para> <para>Do not forget to extend your <xref linkend="glo_Junit"/> tests. You may want to import the <link xlink:href="https://gitlab.mi.hdm-stuttgart.de/goik/GoikLectures/tree/master/P/Sd1/Array/integerStoreStat">skeleton project</link> for getting started.</para> <caution> <para>When testing for equality of double values you may find the <xref linkend="glo_Junit"/> method <methodname xlink:href="http://junit.sourceforge.net/javadoc/org/junit/Assert.html#assertEquals(double,%20double)">assertEquals()</methodname>to be marked as <link xlink:href="https://docs.oracle.com/javase/1.5.0/docs/guide/javadoc/deprecation/deprecation.html">deprecated</link>. Give a reason why this decision has been taken. The answer may guide you in finding a more appropriate test.</para> </caution> </question> <answer> <annotation role="make"> <para role="eclipse">P/Sd1/Array/integerStoreStat</para> </annotation> <para>Testing for equality of two <code language="java">double</code> variables is generally a bad idea. Consider:</para> <programlisting language="java">double b= 1./3.; b++; b--; System.out.println(3 * b);</programlisting> <para>This yields:</para> <screen>0.9999999999999998</screen> <para>Thus <code language="java">assertEquals(1., b)</code> will fail due to limited arithmetic precision. <xref linkend="glo_Junit"/> provides a method <code language="java" xlink:href="https://junit.org/junit4/javadoc/latest/org/junit/Assert.html#assertEquals(double,%20double,%20double)">assertEquals(double expected, double actual, double delta)</code> addressing this problem:</para> <programlisting language="java">@Test public void testApp() { double b= 1./3.; b++; b--; Assert.assertEquals(1., 3 * b, 1.E-15); }</programlisting> <para>The last parameter represents the allowed bias with respect to the expected result. In the above example every value within the range <inlineequation> <m:math display="inline"> <m:mrow> <m:mo>[</m:mo> <m:mrow> <m:mrow> <m:mi>1</m:mi> <m:mo>-</m:mo> <m:msup> <m:mi>10</m:mi> <m:mrow> <m:mo>-</m:mo> <m:mi>15</m:mi> </m:mrow> </m:msup> </m:mrow> <m:mo>,</m:mo> <m:mrow> <m:mi>1</m:mi> <m:mo>+</m:mo> <m:msup> <m:mi>10</m:mi> <m:mrow> <m:mo>-</m:mo> <m:mi>15</m:mi> </m:mrow> </m:msup> </m:mrow> </m:mrow> <m:mo>]</m:mo> </m:mrow> </m:math> </inlineequation> will show up as a positive test result.</para> </answer> </qandaentry> </qandadiv> </qandaset> </section> <section xml:id="sd1PrimeRevisit"> <title>Prime numbers revisited</title> <section xml:id="sd1PrimeSimple"> <title>A simple algorithm</title> <qandaset defaultlabel="qanda" xml:id="sd1QandaPrimTest"> <title>Testing an implementation</title> <qandadiv> <qandaentry> <question> <para>Consider the following method aimed to test whether a given <code language="java">long</code> number is prime or not:</para> <programlisting language="java">/** * Test, whether a given number is prime. * @param candidate The number to be assessed * @return true if candidate is prime, false otherwise * <dl> * <dt>Precondition:</dt> * <dd>2 &lt;= candidate</dd> * </dl> **/ public static boolean isPrime(final long candidate) { for (long i = 2; i * i < candidate; i++) { // Just test up to square if (0 == candidate % i) { // root of candidate. return false; } } return true; }</programlisting> <orderedlist> <listitem> <para>Write a <emphasis role="bold">concise</emphasis> test which tests the above method for all numbers within the range [2, 100]. You need to know all prime numbers from this set in order to implement a <emphasis role="bold">complete</emphasis> test for both directions <quote>is prime</quote> and <quote>is not prime</quote>.</para> </listitem> <listitem> <para>In case you find errors correct them.</para> </listitem> <listitem> <para>Write a method which tests prime number candidates up to an arbitrary limit (say limit == 10000) and returns the number of primes within [2, limit]. Measure this method's execution time. You may want to consult <methodname xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/System.html#currentTimeMillis()">System.currentTimeMillis()</methodname> or <methodname xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/System.html#nanoTime()">System.nanoTime()</methodname> for that purpose.</para> </listitem> </orderedlist> </question> <answer> <annotation role="make"> <para role="eclipse">P/Sd1/Prime/V1</para> </annotation> <orderedlist> <listitem> <para>We want to test whether our <methodname>boolean isPrime(final long candidate)</methodname> method classifies prime numbers as such and whether this message is able to tell non-primes as well. We achieve this by defining a boolean array having indexes ranging from 0 to 100 (inclusive). We then:</para> <itemizedlist> <listitem> <para>Set all array values to false</para> </listitem> <listitem> <para>Set all array values to true if their index is a prime number. This of course requires to know all prime numbers below 100.</para> </listitem> </itemizedlist> <para>This array then allows us to test our method for correctness for values up to 100:</para> <programlisting language="java">public class TestPrimes { @Test public void primeTest() { final int[] primeNumbers = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 31, 37, 41, 43, 47, 53, 59, 29, 61, 67, 71, 73, 79, 83, 89, 97}; final boolean[] isPrime = new boolean[101]; //Testing 2, 3, 4, .., 99, 100 for (int i = 2; i <= 100; i++) { isPrime[i] = false; } for (final int prime: primeNumbers) { isPrime[prime] = true; } for (int i = 2; i <= 100; i++) { assertEquals("Index=" + i , isPrime[i], PrimeNumbers.isPrime(i)); } }</programlisting> </listitem> <listitem> <para>Executing this test yields an error at index 49. This is due to the chosen limit <code language="java">i * i < candidate</code> in:</para> <programlisting language="java">public static boolean isPrime(final long candidate) { for (long i = 2; i * i < candidate; i++) { ...</programlisting> <para>This is wrong: Having <code language="java">candidate == 49</code> the last value of i to be considered will be 6. So the required test <code language="java">49 % 7</code> will never be executed thus erroneously returning true. We have to modify the loop's limit slightly by using <code language="java">i * i <emphasis role="red"><=</emphasis> candidate</code> instead:</para> <programlisting language="none">public static boolean isPrime(final long candidate) { for (long i = 2; i * i <emphasis role="bold"><emphasis role="red"><=</emphasis></emphasis> candidate; i++) { ...</programlisting> <para>This way <code language="java">49 % 7</code> will be evaluated to zero thus returning <code language="java">false</code> and thereby categorizing 49 as a non-prime number.</para> </listitem> <listitem> <para>Executing <methodname xlink:href="P/Sd1/Prime/V1/target/site/apidocs/de/hdm_stuttgart/mi/sd1/main/PrimeNumbers.html#main(java.lang.String:A)">main()</methodname> allows for estimating the prime number computing performance:</para> <screen>Found 664579 prime numbers within 15.136 seconds.</screen> </listitem> </orderedlist> </answer> </qandaentry> </qandadiv> </qandaset> </section> <section xml:id="sd1PrimePerformance"> <title>Improving performance</title> <qandaset defaultlabel="qanda" xml:id="sd1QandaPrimeFactor"> <title>Improving prime number calculation performance</title> <qandadiv> <qandaentry> <question> <para>Our current algorithm checking for prime numbers wastes a lot computing power. Consider testing candidate value 143. Currently our implementation works like:</para> <screen>143 % 2 == 0 ? No. 143 % 3 == 0 ? No. 143 % 4 == 0 ? No. 143 % 5 == 0 ? No. 143 % 6 == 0 ? No. 143 % 7 == 0 ? No. 143 % 8 == 0 ? No. 143 % 9 == 0 ? No. 143 % 10 == 0 ? No. 143 % 11 == 0 ? Yes ==> 143 is not prime</screen> <para>Learning from <link xlink:href="https://en.wikipedia.org/wiki/Prime_factor">prime factorization</link> it actually suffices testing only prime values rather than all integer values up to the already discussed square root limit:</para> <screen>143 % 2 == 0 ? No. 143 % 3 == 0 ? No. 143 % 5 == 0 ? No. 143 % 7 == 0 ? No. 143 % 11 == 0 ? Yes ==> 143 is not prime</screen> <para>Thus only considering primes we may save a lot of operations. The trade off is even bigger for higher prime number values. This algorithm requires storing all computed prime numbers without gaps thereby reducing required computation time.</para> <para>Implement the above algorithm and compare the elapsed execution time.</para> <tip> <para>Storing prime numbers requires an array (or another type of container). Since we do not know the number of prime numbers beforehand the required array size is not yet known when starting the application. There are different possibilities to deal with this problem:</para> <itemizedlist> <listitem> <para>You may want to reuse your unsorted <classname xlink:href="P/Sd1/Array/integerStoreUnbounded/target/site/apidocs/de/hdm_stuttgart/mi/sd1/store/IntegerStore.html">IntegerStore</classname> implementation to provide a dynamically growing array of integer values.</para> </listitem> <listitem> <para>You may again implement a kind of amortized doubling algorithm allowing for dynamic growth.</para> </listitem> </itemizedlist> </tip> </question> <answer> <annotation role="make"> <para role="eclipse">P/Sd1/Prime/V2</para> </annotation> <para>We save ~80% of execution time:</para> <screen>Found 664579 prime numbers within 2.641 seconds.</screen> <para>So the current implementation indeed adds a substantial benefit with respect to performance.</para> </answer> </qandaentry> </qandadiv> </qandaset> </section> </section> <section xml:id="sd1Median"> <title>The median of a given sample.</title> <qandaset defaultlabel="qanda" xml:id="sd1QandaMedian"> <title>Calculating the median</title> <qandadiv> <qandaentry> <question> <para>Read the <link xlink:href="https://en.wikipedia.org/wiki/Median">definition of a given sample's median</link>.</para> <para>We want to extend exercise <xref linkend="sd1QandaIntStoreStat"/> by adding a method <methodname>int getMedian()</methodname>. For this purpose our current implementation lacks ordering of input values. Consider the following sample of values:</para> <screen>2, 7, 0, -3, 4</screen> <para>Obtaining the median requires ordering these values:</para> <screen>-3, 0, 2, 4, 7</screen> <para>Thus the given sample's median is 2. Solve this exercise in the following order:</para> <orderedlist> <listitem> <para>For testing and other purposes it is convenient to provide an additional method returning the array of values being added so far:</para> <programlisting language="java">/** * @return The array of values entered so far */ public int[] getValues() { ... return ...; }</programlisting> <caution> <para>Do not just return your internal array <code language="java">int[] values</code>! Due to the amortized doubling implementation this will in most cases contain unused positions on top of added values.</para> <para>You may either construct a suitable copy containing the current elements yourself or get enlightened by reading the <xref linkend="glo_API"/> documentation of <link xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Arrays.html#copyOfRange(int%5B%5D,int,int)">copyOfRange(...)</link>.</para> </caution> </listitem> <listitem> <para>Provide some tests to assure your sorting implementation works well. You'll implement the actual sorting in the next step. Right now testing for correct sorting will fail (unless a given set of values had already been added in ascending order). A test might look like:</para> <programlisting language="java">final int[] unsortedValues = {0, -1, 5, 2, 7, 6}, sortedValues = {-1, 0, 2, 5, 6, 7}; IntegerStore store = new IntegerStore(); for (final int i: unsortedValues) { store.addValue(i); } // Now check your store for correctly sorted order of elements ...</programlisting> <para>Do not forget to consider value sets which include duplicates and write tests accordingly!</para> <para>Hint: The <xref linkend="glo_Junit"/> <xref linkend="glo_framework"/> provides a (convenience) method <methodname xlink:href="http://junit.sourceforge.net/javadoc/org/junit/Assert.html#assertArrayEquals(int[],%20int[])">assertArrayEquals(...)</methodname>.</para> </listitem> <listitem> <para>Modify your<methodname xlink:href="P/Sd1/Array/integerStoreStat/target/site/apidocs/de/hdm_stuttgart/mi/sd1/store/IntegerStore.html#addValue(int)"> addValue(...)</methodname> method's implementation. Though there are more elaborate sorting methods available in Java we'll do it the hard way ourselves in this exercise. Consider the following example:</para> <programlisting language="java">store.addValue(1); store.addValue(2); store.addValue(7); store.addValue(9); store.addValue(3);</programlisting> <para>Prior to inserting a new value our <methodname xlink:href="P/Sd1/Array/integerStoreStat/target/site/apidocs/de/hdm_stuttgart/mi/sd1/store/IntegerStore.html#addValue(int)">addValue(...)</methodname> method shall find a suitable position inside the array of already added values to insert the new value. When adding the last value 3 in the above example the internal array already contains the values (1, 2, 7, 9). Traversing this array shows that the new value of 3 should be inserted between 2 and 7.</para> <para>Thus a general strategy inserting a new value candidate might be:</para> <orderedlist> <listitem> <para>Find the first index pointing to an existing value being larger or equal to the given candidate. In the above example this index value is 2 pointing to value 7.</para> <para>If there is no such existing value just add the new value at the array's top end like you did before when not yet bothering about sorting.</para> </listitem> <listitem> <para>Shift the <quote>right</quote> part of the array starting at index 2 in our example one position to the right thus creating a free (denoted by <quote>F</quote>) insert position:</para> <screen>Index values | 0| 1| 2| 3| 4| 5| ... -----------------+--+--+--+--+-----+ ... values oldArray | 1| 2| 7| 9| | | -----------------+--+--+--+--+-----+ ... values newArray | 1| 2| F| 7| 9| | ...</screen> <para>You may now insert your latest value 3 at the free index position 2 ending up with a well sorted array (1, 2, 3, 7, 9).</para> <para>This example just illustrates a (very simple!) sorting algorithm.</para> <para>Hint: On implementation be very careful with respect to <quote>off by one</quote> errors you are likely to encounter. The tests you have written beforehand will guide you.</para> </listitem> </orderedlist> </listitem> <listitem> <para>Provide a constructor <code language="java">public IntegerStore(final int[] values)</code> in a meaningful way with respect to median calculations.</para> </listitem> <listitem> <para>Add a dummy implementation <methodname>double getMedian()</methodname>{return 0;} to your class <classname>IntegerStore</classname> from exercise <xref linkend="sd1QandaIntStoreStat"/>.</para> </listitem> <listitem> <para>Provide some tests both for even and uneven sample sizes. All of these will probably fail till you complete your implementation.</para> </listitem> <listitem> <para>Finally complete the desired <code language="java">double getMedian()</code> method's implementation and actually test it. There must be at least one element in order to be able returning a meaningful result:</para> <programlisting language="java">/** * <dl> * <dt><b>Precondition:</b></dt> * <dd>There must be at least one element.</dd> * </dl> * * @return The sample's median. */ public double getMedian() { ... return ... ; }</programlisting> </listitem> <listitem> <para>Implement a main method as in <xref linkend="sd1QandaConsoleInput"/> asking the user for an arbitrary number of values. Then compute both their average and median like:</para> <screen>How big is your sample? 5 Enter value #1 of 5: 1 Enter value #2 of 5: -2 Enter value #3 of 5: 1 Enter value #4 of 5: 5 Enter value #5 of 5: 2 Your sample's average is: 1.4 Your sample's median is: 1.0</screen> </listitem> </orderedlist> </question> <answer> <annotation role="make"> <para role="eclipse">P/Sd1/Array/integerStoreMedianAnswer</para> </annotation> <orderedlist> <listitem> <para>The <link xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Arrays.html#copyOfRange(int%5B%5D,int,int)">copyOfRange(...)</link> method in <methodname xlink:href="P/Sd1/Array/integerStoreMedianAnswer/target/site/apidocs/de/hdm_stuttgart/mi/sd1/store/IntegerStore.html#getValues()">getValues()</methodname> returns that portion of our <code language="java">int[] values</code> array actually been filled with data.</para> </listitem> <listitem> <para>Provide some tests assuring your sorting implementation works well prior to actually implementing the actual sorting in the next step. Right now testing for correct sorting will fail (unless a given set of values had already been added in ascending order). A test might look like:</para> <programlisting language="java">final int[] unsortedValues = {0, -1, 5, 2, 7, 6}, sortedValues = {-1, 0, 2, 5, 6, 7}; IntegerStore store = new IntegerStore(); for (final int i: unsortedValues) { store.addValue(i); } // Now check your store for correctly sorted order of elements ...</programlisting> <para>Do not forget to consider value sets which include duplicates and write tests accordingly!</para> <para>Hint: The <xref linkend="glo_Junit"/> <xref linkend="glo_framework"/> provides a (convenient) method <methodname xlink:href="http://junit.sourceforge.net/javadoc/org/junit/Assert.html#assertArrayEquals(int[],%20int[])">assertArrayEquals(...)</methodname>.</para> </listitem> <listitem> <para>Modify your<methodname xlink:href="P/Sd1/Array/integerStoreStat/target/site/apidocs/de/hdm_stuttgart/mi/sd1/store/IntegerStore.html#addValue(int)"> addValue(...)</methodname> method's implementation. Though there are more elaborate sorting methods available in Java we'll do it the hard way ourselves in this exercise. Consider the following example:</para> <programlisting language="java">store.addValue(1); store.addValue(2); store.addValue(7); store.addValue(9); store.addValue(3);</programlisting> <para>Prior to inserting a new value our <methodname xlink:href="P/Sd1/Array/integerStoreStat/target/site/apidocs/de/hdm_stuttgart/mi/sd1/store/IntegerStore.html#addValue(int)">addValue(...)</methodname> method shall find a suitable position inside the array of already added values to insert the new value. When adding the last value 3 in the above example the internal array already contains the values (1, 2, 7, 9). Traversing this array shows that the new value of 3 should be inserted between 2 and 7.</para> <para>Thus a general strategy inserting a new value candidate might be:</para> <orderedlist> <listitem> <para>Find the first index pointing to an existing value being larger or equal to the given candidate. In the above example this index value is 2 pointing to value 7.</para> <para>If there is no such existing value just add the new value at the array's top as you did without bothering about sorting.</para> </listitem> <listitem> <para>Shift the <quote>right</quote> part of the array starting at index 2 in our example one position to the right thus creating a free (denoted by <quote>F</quote>) insert position:</para> <screen>Index values | 0| 1| 2| 3| 4| 5| ... -----------------+--+--+--+--+-----+ ... values oldArray | 1| 2| 7| 9| | | -----------------+--+--+--+--+-----+ ... values newArray | 1| 2| F| 7| 9| | ...</screen> <para>You may now insert your latest value 3 at the free index position 2 ending up with a well sorted array (1, 2, 3, 7, 9).</para> <para>This example just illustrates a (very simple!) sorting algorithm.</para> <para>Hint: On implementation be very careful with respect to <quote>off by one</quote> errors you are likely to encounter. The tests you have written beforehand will guide you.</para> </listitem> </orderedlist> </listitem> <listitem> <para>The constructor <methodname xlink:href="P/Sd1/Array/integerStoreMedianAnswer/target/site/apidocs/de/hdm_stuttgart/mi/sd1/store/IntegerStore.html#IntegerStore(int:A)">public IntegerStore(final int[] values)</methodname> internally uses our <methodname xlink:href="P/Sd1/Array/integerStoreMedianAnswer/target/site/apidocs/de/hdm_stuttgart/mi/sd1/store/IntegerStore.html#addValue(int)">addValue(...)</methodname> method thus adding each array value one by one. Consider an alternative naive implementation:</para> <programlisting language="java">public IntegerStore(final int[] values) { this.values = values; }</programlisting> <para>This will fail in most cases since the array parameter typically contains unsorted values.</para> <para>Having this constructor in place also simplifies writing tests:</para> <programlisting language="java">... @Test public void testMedian() { IntegerStore store = new IntegerStore(new int[] {2, 7, 0, -3, 4}); assertArrayEquals(new int[] {-3, 0, 2, 4, 7}, store.getValues()); assertTrue(Math.abs(2. - store.getMedian()) < 1.E-10); ...</programlisting> </listitem> <listitem> <para>-</para> </listitem> <listitem> <programlisting language="java">@Test public void testMedian() { IntegerStore store = new IntegerStore(new int[] {2, 7, 0, -3, 4}); assertArrayEquals(new int[] {-3, 0, 2, 4, 7}, store.getValues()); assertTrue(Math.abs(2. - store.getMedian()) < 1.E-10); store.addValue(7); assertArrayEquals(new int[] {-3, 0, 2, 4, 7, 7}, store.getValues()); assertTrue(Math.abs(3. - store.getMedian()) < 1.E-10); store.addValue(7); assertArrayEquals(new int[] {-3, 0, 2, 4, 7, 7, 7}, store.getValues()); assertTrue(Math.abs(4. - store.getMedian()) < 1.E-50); store.addValue(6); assertArrayEquals(new int[] {-3, 0, 2, 4, 6, 7, 7, 7}, store.getValues()); assertTrue(Math.abs(5. - store.getMedian()) < 1.E-50); }</programlisting> </listitem> <listitem> <para><methodname xlink:href="P/Sd1/Array/integerStoreMedianAnswer/target/site/apidocs/de/hdm_stuttgart/mi/sd1/store/IntegerStore.html#getMedian()">double getMedian()</methodname></para> </listitem> <listitem> <para><methodname xlink:href="P/Sd1/Array/integerStoreMedianAnswer/target/site/apidocs/de/hdm_stuttgart/mi/sd1/main/Driver.html#main(java.lang.String:A)">main(...)</methodname></para> </listitem> </orderedlist> </answer> </qandaentry> </qandadiv> </qandaset> </section> <section xml:id="sd1SectPlottingFunctions"> <title>Plotting functions</title> <qandaset defaultlabel="qanda" xml:id="sd1QandaPlottingFunctions"> <title>A simple character based plotting application</title> <qandadiv> <qandaentry> <question> <para>Implement a class to plot e.g. <code language="java">sin(x)</code> and other functions in a terminal like e.g.:</para> <screen> ****** ** ** * ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** * ** ** ******</screen> </question> <answer> <annotation role="make"> <para role="eclipse">P/Sd1/plot/Basic</para> </annotation> <para>The current solution is not yet very flexible: The intended plot function is hard coded within the <classname>PlotSine</classname> class:</para> <programlisting language="java"> static void plotSine() { init(); for (int xTics = 0; xTics < numTicsX; xTics++) { double x = xMin + xTics * xStepWidth; <emphasis role="bold">double sinOfX = Math.sin(x);</emphasis> ... } }</programlisting> <para>You'll find a more sophisticated approach using interfaces in upcoming <xref linkend="sd1SectPlotterInterface"/>.</para> </answer> </qandaentry> </qandadiv> </qandaset> </section> </chapter>