gdi2, tgdi sources

This commit is contained in:
Ulf Gebhardt 2013-12-19 19:04:55 +01:00
parent b77a79b7d3
commit a1b2c502cc
584 changed files with 112145 additions and 0 deletions

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>GDI 2 U1</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,12 @@
#Thu Apr 22 09:55:02 CEST 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,20 @@
class a
{
public static int potenz(int basis, int exponent)
{
if (exponent==1) return basis;
int temp = potenz(basis,exponent/2);
temp = temp*temp;
if ((exponent % 2) == 0) {
return temp;
} else {
return temp*basis;
}
}
}

View File

@ -0,0 +1,67 @@
public class selectionsort {
final static int[] data = {23,11,13,44,14,24,22,12,21,32,41,43,31,33,34,42};
public void selectionSort2(int[] x) {
for (int i=0; i<x.length-1; i++) {
int minIndex = i; // Index of smallest remaining value.
for (int j=i+1; j<x.length; j++) {
if (x[minIndex] > x[j]) {
minIndex = j; // Remember index of new minimum
}
}
if (minIndex != i) {
//... Exchange current element with smallest remaining.
int temp = x[i];
x[i] = x[minIndex];
x[minIndex] = temp;
System.out.println("step: "+i+" "+minIndex+" number:"+temp+" "+x[i]);
printdata();
}
}
}
public void selectionSort(int[] x) {
for (int i=0; i<x.length-1; i++) {
for (int j=i+1; j<x.length; j++) {
if (x[i] > x[j]) {
//... Exchange elements
int temp = x[i];
x[i] = x[j];
x[j] = temp;
System.out.println("step: "+i+" "+j+" number:"+temp+" "+x[i]);
printdata();
}
}
}
}
public void printdata()
{
String s = new String("{");
for(int i=0; i<data.length; i++)
{
s += data[i];
s += ",";
}
s += "}";
System.out.println(s);
}
/**
* @param args
*/
public static void main(String[] args) {
new selectionsort().selectionSort2(data);
}
}

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>H6 GDI</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,12 @@
#Wed Jun 02 10:07:28 CEST 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6

Binary file not shown.

View File

@ -0,0 +1,85 @@
public class h6_6a_gdi {
//Die Adiazenzmatrix für ein Ungerichteten Graphen mit booleans dargestellt
public static final boolean[][] Adiazenz =
{{false, false, true, true, false },
{false, false, true, false, true },
{true, true, false, true, false },
{true, false, true, true, false },
{false, true, false, false, false }};
public boolean[][] calculate()
{
//Zähler für die Kanten
int connections = 0;
//Durchsuche obere Dreiecksmatrix der AidazenzMatrix
for(int i=0; i<Adiazenz.length; i++)
{
for(int j=i; j<Adiazenz.length; j++)
{
//Falls Kante zähle Katenzähler hoch
if(Adiazenz[i][j])
{
connections++;
}
}
}
//Inzidenz-Matrix |V|*|E|
boolean[][] result = new boolean[Adiazenz.length][connections];
//Spalten Zähler (aktuelle Kanten)
int curcon = 0;
//Durchsuche obere Dreiecksmatrix der AidazenzMatrix
for(int i=0; i<Adiazenz.length; i++)
{
for(int j=i; j<Adiazenz.length; j++)
{
//Falls Kante in AdianzenzMatrix
if(Adiazenz[i][j])
{
//Setzte für Knoten der x-Achse(j) und der
//y-Achse(i) der Adiazenzmatrix den Wert der
//aktuellen Kante in der Inzidenzmatrix auf true.
result[i][curcon] = true;
result[j][curcon] = true;
curcon ++; //nächste Kante
}
}
}
//Ergebnis zurückgeben
return result;
}
//Die InzidenzMatrix ausgeben
public void calcandprint()
{
boolean[][] result = calculate();
String output = new String();
for(int i=0; i< result.length; i++)
{
for(int j=0; j< result[i].length;j++)
{
output += result[i][j] + "\t";
}
output += "\n";
}
System.out.println(output);
}
//Main...
public static void main(String[] args) {
new h6_6a_gdi().calcandprint();
}
}

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Project0</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,12 @@
#Thu Apr 15 17:29:36 CEST 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,246 @@
Aegypten
Aequatorialguinea
Aethiopien
Afghanistan
Aland
Albanien
Algerien
Amerikanisch-Samoa
Amerikanische Jungferninseln
Andorra
Angola
Anguilla
Antarktis
Antigua und Barbuda
Argentinien
Armenien
Aruba
Ascension
Aserbaidschan
Australien
Bahamas
Bahrain
Bangladesch
Barbados
Belgien
Belize
Benin
Bermuda
Bhutan
Bolivien
Bosnien und Herzegowina
Botswana
Bouvetinsel
Brasilien
Britische Jungferninseln
Britisches Territorium im Indischen Ozean
Brunei
Bulgarien
Burkina Faso
Burundi
Chile
China
Cookinseln
Costa Rica
Cote d'Ivoire
Daenemark
Deutschland
Die Kronkolonie St. Helena und Nebengebiete
Diego Garcia
Dominica
Dominikanische Republik
Dschibuti
Ecuador
El Salvador
Eritrea
Estland
Europaeische Union
Falklandinseln
Fidschi
Finnland
Frankreich
Franzoesisch-Guayana
Franzoesisch-Polynesien
Franzoesische Sued- und Antarktisgebiete
Gabun
Gambia
Georgien
Ghana
Gibraltar
Grenada
Griechenland
Gruenland
Guadeloupe
Guam
Guatemala
Guernsey
Guinea
Guinea-Bissau
Guyana
Haiti
Heard und McDonaldinseln
Honduras
Hongkong
Indien
Indonesien
Insel Mann
Irak
Iran
Irland
Island
Israel
Italien
Jamaika
Japan
Jemen
Jersey
Jordanien
Kaimaninseln
Kambodscha
Kamerun
Kanada
Kanarische Inseln
Kap Verde
Kasachstan
Katar
Kenia
Kirgisistan
Kiribati
Kokosinseln
Kolumbien
Komoren
Kongo
Kongo
Korea
Korea
Kosovo
Kroatien
Kuba
Kuwait
Laos
Lesotho
Lettland
Libanon
Liberia
Libyen
Liechtenstein
Litauen
Luxemburg
Macao
Madagaskar
Malawi
Malaysia
Malediven
Mali
Malta
Marokko
Marshallinseln
Martinique
Mauretanien
Mauritius
Mayotte
Mazedonien
Mexiko
Moldawien
Monaco
Mongolei
Montenegro
Montserrat
Mosambik
Myanmar
Namibia
Nauru
Nepal
Neukaledonien
Neuseeland
Neutrale Zone
Nicaragua
Niederlande
Niederlanndische Antillen
Niger
Nigeria
Niue
Norfolkinsel
Norwegen
Noerdliche Marianen
Oesterreich
Oman
Pakistan
Palaestinensische Autonomiegebiete
Palau
Panama
Papua-Neuguinea
Paraguay
Peru
Philippinen
Pitcairninseln
Polen
Portugal
Puerto Rico
Ruanda
Rumänien
Russland
Salomonen
Sambia
Samoa
San Marino
Saudi-Arabien
Schweden
Schweiz
Senegal
Serbien
Seychellen
Sierra Leone
Simbabwe
Singapur
Slowakei
Slowenien
Somalia
Spanien
Sri Lanka
St. Kitts und Nevis
St. Lucia
St. Pierre und Miquelon
St. Vincent und die Grenadinen (GB)
Sudan
Suedafrika
Suriname
Svalbard und Jan Mayen
Swasiland
Syrien
Suedgeorgien und die Suedlichen Sandwichinseln
Tadschikistan
Taiwan
Tansania
Thailand
Timor-Leste
Togo
Tokelau
Tonga
Trinidad und Tobago
Tristan da Cunha
Tschad
Tschechische
Tuerkei
Tunesien
Turkmenistan
Turks- und Caicosinseln
Tuvalu
Uganda
Ukraine
Ungarn
Uruguay
Usbekistan
Vanuatu
Vatikanstadt
Venezuela
Vereinigte Arabische Emirate
Vereinigte Staaten von Amerika
Vereinigtes Koenigreich von Grossbritannien und Nordirland
Vietnam
Wallis und Futuna
Weihnachtsinsel
Weißrussland
Westsahara
Zentralafrikanische Republik
Zypern

View File

@ -0,0 +1,146 @@
/*******************************************************************
* Gruppe: Timo Singer, Michael Scholz, Ulf Gebhardt
*
*******************************************************************
*
* Questions / Fragen
*******************************************************************
* a) How does the measured performance of contains_fast and
* contains_lecture relate to each other? Explain the result!
*
* Wie verh<EFBFBD>lt sich die gemessene Laufzeit von den Methoden
* contains_fast und contains_lecture zu einander?
* Erkl<EFBFBD>ren Sie das Ergebnis!
* ----------------------------------------------------------------
*
* contains_fast ist circa doppelt (2x) so schnell, ben<EFBFBD>tigt also in etwa
* die H<EFBFBD>lfte der Zeit, die contains_lecture ben<EFBFBD>tigt.
*
* Dieses Verhalten l<EFBFBD>sst sich dadurch erkl<EFBFBD>ren, dass das gesuchte Element
* im Mittel in der Mitte der Liste liegt, d.h. die for-schleife in
* contains_fast (im Mittel = f<EFBFBD>r sehr viele Aufrufe) schon nach der H<EFBFBD>lfte
* abbricht, da das Element gefunden wurde und die funktion mit return
* verlassen wird.
*
* Vergleich der Funktionen:
*
* Eingabemenge Funktion Schleifendurchl<EFBFBD>ufe
* n contains_lecture n (jedes mal)
* n contains_fast n/2 (im Durchschnitt!)
* ----------------------------------------------------------------
* b) The method contains_java calls the predefined Java contains
* function for Lists. How does contains_java perform compared to
* the other methods? Do you have an idea, why?
*
* Die Methode contains_java ruft die in der Java-API vordefinierte
* contains-Funktion f<EFBFBD>r Listen auf. Wie verh<EFBFBD>lt sich die Laufzeit
* von contains_java zu den anderen? Was k<EFBFBD>nnte der Grund sein?
* ----------------------------------------------------------------
*
* contains_java ist nochmal schneller als contains_fast.
*
* D.h, wenn man alle 3 Funktionen vergleicht, dann gilt f<EFBFBD>r die Laufzeit
* im Durchschnitt:
*
* Laufzeit (im Durchschnitt):
*
* contains_lecture > contains_fast > contains_java
*
* contains_java ist schneller als contains_fast, da die f<EFBFBD>r Listen
* in der Java-API definierte Funktion einen noch effizienteren
* Suchalgorithmus benutzt, als contains_fast.
*
* Wir vermuten, dass als Suchalgorithmus die Bin<EFBFBD>re-Suche eingesetzt wird.
* Diese hat eine Komplexit<EFBFBD>t von O(log(n)), im Gegensatz zu O(n) f<EFBFBD>r
* contains_lecture & contains_fast.
*
* Eine andere Erkl<EFBFBD>rungsm<EFBFBD>glichkeit, warum contains_java schneller ist, ist
* dass die List-Klasse intern Hashing vornimmt. Dies f<EFBFBD>hrt im Durchschnitt
* zu einem O(1), im schlechtesten Fall allerdings zu O(n).
*
*******************************************************************/
import java.util.List;
import java.util.Random;
/**
* This class offers three different implementations of the "contains" method.
* Each method takes a list of strings and a string and checks whether the
* string is contained in the list.
*/
public class Contains {
/**
* Calls the "contains"-function predefined by the Java List class.
*
* @param list A list of strings
* @param element A single string
* @return True if element is contained in list, false otherwise.
*/
public boolean contains_java(List<String> list, String element) {
return list.contains(element);
}
/**
* The contains function as defined in the lecture
* (Slide set 3, page 11).
*
* @param list A list of strings
* @param element A single string
* @return True if element is contained in list, false otherwise.
*/
public boolean contains_lecture(List<String> list, String element) {
boolean found = false;
for (String s : list) {
if (s.equals(element)) {
found = true;
}
}
return found;
}
/**
* Implemented a small optimization for the contains function
* defined in the lecture: As soon as the element is found,
* true is returned and iteration stops
*
* @param list A list of strings
* @param element A single string
* @return True if element is contained in list, false otherwise.
*/
public boolean contains_fast(List<String> list, String element) {
for (String s : list) {
if (s.equals(element)) {
return true;
}
}
return false;
}
/**
* Reads a list and performs a lot of random lookups using the three
* contains methods defined above. The elements looked for are
* randomly chosen from the list beforehand.
*
* @param argv not used
*/
public static void main(String[] argv) {
Contains c = new Contains();
// Reads a long list of strings
ListFileReader fr = new ListFileReader("countries.txt");
// Random number generator
Random rand = new Random();
List<String> list = fr.getList();
int length = list.size();
for (int i=0; i<5000; i++) {
// Read a random string from the list
String string = list.get(rand.nextInt(length));
// Check whether the string is contained (should always return true)
c.contains_lecture(list, string);
c.contains_fast(list, string);
c.contains_java(list, string);
}
}
}

View File

@ -0,0 +1,44 @@
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
public class ListFileReader{
private String filename = null;
private List<String> dataList = null;
public ListFileReader(String filename) {
this.filename = filename;
this.dataList = new LinkedList<String>();
readFile();
}
public void readFile() {
try {
FileReader fr = new FileReader(filename);
BufferedReader in = new BufferedReader(fr);
String line;
while((line = in.readLine())!=null) {
dataList.add(line);
for (int i=0; i<100; i++) {
dataList.add(line + i);
}
}
in.close();
fr.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public List<String> getList(){
return dataList;
}
}

View File

@ -0,0 +1,69 @@
import static org.junit.Assert.*;
import java.util.LinkedList;
import org.junit.BeforeClass;
import org.junit.Test;
public class ContainsTest {
static ListFileReader fr = null;
static Contains c = null;
static String myCountry = null;
static String noCountry = null;
@BeforeClass
public static void init() {
c = new Contains();
fr = new ListFileReader("countries.txt");
myCountry = "Senegal";
noCountry = "12345";
}
@Test
public void testJavaContainsTrue() {
assertTrue(c.contains_java(fr.getList(), myCountry));
}
@Test
public void testJavaContainsFalse() {
assertFalse(c.contains_java(fr.getList(), noCountry));
}
@Test
public void testJavaContainsEmptyList() {
assertFalse(c.contains_java(new LinkedList<String>(), noCountry));
}
@Test
public void testLectureContainsTrue() {
assertTrue(c.contains_lecture(fr.getList(), myCountry));
}
@Test
public void testLectureContainsFalse() {
assertFalse(c.contains_lecture(fr.getList(), noCountry));
}
@Test
public void testLectureContainsEmptyList() {
assertFalse(c.contains_lecture(new LinkedList<String>(), noCountry));
}
@Test
public void testFastContainsTrue() {
assertTrue(c.contains_fast(fr.getList(), myCountry));
}
@Test
public void testFastContainsFalse() {
assertFalse(c.contains_fast(fr.getList(), noCountry));
}
@Test
public void testFastContainsEmptyList() {
assertFalse(c.contains_fast(new LinkedList<String>(), noCountry));
}
}

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Project1</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,12 @@
#Sat May 08 11:41:49 CEST 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,6 @@
public class CapacityExceededException extends RuntimeException {
private static final long serialVersionUID = -3768115092191702079L;
}

View File

@ -0,0 +1,6 @@
public class ObjectAlreadyPresentException extends RuntimeException {
private static final long serialVersionUID = -6499002999657327239L;
}

View File

@ -0,0 +1,6 @@
public class ObjectNotPresentException extends RuntimeException {
private static final long serialVersionUID = 1870950568231197185L;
}

View File

@ -0,0 +1,80 @@
/**
* An object that can be put into a Rucksack. Each PackingObject
* has a value and a weight.
*
* Each PackingObject also has a unique index, which you can use
* for an optimized storing of PackingObjects in a Rucksack.
*
* @author Johannes Kinder
*/
public class PackingObject {
private static int maxIndex = 0;
/**
* Returns the number of PackingObjects that have been created.
* All test cases ensure that all PackingObjects have been created
* before the first Rucksack object is created. Therefore, you can safely
* use this function to get the total number of PackingObjects.
*
* @return the number of packing objects that have been created.
*/
public static int getTotalNumberOfObjects() {
return maxIndex;
}
/**
* This is used by the test cases to reset the counter for PackingObjects.
*/
public static void reset() {
maxIndex = 0;
}
private final int value;
private final int weight;
private final int index;
public PackingObject(int value, int weight) {
this.value = value;
this.weight = weight;
this.index = maxIndex++;
}
/**
* Returns the unique index of this PackingObject.
*
* @return index
*/
public int getIndex() {
return index;
}
/**
* Returns the value of this PackingObject.
*
* @return value
*/
public int getValue() {
return value;
}
/**
* Returns the weight of this PackingObject.
*
* @return weight
*/
public int getWeight() {
return weight;
}
/**
* Creates a string representation of this PackingObject of the
* form (value,weight).
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('(').append(getValue()).append(',').append(getWeight()).append(')');
return sb.toString();
}
}

View File

@ -0,0 +1,215 @@
import java.util.ArrayList;
/**
* The Rucksack class represents a rucksack that holds objects
* of type PackingObject. Implement the predefined interface and
* use it from RucksackProblem.java to solve a Rucksack problem
* instance.
*/
public class Rucksack {
/**
* Max capacity of the rucksack.
*
* Is Initialized with 0
*/
private int m_capacity = 0;
/**
* Current Value of all Objects in rucksack
*
* Initialized with 0
*/
private int m_currentValue = 0;
/**
* Current Weight of all Objects in rucksack.
*
* Initialized with 0
*/
private int m_currentWeight = 0;
/**
* ObjectList
*
* Is initialized. (empty)
*/
//private LinkedList<PackingObject> m_objects = new LinkedList<PackingObject>();
private ArrayList<PackingObject> m_objects = new ArrayList<PackingObject>();
/**
* Do NOT MODIFY!!! -> For Copying and reading only
* @return
*/
public ArrayList<PackingObject> getObjects() {
return m_objects;
}
/**
* Initializes a new Rucksack object with a given capacity.
* Sets up all required data structures.
*
* @param capacity The capacity of the Rucksack.
*/
public Rucksack(int capacity) {
if(capacity >= 0)
{
this.m_capacity = capacity;
} else
{
throw new IllegalArgumentException();
}
}
/**
* Inserts an object into the Rucksack.
*
* @param o The object to be added.
* @throws ObjectAlreadyPresentException if the object is already present.
* @throws CapacityExceededException if the capacity is exceeded by the
* new object.
*/
void putObject(PackingObject o) {
if(this.getTotalCapacity() >= this.getTotalWeight() + o.getWeight())
{
if(!this.contains(o))
{
this.m_objects.add(o);
this.m_currentWeight += o.getWeight();
this.m_currentValue += o.getValue();
} else
{
throw new ObjectAlreadyPresentException();
}
} else
{
throw new CapacityExceededException();
}
}
/**
* Removes an object from the Rucksack.
*
* @param o The object to be removed.
* @throws ObjectNotPresentException if the object is not in the rucksack.
*/
void removeObject(PackingObject o) {
if(this.m_objects.remove(o))
{
this.m_currentValue -= o.getValue();
this.m_currentWeight -= o.getWeight();
} else
{
throw new ObjectNotPresentException();
}
}
/**
* Checks whether an object is contained in the Rucksack
*
* @param o The object to check for.
* @return True if the object is present, false otherwise.
*/
public boolean contains(PackingObject o) {
return this.m_objects.contains(o);
}
/**
* Returns the total weight of all objects in the rucksack.
*
* @return total weight
*/
public int getTotalWeight() {
/*int result = 0;
for(int i = 0; i < this.m_objects.size(); i++)
{
result +=this.m_objects.get(i).getWeight();
}
return result;*/
return this.m_currentWeight;
}
/**
* Returns the total value of all objects in the rucksack.
*
* @return total value
*/
public int getTotalValue() {
/*int result = 0;
for(int i = 0; i < this.m_objects.size(); i++)
{
result +=this.m_objects.get(i).getValue();
}
return result;*/
return this.m_currentValue;
}
/**
* Returns the initial capacity of the rucksack.
*
* @return total capacity
*/
public int getTotalCapacity() {
return this.m_capacity;
}
/**
* Returns the capacity of the Rucksack still available.
*
* @return available capacity
*/
public int getAvailableCapacity() {
return this.getTotalCapacity() - this.getTotalWeight();
}
/**
* Copies the contents of another Rucksack to this Rucksack.
*
* @param other The Rucksack to copy from.
*/
@SuppressWarnings("unchecked")
public void copyFrom(Rucksack other) {
if(other != null)
{
this.m_capacity = other.getTotalCapacity();
this.m_objects = (ArrayList<PackingObject>) other.getObjects().clone();
this.m_currentWeight = other.getTotalWeight();
this.m_currentValue = other.getTotalValue();
}
}
/**
* Prints all objects in this Rucksack by iterating over a list of
* passed PackingObjects and checking for each object whether it
* is in the Rucksack using contains().
*
* You can use this function for debugging purposes.
*
* @param objects The complete list of objects that might be in the
* rucksack
* @return A string of the format [(value1,weight1), (value2,weight2), ...]
*/
public String toString(PackingObject[] objects) {
StringBuilder sb = new StringBuilder();
sb.append('[');
for (PackingObject object : objects) {
if (contains(object)){
sb.append(object.toString()).append(", ");
}
}
if (sb.length() > 1) {
sb.delete(sb.length() - 2, sb.length());
}
sb.append(']');
return sb.toString();
}
}

View File

@ -0,0 +1,246 @@
/*******************************************************************
* Questions / Fragen
*******************************************************************
* a) What are the asymptotic time complexities T(n) of the
* recursive and iterative versions of the algorithm, with n being
* the total number of available packing objects? State your answer
* in big-Oh notation.
*
* Was sind die Laufzeitkomplexit<EFBFBD>ten T(n) der rekursiven und der
* iterativen Version des Algorithmus, wobei n die Anzahl der
* packbaren Objekte ist? Geben Sie die Komplexit<EFBFBD>t in O-Notation an.
* ----------------------------------------------------------------
*
* Iterativ: solveIterative = O()
*
* Recursiv: solveRecursive = O()
* ----------------------------------------------------------------
* b) Use TPTP to profile RucksackProblem.main(). Try different
* values for the variable numObjects in main() and measure the
* total execution time of solveRecursive(int) and solveIterative,
* and the number of recursive calls to solveRecursive. To what
* problem size can you go on your machine?
* Enter at least 5 different, meaningful runs in the table below.
*
* Verwenden Sie TPTP um RucksackProblem.main() zu profilen.
* Probieren Sie verschiedene Werte f<EFBFBD>r die Variable numObjects in
* main() aus und messen Sie die Laufzeit von solveRecursive(int)
* und solveIterative sowie die Anzahl der rekursiven Aufrufe von
* solveRecursive(int). Bis zu welcher Gr<EFBFBD><EFBFBD>e k<EFBFBD>nnen Sie auf Ihrem
* Rechner gehen? Tragen Sie mindestens
* 5 verschiedene, aussagekr<EFBFBD>ftige Resultate in der Tabelle ein.
* ----------------------------------------------------------------
*
*
* numObj | Cumul. time (iter)| Cumul. time (rec) | Recursive calls
* ---------+-------------------+-------------------+----------------
* 5 | | |
* 7 | | |
* 10 | | |
* 12 | | |
* 15 | | |
* 18 | | |
*
*******************************************************************/
import java.util.Deque;
import java.util.LinkedList;
import java.util.NoSuchElementException;
import java.util.Random;
/**
* A class describing an instance of the Rucksack problem. A call to the
* constructor initializes the problem, and a call to solve() starts a
* recursive search.
*/
public class RucksackProblem {
private PackingObject[] objects;
private Rucksack init_rucksack = null;
private Rucksack best_rucksack = null;
/**
* The constructor initializes the class with a set of objects to pack
* and a rucksack of a given capacity.
*
* @param objects An array of PackingObjects to store optimally in the
* rucksack
* @param rucksack A Rucksack that has been initialized with some
* capacity
*/
public RucksackProblem(PackingObject[] objects, Rucksack rucksack) {
//check objects
for(int i=0; i< objects.length; i++)
{
if(objects[i].getValue() < 0 ||
objects[i].getWeight() < 0)
{
throw new IllegalArgumentException();
}
}
//Check rucksack
if(rucksack == null)
{
throw new IllegalArgumentException();
}
//Initialize Data
this.objects = objects;
this.init_rucksack = rucksack;
this.best_rucksack = new Rucksack(0);
}
public Rucksack getOptimalRucksack() {
return this.best_rucksack;
}
public PackingObject[] getAllObjects() {
return objects;
}
/**
* Start the recursive algorithm to solve the Rucksack problem at
* the 0-th object.
*/
public void solveRecursive() {
solveRecursive(0);
}
/**
* The recursive algorithm. Do not use loops here, implement only
* using recursive calls.
*
* For every object, tries to solve the rest of the problem both
* with the object and without the object using recursive calls
* to solveRecursive(i+1).
*
* @param i the current position in the object array.
*/
private void solveRecursive(int i) {
if(i >= this.objects.length)
{
//Anchor -> No Objects left in Array
return;
} else
{
//Solve without the actual object
solveRecursive(i+1);
try
{
//Put Object into Rucksack if possible
this.init_rucksack.putObject(this.objects[i]); //throws
//Is New Rucksack better then the old?
if(init_rucksack.getTotalValue() > best_rucksack.getTotalValue())
{
this.best_rucksack.copyFrom(this.init_rucksack);
}
//Solve with object
solveRecursive(i+1);
//Remove Object again -> so all cases are covered
this.init_rucksack.removeObject(this.objects[i]); //can not throw -> object is in list
//Catch Exceptions if putObject fails
} catch(ObjectAlreadyPresentException e1){}
catch(CapacityExceededException e2){}
}
}
/**
* The iterative version of the algorithm. Do not include any
* recursive calls, but implement it using a loop and a stack.
*
* Loop:
* Have we processed all objects?
* Stop if there are no backtracking points left
* Else backtrack to last object that was put into rucksack
* Remove it and continue with next object
*
* Does the object still fit into the available capacity?
* Put object into rucksack
* Remember this object as a backtracking point
* Remember if the new rucksack is the best we know
*
* Continue loop with next object
*/
public void solveIterative() {
// A stack to use with the algorithm
Deque<Integer> stack = new LinkedList<Integer>();
// The current position in the array of objects
int i = 0;
//Do till done
while(true)
{
//Still objects in array?
if(i < this.objects.length)
{
try
{
//Put Object into Rucksack if possible
this.init_rucksack.putObject(this.objects[i]); //throws
//Put current Index to stack to allow backtracking
stack.push(i);
//Is New Rucksack better then the old?
if(init_rucksack.getTotalValue() > best_rucksack.getTotalValue())
{
this.best_rucksack.copyFrom(this.init_rucksack);
}
//Catch Exceptions if putObject fails
} catch(ObjectAlreadyPresentException e1){}
catch(CapacityExceededException e2){}
i++; //Move to next Object
} else
{
try
{
//get index of backtracking element from stack
int obj = stack.pop(); //throws when empty
//remove the object
this.init_rucksack.removeObject(this.objects[obj]);
//start search with objects excluding the obj from the stack
i = obj +1;
//Catch exception when stack is empty
} catch(NoSuchElementException e1)
{
//All cases covered
return;
}
}
}
}
public static void main(String[] argv) {
int numObjects = 5;
PackingObject[] objects = new PackingObject[numObjects];
Random rand = new Random();
for (int i=0; i<numObjects; i++) {
objects[i] = new PackingObject(rand.nextInt(100), rand.nextInt(100));
}
// Invoke recursive algorithm
Rucksack rucksack = new Rucksack(numObjects * 25);
RucksackProblem problem = new RucksackProblem(objects, rucksack);
problem.solveRecursive();
// Invoke iterative algorithm
rucksack = new Rucksack(numObjects * 25);
problem = new RucksackProblem(objects, rucksack);
problem.solveIterative();
}
}

View File

@ -0,0 +1,320 @@
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
public class RucksackProblemTest {
@Before
public void setUp() throws Exception {
PackingObject.reset();
}
////////////////////////////////////////////////
// Tests for Rucksack object
@Test
public void rucksackCreation() {
int capacity = 50;
Rucksack rucksack = new Rucksack(capacity);
assertEquals(capacity, rucksack.getTotalCapacity());
assertEquals(capacity, rucksack.getAvailableCapacity());
assertEquals(0, rucksack.getTotalWeight());
assertEquals(0, rucksack.getTotalValue());
}
@Test
public void rucksackPutObjectContains() {
int weight1 = 5;
int value1 = 4;
int weight2 = 15;
int value2 = 14;
int capacity = 40;
PackingObject obj1 = new PackingObject(value1, weight1);
PackingObject obj2 = new PackingObject(value2, weight2);
Rucksack rucksack = new Rucksack(capacity);
assertFalse(rucksack.contains(obj1));
rucksack.putObject(obj1);
assertTrue(rucksack.contains(obj1));
assertEquals(weight1, rucksack.getTotalWeight());
assertEquals(value1, rucksack.getTotalValue());
assertEquals(capacity - weight1, rucksack.getAvailableCapacity());
assertFalse(rucksack.contains(obj2));
rucksack.putObject(obj2);
assertTrue(rucksack.contains(obj2));
assertEquals(weight1 + weight2, rucksack.getTotalWeight());
assertEquals(value1 + value2, rucksack.getTotalValue());
assertEquals(capacity - weight1 - weight2, rucksack.getAvailableCapacity());
try {
rucksack.putObject(obj2);
assertTrue("Adding an object already present should throw a ObjectAlreadyPresentException!", false);
} catch (ObjectAlreadyPresentException e) {
}
}
@Test
public void rucksackExceedCapacity() {
int weight1 = 5;
int value1 = 4;
int weight2 = 15;
int value2 = 14;
int capacity = 15;
PackingObject obj1 = new PackingObject(value1, weight1);
PackingObject obj2 = new PackingObject(value2, weight2);
Rucksack rucksack = new Rucksack(capacity);
rucksack.putObject(obj1);
try {
rucksack.putObject(obj2);
assertTrue("Adding an object above capacity should throw a CapacityExceededException!", false);
} catch (CapacityExceededException e) {
}
}
@Test
public void rucksackRemoveObjectContains() {
int weight1 = 5;
int value1 = 4;
int weight2 = 15;
int value2 = 14;
int capacity = 20;
PackingObject obj1 = new PackingObject(value1, weight1);
PackingObject obj2 = new PackingObject(value2, weight2);
Rucksack rucksack = new Rucksack(capacity);
rucksack.putObject(obj1);
rucksack.putObject(obj2);
rucksack.removeObject(obj2);
assertEquals(value1, rucksack.getTotalValue());
assertFalse(rucksack.contains(obj2));
try {
rucksack.removeObject(obj2);
assertTrue("Removing object not present should throw ObjectNotPresentException!", false);
} catch (ObjectNotPresentException e) {
}
}
@Test
public void rucksackCopyFrom() {
int capacity1 = 20;
PackingObject obj1 = new PackingObject(1,1);
PackingObject obj2 = new PackingObject(2,2);
Rucksack rucksack1 = new Rucksack(capacity1);
Rucksack rucksack2 = new Rucksack(5);
rucksack1.putObject(obj1);
rucksack2.copyFrom(rucksack1);
assertEquals(capacity1, rucksack2.getTotalCapacity());
assertTrue(rucksack2.contains(obj1));
rucksack1.removeObject(obj1);
assertFalse(rucksack1.contains(obj1));
assertTrue(rucksack2.contains(obj1));
rucksack2.putObject(obj2);
assertFalse(rucksack1.contains(obj2));
assertTrue(rucksack2.contains(obj2));
}
///////////////////////////////////////////////////////////////
// Tests for RucksackProblem
private int calculateValue(RucksackProblem problem, Rucksack rucksack) {
int result = 0;
for (PackingObject object : problem.getAllObjects()) {
if (rucksack.contains(object)) {
result += object.getValue();
}
}
return result;
}
private int calculateWeight(RucksackProblem problem, Rucksack rucksack) {
int result = 0;
for (PackingObject object : problem.getAllObjects()) {
if (rucksack.contains(object)) {
result += object.getWeight();
}
}
return result;
}
private PackingObject[] createPackingObjects(int[] values, int[] weights) {
PackingObject[] objects = new PackingObject[weights.length];
for (int i=0; i<weights.length; i++) {
objects[i] = new PackingObject(values[i], weights[i]);
}
return objects;
}
private RucksackProblem createProblemInstance(int[] values, int[] weights, int capacity) {
PackingObject[] objects = createPackingObjects(values, weights);
Rucksack rucksack = new Rucksack(capacity);
return new RucksackProblem(objects, rucksack);
}
private void solve(RucksackProblem problem, boolean iterative) {
if (iterative) {
problem.solveIterative();
} else {
problem.solveRecursive();
}
}
@Test
public void constructorNegativeValues(){
int[] values = {7,-5,4};
int[] weights = {5, 4,4};
int capacity = 8;
try {
createProblemInstance(values, weights, capacity);
assertTrue("IllegalArgumentException expected on negative input!", false);
} catch (IllegalArgumentException e) {
}
}
@Test
public void constructorNegativeWeights(){
int[] values = {7, 5,4};
int[] weights = {5,-4,4};
int capacity = 8;
try {
createProblemInstance(values, weights, capacity);
assertTrue("IllegalArgumentException expected on negative input!", false);
} catch (IllegalArgumentException e) {
}
}
@Test
public void solveIterativeAllObjectsPacked() {
solveAllObjectsPacked(true);
}
@Test
public void solveIterativeEmptyProblem() {
solveEmptyProblem(true);
}
@Test
public void solveIterativeOneObjectPacked() {
solveOneObjectPacked(true);
}
@Test
public void solveIterativeRucksack1() {
solveRucksack1(true);
}
@Test
public void solveIterativeRucksack2() {
solveRucksack2(true);
}
@Test
public void solveRecursiveAllObjectsPacked() {
solveAllObjectsPacked(false);
}
@Test
public void solveRecursiveEmptyProblem() {
solveEmptyProblem(false);
}
@Test
public void solveRecursiveOneObjectPacked() {
solveOneObjectPacked(false);
}
@Test
public void solveRecursiveRucksack1() {
solveRucksack1(false);
}
@Test
public void solveRecursiveRucksack2() {
solveRucksack2(false);
}
public void solveRucksack1(boolean iterative) {
int[] values = {34,11,32,100,65,33,300,55,200,37,400,32,76,50,49,19,17,28,7,4};
int[] weights = {34,11,32, 10,65,33,30, 55, 20,37, 40,32,76, 5,49,19,17,28,7,4};
int capacity = 105;
RucksackProblem problem = createProblemInstance(values, weights, capacity);
solve(problem, iterative);
Rucksack result = problem.getOptimalRucksack();
assertEquals(1050, result.getTotalValue());
assertEquals(capacity, result.getTotalWeight());
assertEquals(result.getTotalValue(), calculateValue(problem, result));
assertEquals(result.getTotalWeight(), calculateWeight(problem, result));
}
public void solveRucksack2(boolean iterative) {
int[] values = {7,5,4};
int[] weights = {5,4,4};
int capacity = 8;
RucksackProblem problem = createProblemInstance(values, weights, capacity);
solve(problem, iterative);
Rucksack result = problem.getOptimalRucksack();
assertEquals(9, result.getTotalValue());
assertEquals(8, result.getTotalWeight());
assertEquals(result.getTotalValue(), calculateValue(problem, result));
assertEquals(result.getTotalWeight(), calculateWeight(problem, result));
}
public void solveEmptyProblem(boolean iterative) {
int[] values = {};
int[] weights = {};
int capacity = 1;
RucksackProblem problem = createProblemInstance(values, weights, capacity);
solve(problem, iterative);
Rucksack result = problem.getOptimalRucksack();
assertEquals(0, result.getTotalValue());
assertEquals(0, result.getTotalWeight());
}
public void solveAllObjectsPacked(boolean iterative) {
int[] values = { 6, 5, 4, 3, 2, 1, 7, 8, 9,10};
int[] weights = { 1,10, 2, 9, 3, 8, 4, 7, 5, 6};
int capacity = 1+2+3+4+5+6+7+8+9+10;
RucksackProblem problem = createProblemInstance(values, weights, capacity);
solve(problem, iterative);
Rucksack result = problem.getOptimalRucksack();
assertEquals(capacity, result.getTotalValue());
assertEquals(capacity, result.getTotalWeight());
for (PackingObject o : problem.getAllObjects()) {
assertTrue(result.contains(o));
}
assertEquals(result.getTotalValue(), calculateValue(problem, result));
assertEquals(result.getTotalWeight(), calculateWeight(problem, result));
}
public void solveOneObjectPacked(boolean iterative) {
int[] values = { 1, 1, 1, 100, 1, 1, 1, 1, 1, 1 };
int[] weights = { 1, 1, 1, 10, 1, 1, 1, 1, 1, 1 };
int capacity = 10;
RucksackProblem problem = createProblemInstance(values, weights, capacity);
solve(problem, iterative);
Rucksack result = problem.getOptimalRucksack();
assertEquals(100, result.getTotalValue());
assertEquals(10, result.getTotalWeight());
for (PackingObject object : problem.getAllObjects()) {
if (object.getIndex() == 3) {
assertTrue(result.contains(object));
} else {
assertFalse(result.contains(object));
}
}
assertEquals(result.getTotalValue(), calculateValue(problem, result));
assertEquals(result.getTotalWeight(), calculateWeight(problem, result));
}
}

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/JTGraph"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>P2</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,12 @@
#Tue May 25 15:12:57 CEST 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,171 @@
import java.io.IOException;
/***********************************************************************************
* Task / Aufgabe
***********************************************************************************
* * Implement the A* algorithm to solve the puzzle problem known from
* the exercises. Use the following heuristic to calculate the distance:
*
* - The distance from start is the number of steps needed to reach the current
* state, e.g., the direct neighbour state has distance 1 and so on.
* - The distance to destination is the number of blocks on wrong positions, e.g.,
* 1 2 3 1 2 3
* 4 5 6 4 5 6
* 8 7 # 7 8 #
* (start) (destination)
* The distance from start to destination would be 2. (Note: start cannot be solved.)
* (7 and 8 are on wrong positions)
* Hints: When testing, be aware that some puzzle states cannot be solved.
* Try not to consider predecessor states, since they have already
* been processed.
*
* * Implementieren Sie den A* Algorithmus, um das in den Übungen behandelte Puzzle
* Problem zu lösen.
* Verwenden Sie folgende Heuristik für die Berechnung der Entfernungskosten:
*
* - Die Entfernung vom Startknoten ist die Anzahl der benötigten Schritte
* bis zum aktuellen Zustand, z.B. der unmittelbare Nachbarzustand hat
* die Entfernung 1, usw.
* - Die Entfernung zum Zielknoten ist die Anzahl der Puzzleteile,
* die an den falschen Positionen sind, z.B.
* 1 2 3 1 2 3
* 4 5 6 4 5 6
* 8 7 # 7 8 #
* (Start) (Ziel)
* The Entfernung zwischen Start und Ziel wäre 2.(Achtung: Start ist unlösbar.)
* (7 und 8 sind an falschen Positionen)
* Hinweise: Achten Sie beim Testen, dass bestimmte Zust<EFBFBD>nde möglicherweise
* nicht lösbar sind. Versuchen Sie die Vorgängerzustände nicht zu
* betrachten, da sie ja schon bearbeitet wurden.
***********************************************************************************/
/***********************************************************************************
* Questions / Fragen
***********************************************************************************
*
* ----------------------------------------------------------------
* a) Choose and implement another two heuristics to calculate the distance,
* e.g., one could use the heuristic introduced in the exercises or similar
* versions of it.
* Use TPTP to profile Puzzle.main() with all three heuristics.
* i) Which heuristic did you choose? Why? Discuss them.
* Which heuristic was the best?
* ii) What was the largest puzzle (NxN) used?
*
* Enter at least 5 different, meaningful runs in the table below.
*
* a) W<EFBFBD>hlen und implementieren Sie zwei zus<EFBFBD>tzliche Heuristiken f<EFBFBD>r die
* Berechnung der Enfernungskosten. Sie k<EFBFBD>nnen z.B. die in der <EFBFBD>bung
* vorgestellte Heuristik verwenden, oder <EFBFBD>hnliches.
* Verwenden Sie TPTP um Puzzle.main() zu profilen.
* i) Welche Heuristiken haben Sie gew<EFBFBD>hlt? Wieso? Diskutieren Sie sie.
* Welche Heuristik war die beste?
* ii) Welche Gr<EFBFBD><EFBFBD>e(NxN) hatten die verwendeten Puzzles?
*
* Tragen Sie mindestens 5 verschiedene, aussagekr<EFBFBD>ftige Resultate in der Tabelle ein.
* ----------------------------------------------------------------
*
* Heuristik 1: Anzahl der Elemente an der falschen Position
* O(n^2); n = puzzlesize
*
* Heuristik 2: Entfernung der einzelnen Elemente von ihrer Position zur
* Zielposition. Berechnet <EFBFBD>ber ganze Felder:
* x-distance + y-distance.
* Diese Werte werden f<EFBFBD>r alle Elemente in einem PuzzleMove
* aufaddiert.
* O(n^4); n = puzzlesize
*
* Heuristik 3: Entfernung der einzelnen Elemente von ihrer Position zur
* Zielposition. Berechnet <EFBFBD>ber Pythagoras:
* sqrt(x-distance^2 + y-distance^2)
* Diese Werte werden f<EFBFBD>r alle Elemente in einem PuzzleMove
* aufaddiert.
* O(n^4); n = puzzlesize
*
* Es hat sich herausgestellt, das Heuristik 2 trotz h<EFBFBD>herer Komplexit<EFBFBD>t
* im Vergleich zu Heuristik 1 deutlich besser ist, da die Absch<EFBFBD>tzung
* genauer ist. Dadurch m<EFBFBD>ssen weniger Schritte genommen werden um die L<EFBFBD>sung
* zu finden.
*
* Heuristik 1 ist am ungenausten, ben<EFBFBD>tigt deshalb deutlich mehr Schritte als
* Heuristik 2 & 3. Sie ist allerdings trozdem schneller als Heuristik3, da
* die Komplexit<EFBFBD>t von Heuristik1 wesentlich besser ist als die von heuristik3
* O(n^2) -> O(n^4)
*
* Heuristik 3 ist genauer als Heuristik 1 aber ungenauer als Heuristik 2. Dies
* resultiert aus der Diagonalen-Sch<EFBFBD>tzung, welche nicht den Spielz<EFBFBD>gen entspricht,
* sondern eine rein mathematische Anschauung ist.
* Heuristik 3 hat sich am Zeitintensivsten erwiesen. O(n^4)
*
* Im ganzen ist Heuristik2 f<EFBFBD>r die von uns getesten F<EFBFBD>lle die beste Wahl,
* da hier in k<EFBFBD>rzester Zeit und mit am wenigsten Schritten das Ergebnis gefunden
* wird trotz schlechterer Komplexit<EFBFBD>t O(n^4).
* Bei kleinen oder einfachen Puzzels zeigt sich allerdings kaum ein Unterschied.
* Heuristik2 ist die genauste Sch<EFBFBD>tzung (abzulesen an den genommen Schritten).
*
*
* | heuristic 1 | heuristic 2 | heuristic 3
* -------------+-------+-----------+-------+-----------+-------+--------
* NxN puzzle | ms | steps | ms | steps | ms | steps
* -------------+-------+-----------+-------+-----------+-------+--------
* 3x3 test_00 | 15303 8717 | 2246 1474 | 26096 3972 (Vorlage test_0.txt)
* 3x3 test_02 | 15383 8717 | 2165 1474 | 26022 3972 (Haus<EFBFBD>bung)
* 3x3 test_03 | 2 5 | 3 5 | 2 5
* 4x4 test_04 | 28 143 | 49 102 | 201 134
* 4x4 test_05 | 2 3 | 3 3 | 2 3
*
* ms - time needed to find the solution
* steps - steps needed to reach the destination
***********************************************************************************/
/**
* The class from where the puzzle is loaded and prepared for processing
*/
public class Puzzle extends PuzzleAStar
{
/**
* Initialise the puzzle states (Start and Destination)
*
* @param start
* @param destination
*/
public Puzzle (PuzzleMove start, PuzzleMove destination)
{
setStartState(start);
setDestinationState(destination);
}
/**
* The main method
*
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException
{
// Read the PuzzleInput
PuzzleInputOutput pio = new PuzzleInputOutput("test_05.txt");
//Create and initialize the Puzzle
Puzzle puzzle = new Puzzle( new PuzzleMove(pio.getPuzzleStart() ,PuzzleMove.HEURISTIC_C),
new PuzzleMove(pio.getPuzzleDestination() ,PuzzleMove.HEURISTIC_C));
puzzle.init();
//Calculate A*
puzzle.findDestination();
//Print Summary
System.out.println("Summary:");
System.out.println("\nHeuristic used: "+puzzle.getDestinationState().getHeuristic());
System.out.println("\nStartState: ");
PuzzleInputOutput.printPuzzle(puzzle.getStartState().getState());
System.out.println("FinalState: ");
PuzzleInputOutput.printPuzzle(puzzle.getDestinationState().getState());
puzzle.printSolutionSummary(puzzle.getCurrentState());
//Uncomment if you want to see the Path from start to solution if there is one
//puzzle.printPathToSolution(puzzle.getGraph());
}
}

View File

@ -0,0 +1,243 @@
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.jgrapht.DirectedGraph;
import org.jgrapht.graph.SimpleDirectedWeightedGraph;
/**
* This class represents the implementation of the A* algorithm
*/
public abstract class PuzzleAStar {
private DirectedGraph<PuzzleMove, Integer> graph; // vertex: PuzzleMove
// edge: Integer (use an int value as a unique ID)
private PuzzleMove startState; // the start state of the puzzle
private PuzzleMove destinationState; // the destination state of the puzzle
private PuzzleMove currentState; // the current explored puzzle state
private List<PuzzleMove> movesToProcess; // the number of moves not taken yet
private long startPuzzleTime; // Timing variables
private long endPuzzleTime;
/**
* Initializes PuzzleAStar
*/
void init() {
//Create ArrayList for moves
movesToProcess = new ArrayList<PuzzleMove>();
//Create graph
graph = new SimpleDirectedWeightedGraph<PuzzleMove, Integer>(Integer.class);
//Set currentState to startState
this.currentState = startState;
//Add StartState to graph
graph.addVertex(startState);
}
/**
* This method implements the A* algorithm for the puzzle
*/
public void findDestination() {
//check input data
if(currentState == null){
return;
}
//save the start time
startPuzzleTime = System.currentTimeMillis();
//integer identification for edges
int edgecount = 0;
//Add all possible Moves of startState to movesToProcess
movesToProcess.addAll(currentState.successorMoves());
//Do as long destination is not reached
while(!currentState.equals(destinationState))
{
PuzzleMove nextstep = null;
for(int i=0; i< movesToProcess.size(); i++)
{
//calculate distance of Move - need to be done here cuz PuzzleMove has no
//access to destinationState
movesToProcess.get(i).calculateDistance(this.destinationState);
//identify best move in movesToProcess
if(nextstep == null)
{
//no move found till now
nextstep = movesToProcess.get(i);
} else
{
//is move better then last identified?
if(nextstep.getCost() > movesToProcess.get(i).getCost())
{
nextstep = movesToProcess.get(i);
}
}
}
//movesToProcess is empty. There is no connection from start to destination
if(nextstep == null)
{
//no way found
break;
}
//try to add identified step. If not possible it is already in the graph
if(graph.addVertex(nextstep))
{
//Add an edge from identified step's predecessor to identified step
graph.addEdge(nextstep.getPredecessorMove(), nextstep,edgecount++);
//now continue with identified step
currentState = nextstep;
//add all successorMoves to movesToProcess
movesToProcess.addAll(currentState.successorMoves());
}
//remove the identified step from movesToProcess
movesToProcess.remove(nextstep);
}
//save end time
endPuzzleTime = System.currentTimeMillis();
}
/**
* This method prints a summary of the solution
*
* @param state The final puzzle state (Destination)
*/
public void printSolutionSummary(PuzzleMove state) {
System.out.println("Time needed to find Destination (ms): " + (this.endPuzzleTime-this.startPuzzleTime));
System.out.println("Current cost at final state (Destination): " + state.getCost());
System.out.println("States processed so far: " + numberOfProcessedStates());
System.out.println("States identified for processing (not being processed): " + numberOfStatesToProcess());
}
/**
* This method prints the path to the solution
*
* Make sure you called findDestination() first.
* This method only works if the A* Algorithm was
* calculated before.
*
* Uses currentState & destinationState
*
* @param graph
*/
public void printPathToSolution(DirectedGraph<PuzzleMove, Integer> graph) {
System.out.println("\nThe steps/path needed to reach the destination:\n");
//Check if A* was successful
if(!currentState.equals(destinationState)){
System.out.println("No Path to Solution found");
return;
}
//Add String representation of destinationState
String result = currentState.toString();
PuzzleMove curMove = destinationState;
//Move from destination to start
while(!curMove.equals(startState))
{
//get incoming edges
Set<Integer> s = graph.incomingEdgesOf(curMove);
//No or more then one edge found - something is wrong
if(s.size() != 1)
{
System.out.println("An Error occured: Graph destination has no or to many connections to start");
return;
}
//only look at first edge
Iterator<Integer> it = s.iterator();
curMove = graph.getEdgeSource(it.next());
//Add String representation before last steps
result = curMove.toString() + result;
}
//print the result
System.out.println(result);
}
/**
* The number of states identified for processing but not processed yet
* @return the number of moves not taken yet
*/
int numberOfStatesToProcess() {
return this.movesToProcess.size();
}
/**
* The number of states/puzzle moves processed so far
* @return the number of edges
*/
int numberOfProcessedStates() {
return this.graph.vertexSet().size();
}
/**
* @return the graph
*/
public DirectedGraph<PuzzleMove, Integer> getGraph() {
return this.graph;
}
/**
* @return the currentState
*/
public PuzzleMove getCurrentState() {
return this.currentState;
}
/**
* @param destinationState the destinationState to set
*/
public void setDestinationState(PuzzleMove destinationState) {
this.destinationState = destinationState;
}
/**
* @param startState the startState to set
*/
public void setStartState(PuzzleMove startState) {
this.startState = startState;
}
/**
* @return the startState
*/
public PuzzleMove getStartState() {
return this.startState;
}
/**
* @return the destinationState
*/
public PuzzleMove getDestinationState() {
return this.destinationState;
}
/**
* @return the movesToProcess
*/
public List<PuzzleMove> getMovesToProcess() {
return this.movesToProcess;
}
}

View File

@ -0,0 +1,16 @@
/**
* PuzzleFileFormatException
*/
public class PuzzleFileFormatException extends RuntimeException
{
private static final long serialVersionUID = 1L;
/**
* PuzzleFileFormatException
* @param s the message
*/
public PuzzleFileFormatException(String s) {
super(s);
}
}

View File

@ -0,0 +1,212 @@
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.StringTokenizer;
/**
* Methods needed to read and write the puzzle
*/
public class PuzzleInputOutput
{
private static String[][] puzzleStart;
private static String[][] puzzleDestination;
public final static int PARSERSTATE_LVLSIZE = 0;
public final static int PARSERSTATE_STARTCONFIG = 1;
public final static int PARSERSTATE_FINALCONFIG = 2;
public final static int PARSERSTATE_PARSINGEND = 3;
public final static String FORMAT_CONFIGSEPERATOR = "---";
public final static String FORMAT_FREEFIELD = "#";
/**
* This method reads the data from the file and
* initialises the Start and Destination states of the Puzzle
*
* @param puzzleFile
* @throws IOException
*/
public PuzzleInputOutput(String puzzleFile) throws IOException
{
//open file
BufferedReader reader = new BufferedReader(new FileReader(puzzleFile));
//var to store a line temporary
String line;
//var to store size of puzzle temporary
int size = 0;
//state of the parsing
int state = PARSERSTATE_LVLSIZE;
//state of the configuration parsing
int config_state = 0;
//state which indicates if free field was seen in actual configuration
boolean free_field = false;
//do we need a linebreak?
boolean linebreak = true;
//last row in array to force a linebreak
int last_line = 0;
//read until fileend
while((line = reader.readLine()) != null)
{
//check if an linebreak was expected
if(!linebreak)
{
throw new PuzzleFileFormatException("Unexpected Linebreak in Puzzlefile");
}
linebreak = false;
//tokenize the input string
StringTokenizer st = new StringTokenizer(line);
while(st.hasMoreTokens())
{
//linbreak not found
if(linebreak)
{
throw new PuzzleFileFormatException("Expected Linebreak in Puzzlefile, but could not find it");
}
switch(state)
{
//parse levelsize
case PARSERSTATE_LVLSIZE:
{
//read size
try
{
size = Integer.valueOf(st.nextToken());
} catch(NumberFormatException e)
{
throw new PuzzleFileFormatException("Levelsizetoken was not a number");
}
//create arrays
puzzleStart = new String[size][size];
puzzleDestination = new String[size][size];
//change state of parser
state = PARSERSTATE_STARTCONFIG;
//expect linebreak
linebreak = true;
break;
}
//parse configurations
case PARSERSTATE_STARTCONFIG:
case PARSERSTATE_FINALCONFIG:
{
// still reading config?
if(config_state < size*size)
{
String token = st.nextToken();
//save last linenumber
last_line = config_state/size;
//fill in token
if(state == PARSERSTATE_STARTCONFIG){
puzzleStart[config_state/size][config_state%size] = token;
} else {
puzzleDestination[config_state/size][config_state%size] = token;
}
//free field?
if(token.equals(FORMAT_FREEFIELD))
{
//more than one free field
if(free_field) {
throw new PuzzleFileFormatException("Puzzle file contained more then one free Field in one Configuration");
}
free_field = true;
}
//next part in array
config_state++;
//last line
if(config_state/size == size)
{
//No free field?
if(!free_field) {
throw new PuzzleFileFormatException("Puzzle file contained no free Field in one Configuration");
}
}
//do we need a linebreak here?
if(last_line != config_state/size)
{
linebreak = true;
}
} else
{
//PuzzleFile Seperator
if(state == PARSERSTATE_STARTCONFIG && !st.nextToken().equals(FORMAT_CONFIGSEPERATOR)){
throw new PuzzleFileFormatException("Puzzle file ConfigurationSeperator was not found");
}
//reset vars
free_field = false;
config_state = 0;
//parse finalconfig after startconfig
if(state == PARSERSTATE_STARTCONFIG){
state = PARSERSTATE_FINALCONFIG;
linebreak = true;
} else {
//No more characters or linebreaks expected!
state = PARSERSTATE_PARSINGEND;
}
}
break;
}
default:
throw new PuzzleFileFormatException("Puzzle file contains more lines after finalconfiguration");
}
}
}
}
/**
* It prints the given puzzle state
*
* @param puzzle the puzzle
*/
public static void printPuzzle(String[][] puzzle)
{
if(puzzle == null)
{
System.out.println("Puzzle given was null");
}
String output = new String();
for(int i=0; i < puzzle.length; i++)
{
for(int j=0; j < puzzle[i].length; j++)
{
output += puzzle[i][j] + "\t";
}
output += "\n";
}
System.out.println(output);
}
/**
* @return the puzzleStart
*/
public String[][] getPuzzleStart() {
return puzzleStart;
}
/**
* @return the puzzleDestination
*/
public String[][] getPuzzleDestination() {
return puzzleDestination;
}
}

View File

@ -0,0 +1,622 @@
import java.awt.Point;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* This class defines a puzzle move
*/
public class PuzzleMove implements Cloneable
{
//---STATICS-------------------------------------------
//Heuristic Definitions
public final static int HEURISTIC_A = 0;
public final static int HEURISTIC_B = 1;
public final static int HEURISTIC_C = 2;
//---VARIABLES-----------------------------------------
/**
* distance from start; default 0
*/
private int ds = 0;
/**
* distance to destination; default 0
*/
private int dd = 0;
/**
* the distance cost (cost = ds + dd); default 0
*/
private int cost = 0;
/**
* Used Heuristic; Default: HEURISTIC_A
*
* Valid values: 0-2
*/
private int heuristic = HEURISTIC_A;
/**
* the state of the current puzzle move/state
*/
private String[][] state;
/**
* Predecessor of this Move
*
* Is null if predecessor does not exist or is unknown
*/
private PuzzleMove predecessorMove = null;
//---METHODS-------------------------------------------
/**
* Standard Constructor
*
* to make the PuzzleMove valid use
* setState();
*
* optional:
* setHeuristic() - default HEURISTIC_A
* setDd() - default 0
* setDs() - default 0
*/
public PuzzleMove(){}
/**
* Constructor
*
* @param state PuzzleState
* @param heuristic Used heuristic
*/
public PuzzleMove(String[][] state, int heuristic)
{
this.setState(state);
this.setHeuristic(heuristic);
}
/**
* Constructor
*
* @param state PuzzleState
* @param heuristic Used Heuristic
* @param dd Distance to Destination
* @param ds Distance to Start
*/
public PuzzleMove(String[][] state, int heuristic, int dd, int ds) {
this.setState(state);
this.setHeuristic(heuristic);
this.setDd(dd);
this.setDs(ds);
}
/**
* Find Element Position in given state which has given value
*
* @param value String
* @param state String[][]
* @return null if not found else returns a Point
*/
private Point findElementPos(String value, String[][] state)
{
//Iterate over array
for(int i=0; i<state.length;i++)
{
for(int j=0; j<state[i].length;j++)
{
//Check if state[i][j] is searchelement
if(state[i][j].equals(value))
{
return new Point(i,j);
}
}
}
//String not found in array
return null;
}
/**
* Find Element Position in this.state which has given value
*
* @param value String
* @return null if not found else returns a Point
*/
private Point findElementPos(String value)
{
return findElementPos(value,state);
}
/**
* Exchanges the Fields of given state at point a and b
* @param state String[][]
* @param a Point
* @param b Point
* @return modified state
*/
private String[][] exchangeFields(String[][] state, Point a, Point b)
{
//save value of state at point a
String temp = state[a.x][a.y];
//set value of state at point a to value of point b
state[a.x][a.y] = state[b.x][b.y];
//set value of state at point b to saved value of point a
state[b.x][b.y] = temp;
//return modified state
return state;
}
/**
* Exchanges the Fields at point a and b of current State
*
* @param a Point
* @param b Point
* @return modified State
*/
private String[][] exchangeFields(Point a, Point b)
{
return exchangeFields(this.state, a, b);
}
/**
* Calculates on Successor according to the given x/y_mods
*
* @param free_field Free field in this.state arrays
* @param x_mod Integer defining the movement of the free_field on x-Achsis
* @param y_mod Integer defining the movement of the free_field on y-Achsis
* @return null if parameters where invalid or x/y-mod would cause ArrayOutOfBounds
* or new PuzzleMove if successfull
*/
private PuzzleMove successorMove(Point free_field, int x_mod, int y_mod)
{
//Check if free_field is valid
if( free_field == null ||
free_field.x < 0 ||
free_field.x >= this.state.length ||
free_field.y < 0 ||
free_field.y >= this.state.length ){
return null;
}
//create a new Point according to modificators
Point b = new Point(free_field.x + x_mod, free_field.y + y_mod);
//check new point
if( b.x < 0 ||
b.x >= this.state.length ||
b.y < 0 ||
b.y >= this.state.length )
{
return null;
}
//clone this PuzzleMove
PuzzleMove result = this.clone();
//Exchange the free_field and the Modification-Point
result.exchangeFields(free_field, b);
//Increase Ds
result.setDs(this.getDs()+1);
//Set Predecessor
result.setPredecessorMove(this);
//Return new PuzzleMove
return result;
}
/**
* Calculates the possible successor moves/states
* @return a list with the successor moves/states
*/
public List<PuzzleMove> successorMoves() {
//Create Result List
List<PuzzleMove> result = new ArrayList<PuzzleMove>();
//Find the free Field in state
Point free_field = findElementPos(PuzzleInputOutput.FORMAT_FREEFIELD);
//Temporary Variable for new Moves
PuzzleMove newMove;
//top-Move
newMove = successorMove(free_field,-1,0);
if(newMove != null)
{
result.add(newMove);
}
//bottom-Move
newMove = successorMove(free_field,+1,0);
if(newMove != null)
{
result.add(newMove);
}
//left-Move
newMove = successorMove(free_field,0,-1);
if(newMove != null)
{
result.add(newMove);
}
//right-Move
newMove = successorMove(free_field,0,+1);
if(newMove != null)
{
result.add(newMove);
}
return result;
}
/**
* Calculates the distance to the destination p (according to the currently chosen heuristic)
* @param p the destination state
* @return the distance of the current state to destination
*/
public int calculateDistance(PuzzleMove p) {
//Simple switch and link to methodOne-Three
switch(this.heuristic)
{
case HEURISTIC_A:
return methodOne(p);
case HEURISTIC_B:
return methodTwo(p);
case HEURISTIC_C:
return methodThree(p);
default:
return -1;
}
}
/**
* Heuristic 0
*
* How many Elements are not in the right place
*
* @param p the puzzle state
* @return the destination cost according to this heuristic
*/
private int methodOne(PuzzleMove p) {
//Check if p is valid
if( p == null){
return -1;
}
int dist = 0;
//Iterate over state
for(int i=0; i<this.state.length; i++)
{
for(int j=0; j<this.state[i].length; j++)
{
//Check if Element is in right place, if not increase dist-counter
if(!this.state[i][j].equals(p.getState()[i][j]))
{
dist++;
}
}
}
//Set new calculated dd value
setDd(dist);
return dist;
}
/**
* Heuristic 1
*
* Calculate the distance between Elements in state
* and its target-destination and summ it up
*
* @param p the puzzle state
* @return the destination cost according to this heuristic
*/
private int methodTwo(PuzzleMove p) {
//Check if p is valid
if( p == null){
return -1;
}
int dist = 0;
//Iterate over state
for(int i=0; i<this.state.length; i++)
{
for(int j=0; j<this.state[i].length; j++)
{
//Find Element of state in destination-state (O(n^2))
Point point = findElementPos(this.state[i][j],p.getState());
//Element not found
if(point == null){
return -1;
}
//Calculate the distance between Element and its destination
dist += Math.abs(point.x-i) + Math.abs(point.y-j);
}
}
//Set new calculated dd value
setDd(dist);
return dist;
}
/**
* Heuristic 2
*
* @param p the puzzle state
* @return the destination cost according to this heuristic
*/
private int methodThree(PuzzleMove p) {
//Check if p is valid
if( p == null){
return -1;
}
int dist = 0;
//Iterate over state
for(int i=0; i<this.state.length; i++)
{
for(int j=0; j<this.state[i].length; j++)
{
//Find Element of state in destination-state (O(n^2))
Point point = findElementPos(this.state[i][j],p.getState());
//Element not found
if(point == null){
return -1;
}
//Calculate the distance between Element and its destination (diagonally using sqrt)
dist += Math.sqrt(Math.pow(Math.abs(point.x-i),2) + Math.pow(Math.abs(point.y-j),2));
}
}
//Set new calculated dd value
setDd(dist);
return dist;
}
/**
* HashCode to make equals work.
*
* Only uses state to calculate hashcode
*/
@Override public int hashCode() {
int hashcode = 0;
for(int i= 0; i < state.length; i++){
hashcode += Arrays.hashCode(state[i]);
}
return hashcode;
}
/**
* Checks if two puzzle moves are equal
* @param obj to be compared
*
* Checks only state -> does not compare
* -heuristic
* -dd
* -ds
*/
@Override public boolean equals(Object obj)
{
//Checks if obj is a PuzzleMove
if(!(obj instanceof PuzzleMove)){
return false; //return false - its not a puzzlemove
}
//cast to Puzzlemove
PuzzleMove p = (PuzzleMove)obj;
//Check state-length
if( p.getState().length != this.state.length){
return false;
}
//iterate over array
for(int i=0; i<this.state.length;i++)
{
//Check subarray-length of state
if(p.getState()[i].length != this.state[i].length){
return false;
}
for(int j=0; j<this.state[i].length;j++)
{
//Check if state elements are equal
if(!p.getState()[i][j].equals(this.state[i][j])){
return false;
}
}
}
//All Checks done return true
return true;
}
/**
* @return Returns a String-Representation of the PuzzleMove
*/
@Override public String toString()
{
String result = "Step: " + ds +
": cost = " + cost +
", ds = " + ds +
", dd = " + dd +
"\n--------------------------------\n";
for(int i=0;i<state.length; i++){
for(int j=0;j<state[i].length; j++){
result += state[i][j] + "\t";
}
result += "\n";
}
return result;
}
/**
* Clone this PuzleMove
*
* clones
* -state
* -heuristic
* -dd
* -ds
*/
@Override public PuzzleMove clone()
{
//new array
String[][] aarrayclone = new String[this.state.length][this.state.length];
//clone every subarray
for(int i=0; i<aarrayclone.length;i++)
{
System.arraycopy(this.state[i],0,aarrayclone[i],0,aarrayclone.length);
}
//create a new puzzle, set array, heuristic, dd, ds
PuzzleMove aclone = new PuzzleMove(aarrayclone,getHeuristic(),dd,ds);
//return the cloned element
return aclone;
}
/**
* @param state the state to set
*/
public void setState(String[][] state) {
this.state = state;
}
/**
* @return the state
*/
public String[][] getState() {
return state;
}
/**
* Sets the Heuristic used
*
* @param heuristic HEURISTIC_A/B/C
* @return true if heuristic value was valid
*/
public boolean setHeuristic(int heuristic) {
if( heuristic >= HEURISTIC_A &&
heuristic <= HEURISTIC_C)
{
this.heuristic = heuristic;
return true;
}
return false;
}
/**
* Returns the Heuristic used
*
* @return integer between 0-2
*/
public int getHeuristic() {
return heuristic;
}
/**
* Returns the calculated Costs for this Move
*
* @return calculated Costs
*/
public int getCost() {
return cost;
}
/**
* Calculate new Costs, save them to cost
* @return new costs
*/
private int calculateCosts()
{
return (cost = ds + dd);
}
/**
* @return Distance to Start
*/
public int getDs() {
return ds;
}
/**
* Sets Distance to Start and Calculates new Costs
*
* @param ds
*/
public void setDs(int ds) {
this.ds = ds;
calculateCosts();
}
/**
* @return Distance to Destination
*/
public int getDd() {
return dd;
}
/**
* Sets Distance to Destination and Calculates new Costs
*
* @param dd
*/
public void setDd(int dd) {
this.dd = dd;
calculateCosts();
}
/**
* Sets PredecessorMove
* @param predecessorMove PuzzleMove
*/
public void setPredecessorMove(PuzzleMove predecessorMove) {
this.predecessorMove = predecessorMove;
}
/**
* @return PredecessorMove; can be null
*/
public PuzzleMove getPredecessorMove() {
return predecessorMove;
}
}

View File

@ -0,0 +1,8 @@
3
# 1 2
3 4 5
6 7 8
---
1 2 3
4 5 6
7 8 #

View File

@ -0,0 +1,8 @@
3
# 1 2
3 4 5
6 7 8
---
# 1 2
3 4 5
6 7 8

View File

@ -0,0 +1,8 @@
3
# 1 2
3 4 5
6 7 8
---
1 2 3
4 5 6
7 8 #

View File

@ -0,0 +1,8 @@
3
# 1 2
3 4 5
6 7 8
---
1 2 5
3 4 8
6 7 #

View File

@ -0,0 +1,10 @@
4
# 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
---
6 1 2 3
4 5 # 7
8 9 10 11
12 13 14 15

View File

@ -0,0 +1,10 @@
4
# 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
---
1 5 2 3
4 # 6 7
8 9 10 11
12 13 14 15

View File

@ -0,0 +1,8 @@
4
1 2 3
4 5 6
7 8 #
---
1 2 3
4 5 6
7 8 #

View File

@ -0,0 +1,8 @@
3
1 2 3 4
4 5 6 4
7 8 # 4
---
1 2 3
4 5 6
7 8 #

View File

@ -0,0 +1,9 @@
3
1 2 3
4 5 6
7 8 #
i o l
---
1 2 3
4 5 6
7 8 #

View File

@ -0,0 +1,8 @@
3
1 2 3
4 5 6
7 8 #
--
1 2 3
4 5 6
7 8 #

View File

@ -0,0 +1,8 @@
3
1 2 3
4 5 6
7 8 #
---
1 2 3 4
4 5 6
7 8 #

View File

@ -0,0 +1,8 @@
3
0 1 2
3 4 5
6 7 8
---
0 1 2
3 4 5
6 7 8

View File

@ -0,0 +1,6 @@
2
# 1
2 3
---
# 1
2 4

View File

@ -0,0 +1,74 @@
/**
* Test cases
*/
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import org.jgrapht.DirectedGraph;
import org.junit.Test;
public class PuzzleTest
{
@Test(expected=PuzzleFileFormatException.class)
public void readTest1() throws IOException
{
new PuzzleInputOutput("test_1.txt");
}
@Test(expected=PuzzleFileFormatException.class)
public void readTest2() throws IOException
{
new PuzzleInputOutput("test_2.txt");
}
@Test(expected=PuzzleFileFormatException.class)
public void readTest3() throws IOException
{
new PuzzleInputOutput("test_3.txt");
}
@Test(expected=PuzzleFileFormatException.class)
public void readTest4() throws IOException
{
new PuzzleInputOutput("test_4.txt");
}
@Test(expected=PuzzleFileFormatException.class)
public void readTest5() throws IOException
{
new PuzzleInputOutput("test_5.txt");
}
@Test
public void testEquals() throws IOException
{
PuzzleInputOutput pio = new PuzzleInputOutput("test_00.txt");
PuzzleMove start = new PuzzleMove();
PuzzleMove end = new PuzzleMove();
start.setState(pio.getPuzzleStart());
end.setState(pio.getPuzzleDestination());
Puzzle p = new Puzzle(start, end);
p.init();
p.findDestination();
assertEquals(p.getCurrentState(), end); // current state should be the destination
assertFalse("Equals is not properly implemented.", start.equals(end));
end = start;
assertTrue("Equals is not properly implemented", start.equals(end));
}
@Test
public void testEqualityCheck() throws IOException
{
PuzzleInputOutput pio = new PuzzleInputOutput("test_01.txt");
PuzzleMove start = new PuzzleMove();
PuzzleMove end = new PuzzleMove();
start.setState(pio.getPuzzleStart());
end.setState(pio.getPuzzleDestination());
Puzzle p = new Puzzle(start, end);
p.init();
p.findDestination();
DirectedGraph<PuzzleMove, Integer> g = p.getGraph();
// If start and destination are the same...
assertFalse(p.numberOfProcessedStates() > 1); //...no need to process more than one state
assertFalse(g.vertexSet().size() > 1); //...the graph should have only one node
}
}

Binary file not shown.

View File

@ -0,0 +1,25 @@
/*
* File: Add2Application.java
* --------------------------
* This program adds two numbers and prints their sum. This version
* runs as a Java application without using the acm.program package.
*/
import acm.io.*;
import java.awt.*;
import javax.swing.*;
public class Add2Application {
public static void main(String[] argv) {
JFrame frame = new JFrame("Add2Application");
IOConsole console = new IOConsole();
frame.getContentPane().add(BorderLayout.CENTER, console);
frame.setSize(500, 300);
frame.show();
console.println("This program adds two numbers.");
int n1 = console.readInt("Enter n1: ");
int n2 = console.readInt("Enter n2: ");
int total = n1 + n2;
console.println("The total is " + total + ".");
}
}

View File

@ -0,0 +1,26 @@
/*
* File: Add2Console.java
* ----------------------
* This program adds two numbers and prints their sum. Because
* this version is a ConsoleProgram, the input and output appear
* on the console.
*/
import acm.program.*;
public class Add2Console extends ConsoleProgram {
public void run() {
println("This program adds two numbers.");
int n1 = readInt("Enter n1: ");
int n2 = readInt("Enter n2: ");
int total = n1 + n2;
println("The total is " + total + ".");
}
/* Standard Java entry point */
/* This method can be eliminated in most Java environments */
public static void main(String[] args) {
new Add2Console().start(args);
}
}

View File

@ -0,0 +1,26 @@
/*
* File: Add2Dialog.java
* ---------------------
* This program adds two numbers and prints their sum. Because
* this version is a DialogProgram, the input and output appear
* as popup dialogs.
*/
import acm.program.*;
public class Add2Dialog extends DialogProgram {
public void run() {
println("This program adds two numbers.");
int n1 = readInt("Enter n1: ");
int n2 = readInt("Enter n2: ");
int total = n1 + n2;
println("The total is " + total + ".");
}
/* Standard Java entry point */
/* This method can be eliminated in most Java environments */
public static void main(String[] args) {
new Add2Dialog().start(args);
}
}

View File

@ -0,0 +1,26 @@
/*
* File: Add2Program.java
* ----------------------
* This program adds two numbers and prints their sum. Because
* this version is a Program, input and output are assigned to
* System.in and System.out.
*/
import acm.program.*;
public class Add2Program extends Program {
public void run() {
println("This program adds two numbers.");
int n1 = readInt("Enter n1: ");
int n2 = readInt("Enter n2: ");
int total = n1 + n2;
println("The total is " + total + ".");
}
/* Standard Java entry point */
/* This method can be eliminated in most Java environments */
public static void main(String[] args) {
new Add2Program().start(args);
}
}

View File

@ -0,0 +1,52 @@
/*
* File: BouncingBall.java
* -----------------------
* This file implements a simple bouncing ball using the run method
* to drive the animation.
*/
import acm.program.*;
public class BouncingBall extends GraphicsProgram {
/** Initialize the ball and its velocity components */
public void init() {
ball = new GBall(BALL_RADIUS);
add(ball, getWidth() / 2, getHeight() / 2);
dx = 2;
dy = 1;
}
/** Run forever bouncing the ball */
public void run() {
waitForClick();
while (true) {
advanceOneTimeStep();
pause(PAUSE_TIME);
}
}
/* Check for bounces and advance the ball */
private void advanceOneTimeStep() {
double bx = ball.getX();
double by = ball.getY();
if (bx < BALL_RADIUS || bx > getWidth() - BALL_RADIUS) dx = -dx;
if (by < BALL_RADIUS || by > getHeight() - BALL_RADIUS) dy = -dy;
ball.move(dx, dy);
}
/* Private constants */
private static final double BALL_RADIUS = 10;
private static final int PAUSE_TIME = 20;
/* Private instance variables */
private GBall ball; /* The ball object */
private double dx; /* Velocity delta in the x direction */
private double dy; /* Velocity delta in the y direction */
/* Standard Java entry point */
/* This method can be eliminated in most Java environments */
public static void main(String[] args) {
new BouncingBall().start(args);
}
}

View File

@ -0,0 +1,37 @@
/*
* File: BouncingBallUsingThreads.java
* -----------------------------------
* This file implements a simple bouncing ball by creating
* a RunnableBall class and executing it in its own thread.
*/
import acm.program.*;
public class BouncingBallUsingThreads extends GraphicsProgram {
/** Initialize the ball and its velocity components */
public void init() {
ball = new RunnableGBall(BALL_RADIUS);
ball.setEnclosureSize(getWidth(), getHeight());
ball.setVelocity(2, 1);
add(ball, getWidth() / 2, getHeight() / 2);
}
/** Create a thread to bounce the ball */
public void run() {
waitForClick();
new Thread(ball).start();
}
/* Private constants */
private static final double BALL_RADIUS = 10;
/* Private instance variables */
private RunnableGBall ball;
/* Standard Java entry point */
/* This method can be eliminated in most Java environments */
public static void main(String[] args) {
new BouncingBallUsingThreads().start(args);
}
}

View File

@ -0,0 +1,57 @@
/*
* File: BouncingBallUsingTimer.java
* ---------------------------------
* This file implements a simple bouncing ball using a Timer to
* implement the animation.
*/
import acm.program.*;
import acm.util.*;
import java.awt.event.*;
public class BouncingBallUsingTimer extends GraphicsProgram {
/** Initialize the ball and its velocity components */
public void init() {
ball = new GBall(BALL_RADIUS);
add(ball, getWidth() / 2, getHeight() / 2);
dx = 2;
dy = 1;
}
/** Create a timer to advance the ball */
public void run() {
waitForClick();
ActionListener listener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
advanceOneTimeStep();
}
};
SwingTimer timer = new SwingTimer(TIMER_RATE, listener);
timer.start();
}
/** Check for bounces and advance the ball */
private void advanceOneTimeStep() {
double bx = ball.getX();
double by = ball.getY();
if (bx < BALL_RADIUS || bx > getWidth() - BALL_RADIUS) dx = -dx;
if (by < BALL_RADIUS || by > getHeight() - BALL_RADIUS) dy = -dy;
ball.move(dx, dy);
}
/* Private constants */
private static final double BALL_RADIUS = 10;
private static final int TIMER_RATE = 20;
/* Private instance variables */
private GBall ball;
private double dx;
private double dy;
/* Standard Java entry point */
/* This method can be eliminated in most Java environments */
public static void main(String[] args) {
new BouncingBallUsingTimer().start(args);
}
}

View File

@ -0,0 +1,179 @@
/*
* File: CalendarDemo.java
* -----------------------
* This program uses the GUI layout mechanism to create a calendar
* page. The program uses the features of Java's Locale class to
* internationalize the calendar.
*/
import acm.gui.*;
import acm.program.*;
import acm.util.*;
import java.awt.*;
import java.awt.event.*;
import java.text.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;
public class CalendarDemo extends Program implements ItemListener {
/** Initialize the graphical user interface */
public void init() {
setBackground(Color.WHITE);
initCountryList();
localeChooser = new JComboBox(countries);
String country = Locale.getDefault().getDisplayCountry();
localeChooser.setSelectedItem(country);
localeChooser.addItemListener(this);
add(new JButton("<-"), NORTH);
add(localeChooser, NORTH);
add(new JButton("->"), NORTH);
currentCalendar = Calendar.getInstance();
itemStateChanged(null);
addActionListeners();
}
/** Respond to a button action */
public void actionPerformed(ActionEvent e) {
int delta = (e.getActionCommand().equals("<-")) ? -1 : +1;
currentCalendar.add(Calendar.MONTH, delta);
updateCalendarDisplay(currentCalendar);
}
/** Respond to a change in the locale selection */
public void itemStateChanged(ItemEvent e) {
if (e == null || e.getStateChange() == ItemEvent.SELECTED) {
Date time = currentCalendar.getTime();
Locale locale = LOCALES[localeChooser.getSelectedIndex()];
currentCalendar = Calendar.getInstance(locale);
currentCalendar.setTime(time);
symbols = new DateFormatSymbols(locale);
weekdayNames = symbols.getWeekdays();
monthNames = symbols.getMonths();
firstDayOfWeek = currentCalendar.getFirstDayOfWeek();
updateCalendarDisplay(currentCalendar);
}
}
/* Update the calendar display when a new month is selected */
private void updateCalendarDisplay(Calendar calendar) {
removeAll();
setLayout(new TableLayout(0, 7, -1, -1));
add(createMonthLabel(calendar), "gridwidth=7 bottom=3");
for (int i = 0; i < 7; i++) {
add(createWeekdayLabel(i), "weightx=1 width=1 bottom=2");
}
int weekday = getFirstWeekdayIndex(calendar);
for (int i = 0; i < weekday; i++) {
add(createDayBox(null), "weighty=1");
}
int nDays = getDaysInMonth(calendar);
for (int day = 1; day <= nDays; day++) {
add(createDayBox("" + day), "weighty=1");
weekday = (weekday + 1) % 7;
}
while (weekday != 0) {
add(createDayBox(null), "weighty=1");
weekday = (weekday + 1) % 7;
}
validate();
}
/* Generate the header label for a particular month */
private JLabel createMonthLabel(Calendar calendar) {
int month = calendar.get(Calendar.MONTH);
int year = calendar.get(Calendar.YEAR);
String monthName = capitalize(monthNames[month]);
JLabel label = new JLabel(monthName + " " + year);
label.setFont(JTFTools.decodeFont(TITLE_FONT));
label.setHorizontalAlignment(JLabel.CENTER);
return label;
}
/* Create a label for the weekday header at the specified index */
private JLabel createWeekdayLabel(int index) {
int weekday = (firstDayOfWeek + index + 6) % 7 + 1;
JLabel label = new JLabel(capitalize(weekdayNames[weekday]));
label.setFont(JTFTools.decodeFont(LABEL_FONT));
label.setHorizontalAlignment(JLabel.CENTER);
return label;
}
/* Compute the number of days in the current month */
private int getDaysInMonth(Calendar calendar) {
calendar = (Calendar) calendar.clone();
int current = calendar.get(Calendar.DAY_OF_MONTH);
int next = current;
while (next >= current) {
current = next;
calendar.add(Calendar.DAY_OF_MONTH, 1);
next = calendar.get(Calendar.DAY_OF_MONTH);
}
return current;
}
/* Compute the index of the first weekday for the current Locale */
private int getFirstWeekdayIndex(Calendar calendar) {
int day = calendar.get(Calendar.DAY_OF_MONTH);
int weekday = calendar.get(Calendar.DAY_OF_WEEK);
int weekdayIndex = (weekday + 7 - firstDayOfWeek) % 7;
return ((5 * 7 + 1) + weekdayIndex - day) % 7;
}
/* Create a box for a calendar day containing the specified text */
private Component createDayBox(String text) {
VPanel vbox = new VPanel();
if (text== null) {
vbox.setBackground(EMPTY_BACKGROUND);
} else {
JLabel label = new JLabel(text);
label.setFont(JTFTools.decodeFont(DATE_FONT));
vbox.add(label, "anchor=NORTHEAST top=2 right=2");
vbox.setBackground(Color.WHITE);
}
vbox.setOpaque(true);
vbox.setBorder(new LineBorder(Color.BLACK));
return vbox;
}
/* Create a list of country names from the list of Locales */
private void initCountryList() {
countries = new String[LOCALES.length];
for (int i = 0; i < LOCALES.length; i++) {
countries[i] = LOCALES[i].getDisplayCountry();
}
}
/* Capitalize the first letter of a word */
private String capitalize(String word) {
return word.substring(0, 1).toUpperCase() + word.substring(1);
}
/* Private constants */
private static final Color EMPTY_BACKGROUND = new Color(0xDDDDDD);
private static final String TITLE_FONT = "Serif-36";
private static final String LABEL_FONT = "Serif-bold-14";
private static final String DATE_FONT = "Serif-18";
private static final Locale[] LOCALES = {
new Locale("fr", "FR", ""), new Locale("de", "DE", ""),
new Locale("es", "MX", ""), new Locale("it", "IT", ""),
new Locale("nl", "NL", ""), new Locale("es", "ES", ""),
new Locale("en", "GB", ""), new Locale("en", "US", "")
};
/* Private instance variables */
private JComboBox localeChooser;
private String[] countries;
private Calendar currentCalendar;
private DateFormatSymbols symbols;
private String[] monthNames;
private String[] weekdayNames;
private int firstDayOfWeek;
/* Standard Java entry point */
/* This method can be eliminated in most Java environments */
public static void main(String[] args) {
new CalendarDemo().start(args);
}
}

View File

@ -0,0 +1,39 @@
/*
* File: Checkerboard.java
* -----------------------
* This program draws a checkerboard. The dimensions of the
* checkerboard is specified by the constants NROWS and
* NCOLUMNS, and the size of the squares is chosen so
* that the checkerboard fills the available vertical space.
*/
import acm.graphics.*;
import acm.program.*;
public class Checkerboard extends GraphicsProgram {
/** Runs the program */
public void run() {
double sqSize = (double) getHeight() / NROWS;
for (int i = 0; i < NROWS; i++) {
for (int j = 0; j < NCOLUMNS; j++) {
double x = j * sqSize;
double y = i * sqSize;
GRect sq = new GRect(x, y, sqSize, sqSize);
sq.setFilled((i + j) % 2 != 0);
add(sq);
}
}
}
/* Private constants */
private static final int NROWS = 8; /* Number of rows */
private static final int NCOLUMNS = 8; /* Number of columns */
/* Standard Java entry point */
/* This method can be eliminated in most Java environments */
public static void main(String[] args) {
new Checkerboard().start(args);
}
}

View File

@ -0,0 +1,83 @@
/*
* File: CurrConvUsingInnerClasses.java
* ------------------------------------
* This program implements a simple currency converter. This version
* uses anonymous inner classes to specify the action listeners.
*/
import acm.gui.*;
import acm.program.*;
import java.awt.event.*;
import javax.swing.*;
public class CurrConvUsingInnerClasses extends Program {
/** Initialize the graphical user interface */
public void init() {
setLayout(new TableLayout(3, 2));
currencyTable = new CurrencyTable();
leftChooser = new JComboBox(currencyTable.getCurrencyNames());
rightChooser = new JComboBox(currencyTable.getCurrencyNames());
leftField = new DoubleField();
rightField = new DoubleField();
JButton leftButton = new JButton("Convert ->");
JButton rightButton = new JButton("<- Convert");
ActionListener convertLeftToRight = new ActionListener() {
public void actionPerformed(ActionEvent e) {
double fromValue = leftField.getValue();
double fromRate = getRateFromChooser(leftChooser);
double toRate = getRateFromChooser(rightChooser);
double toValue = fromValue * fromRate / toRate;
rightField.setValue(toValue);
}
};
ActionListener convertRightToLeft = new ActionListener() {
public void actionPerformed(ActionEvent e) {
double fromValue = rightField.getValue();
double fromRate = getRateFromChooser(rightChooser);
double toRate = getRateFromChooser(leftChooser);
double toValue = fromValue * fromRate / toRate;
leftField.setValue(toValue);
}
};
leftChooser.setSelectedItem("US Dollar");
rightChooser.setSelectedItem("Euro");
leftField.setFormat("0.00");
leftField.addActionListener(convertLeftToRight);
rightField.setFormat("0.00");
rightField.addActionListener(convertRightToLeft);
rightField.addActionListener(this);
leftButton.addActionListener(convertLeftToRight);
rightButton.addActionListener(convertRightToLeft);
add(leftChooser);
add(rightChooser);
add(leftField);
add(rightField);
add(leftButton);
add(rightButton);
}
/* Gets a rate from the specified chooser */
private double getRateFromChooser(JComboBox chooser) {
String currencyName = (String) chooser.getSelectedItem();
return currencyTable.getExchangeRate(currencyName);
}
/* Private instance variables */
private CurrencyTable currencyTable;
private JComboBox leftChooser;
private JComboBox rightChooser;
private DoubleField leftField;
private DoubleField rightField;
/** Set the program dimensions */
public static final int APPLICATION_WIDTH = 350;
public static final int APPLICATION_HEIGHT = 200;
/* Standard Java entry point */
/* This method can be eliminated in most Java environments */
public static void main(String[] args) {
new CurrConvUsingInnerClasses().start(args);
}
}

View File

@ -0,0 +1,82 @@
/*
* File: CurrencyConverter.java
* ----------------------------
* This program implements a simple currency converter.
*/
import acm.gui.*;
import acm.program.*;
import java.awt.event.*;
import javax.swing.*;
public class CurrencyConverter extends Program {
/** Initialize the graphical user interface */
public void init() {
setLayout(new TableLayout(4, 2));
currencyTable = new CurrencyTable();
leftChooser = new JComboBox(currencyTable.getCurrencyNames());
leftChooser.setSelectedItem("US Dollar");
rightChooser = new JComboBox(currencyTable.getCurrencyNames());
rightChooser.setSelectedItem("Euro");
leftField = new DoubleField();
leftField.setFormat("0.00");
leftField.setActionCommand("Convert ->");
leftField.addActionListener(this);
rightField = new DoubleField();
rightField.setFormat("0.00");
rightField.setActionCommand("<- Convert");
rightField.addActionListener(this);
add(leftChooser);
add(rightChooser);
add(leftField);
add(rightField);
add(new JButton("Convert ->"));
add(new JButton("<- Convert"));
String date = "(rates from " + currencyTable.getDate() + ")";
add(new JLabel(date, JLabel.CENTER), "gridwidth=2");
addActionListeners();
}
/** Listens for a button action */
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
if (cmd.equals("Convert ->")) {
double fromValue = leftField.getValue();
double fromRate = getRateFromChooser(leftChooser);
double toRate = getRateFromChooser(rightChooser);
double toValue = fromValue * fromRate / toRate;
rightField.setValue(toValue);
} else if (cmd.equals("<- Convert")) {
double fromValue = rightField.getValue();
double fromRate = getRateFromChooser(rightChooser);
double toRate = getRateFromChooser(leftChooser);
double toValue = fromValue * fromRate / toRate;
leftField.setValue(toValue);
}
}
/* Gets a rate from the specified chooser */
private double getRateFromChooser(JComboBox chooser) {
String currencyName = (String) chooser.getSelectedItem();
return currencyTable.getExchangeRate(currencyName);
}
/* Private instance variables */
private CurrencyTable currencyTable;
private JComboBox leftChooser;
private JComboBox rightChooser;
private DoubleField leftField;
private DoubleField rightField;
/** Set the program dimensions */
public static final int APPLICATION_WIDTH = 350;
public static final int APPLICATION_HEIGHT = 200;
/* Standard Java entry point */
/* This method can be eliminated in most Java environments */
public static void main(String[] args) {
new CurrencyConverter().start(args);
}
}

View File

@ -0,0 +1,84 @@
/*
* File: CurrencyTable.java
* ------------------------
* This file provides a stub implementation of the CurrencyTable
* class used by the CurrencyConverter example. This implementation
* simply returns a set of data values stored statically in the
* class. A more ambitious implementation could go out to the web
* and retrieve the actual data.
*/
import acm.util.*;
/** This class implements a currency table */
public class CurrencyTable {
/** Return an array containing the names of all defined currencies */
public String[] getCurrencyNames() {
int nCurrencies = CURRENCIES.length;
String[] names = new String[nCurrencies];
for (int i = 0; i < nCurrencies; i++) {
names[i] = CURRENCIES[i].getName();
}
return names;
}
/** Return the exchange rate for a named currency */
public double getExchangeRate(String name) {
for (int i = 0; i < CURRENCIES.length; i++) {
if (name.equalsIgnoreCase(CURRENCIES[i].getName())) {
return CURRENCIES[i].getRate();
}
}
throw new ErrorException("No currency named " + name);
}
/** Return the date at which the exchange rate is calculated */
public String getDate() {
return TABLE_DATE;
}
/* Currency table (Source: Interbank Rate for 22-Jul-05) */
private static final String TABLE_DATE = "22-Jul-05";
private static final CurrencyEntry[] CURRENCIES = {
new CurrencyEntry("Australian Dollar", 0.766),
new CurrencyEntry("Brazilian Real", 0.435),
new CurrencyEntry("British Pound", 1.754),
new CurrencyEntry("Canadian Dollar", 0.821),
new CurrencyEntry("Chinese Yuan", 0.121),
new CurrencyEntry("Euro", 1.218),
new CurrencyEntry("Japanese Yen", 0.00908),
new CurrencyEntry("Mexican Peso", 0.942),
new CurrencyEntry("South African Rand", 0.153),
new CurrencyEntry("Swiss Franc", 0.779),
new CurrencyEntry("US Dollar", 1.000)
};
}
/* Package class: CurrencyEntry */
/**
* This class is used to store the name of a currency together with
* its relative value in comparison to the other currencies. The
* example defines the dollar as 1.0, but the code does not depend
* on that definition.
*/
class CurrencyEntry {
public CurrencyEntry(String name, double rate) {
currencyName = name;
exchangeRate = rate;
}
public String getName() {
return currencyName;
}
public double getRate() {
return exchangeRate;
}
private String currencyName;
private double exchangeRate;
}

View File

@ -0,0 +1,37 @@
/*
* File: DrawFace.java
* -------------------
* This program creates a GFace object.
*/
import acm.graphics.*;
import acm.program.*;
import java.awt.event.*;
public class DrawFace extends GraphicsProgram {
public void run() {
face = new GFace(FACE_WIDTH, FACE_HEIGHT);
add(face, getWidth() / 2, getHeight() / 2);
addMouseListeners();
}
/** Called when the mouse is moved to adjust the eyes */
public void mouseMoved(MouseEvent e) {
face.lookAt(e.getX(), e.getY());
}
/* Constants */
private static final double FACE_WIDTH = 200;
private static final double FACE_HEIGHT = 300;
/* Private instance variables */
private GFace face;
private GObject gobj;
/* Standard Java entry point */
/* This method can be eliminated in most Java environments */
public static void main(String[] args) {
new DrawFace().start(args);
}
}

View File

@ -0,0 +1,41 @@
/*
* File: DrawLine.java
* -------------------
* This program allows users to create lines on the graphics
* canvas by clicking and dragging with the mouse. The line
* is redrawn from the original point to the new endpoint, which
* makes it look as if it is connected with a rubber band.
*/
import acm.graphics.*;
import acm.program.*;
import java.awt.event.*;
/** This class allows users to draw lines on the canvas */
public class DrawLine extends GraphicsProgram {
/** Initializes the program by enabling the mouse listeners */
public void init() {
addMouseListeners();
}
/** Called on mouse press to create a new line */
public void mousePressed(MouseEvent e) {
line = new GLine(e.getX(), e.getY(), e.getX(), e.getY());
add(line);
}
/** Called on mouse drag to reset the endpoint */
public void mouseDragged(MouseEvent e) {
line.setEndPoint(e.getX(), e.getY());
}
/* Private instance variables */
private GLine line;
/* Standard Java entry point */
/* This method can be eliminated in most Java environments */
public static void main(String[] args) {
new DrawLine().start(args);
}
}

View File

@ -0,0 +1,33 @@
/*
* File: DrawTurtleFlower1.java
* ----------------------------
* This program draws a turtle flower using receiver-relative
* invocations in a single, undecomposed run method.
*/
import acm.graphics.*;
import acm.program.*;
public class DrawTurtleFlower1 extends GraphicsProgram {
/**
* Runs the program. This program creates a GTurtle object,
* puts it in the center of the screen, and then draws a flower.
* The flower consiste of 36 squares, with a 10-degrees rotation
* between each one. The squares, in turn, are drawn by drawing
* four line segments interspersed with 90-degree rotations.
*/
public void run() {
GTurtle turtle = new GTurtle();
add(turtle, getWidth() / 2, getHeight() / 2);
turtle.penDown();
for (int i = 0; i < 36; i++) {
for (int j = 0; j < 4; j++) {
turtle.forward(100);
turtle.left(90);
}
turtle.left(10);
}
}
}

View File

@ -0,0 +1,45 @@
/*
* File: DrawTurtleFlower2.java
* ----------------------------
* This program draws a turtle flower using receiver-relative
* invocations and two levels of decomposition.
*/
import acm.graphics.*;
import acm.program.*;
public class DrawTurtleFlower2 extends GraphicsProgram {
/**
* Runs the program. This program creates a GTurtle object,
* puts it in the center of the screen, and then draws a flower.
*/
public void run() {
turtle = new GTurtle();
add(turtle, getWidth() / 2, getHeight() / 2);
turtle.penDown();
drawFlower();
}
/** Draws a flower with 36 squares separated by 10-degree turns. */
private void drawFlower() {
for (int i = 0; i < 36; i++) {
drawSquare();
turtle.left(10);
}
}
/** Draws a square with four lines separated by 90-degree turns. */
private void drawSquare() {
for (int i = 0; i < 4; i++) {
turtle.forward(100);
turtle.left(90);
}
}
/** Holds the GTurtle object as an instance variable */
private GTurtle turtle;
}

View File

@ -0,0 +1,46 @@
/*
* File: DrawTurtleFlower3.java
* ----------------------------
* This program draws a turtle flower using a GTurtle subclass
* that knows how to draw flowers.
*/
import acm.graphics.*;
import acm.program.*;
public class DrawTurtleFlower3 extends GraphicsProgram {
/**
* Runs the program. This program creates a FlowerTurtle object,
* centers it in the screen, and then asks it to draw a flower.
*/
public void run() {
FlowerTurtle turtle = new FlowerTurtle();
add(turtle, getWidth() / 2, getHeight() / 2);
turtle.penDown();
turtle.drawFlower();
}
}
/**
* A GTurtle subclass that knows how to draw a flower.
*/
class FlowerTurtle extends GTurtle {
/** Draws a flower with 36 squares separated by 10-degree turns. */
public void drawFlower() {
for (int i = 0; i < 36; i++) {
drawSquare();
left(10);
}
}
/** Draws a square with four lines separated by 90-degree turns. */
private void drawSquare() {
for (int i = 0; i < 4; i++) {
forward(100);
left(90);
}
}
}

View File

@ -0,0 +1,16 @@
public class Empty {
public String look;
Empty () {
look = " ";
}
String show(int width){
String row ="";
for (int i=0;i<=width;i++)
row += look;
return row;
}
}

View File

@ -0,0 +1,39 @@
/*
* File: FeltBoard.java
* --------------------
* This program offers a simple example of the acm.graphics package
* that draws a red rectangle and a green oval. The dimensions of
* the rectangle are chosen so that its sides are in proportion to
* the "golden ratio" thought by the Greeks to represent the most
* aesthetically pleasing geometry.
*/
import java.awt.Color;
import acm.graphics.GOval;
import acm.graphics.GRect;
import acm.program.GraphicsProgram;
public class FeltBoard extends GraphicsProgram {
/** Runs the program */
public void run() {
GRect rect = new GRect(100, 50, 100, 100 / PHI);
rect.setFilled(true);
rect.setColor(Color.RED);
add(rect);
GOval oval = new GOval(150, 50 + 50 / PHI, 100, 100 / PHI);
oval.setFilled(true);
oval.setColor(Color.GREEN);
add(oval);
}
/** Constant representing the golden ratio */
public static final double PHI = 1.618;
/* Standard Java entry point */
/* This method can be eliminated in most Java environments */
public static void main(String[] args) {
new FeltBoard().start(args);
}
}

View File

@ -0,0 +1,45 @@
/*
* File: FeltBoard.java
* --------------------
* This program offers a simple example of the acm.graphics package
* that draws a red rectangle and a green oval. The dimensions of
* the rectangle are chosen so that its sides are in proportion to
* the "golden ratio" thought by the Greeks to represent the most
* aesthetically pleasing geometry.
*/
import java.awt.Color;
import acm.graphics.GOval;
import acm.graphics.GRect;
import acm.graphics.GSquare;
import acm.program.GraphicsProgram;
public class FeltBoard2 extends GraphicsProgram {
/** Runs the program */
public void run() {
GRect rect = new GRect(100, 50, 100, 100 / PHI);
rect.setFilled(true);
rect.setColor(Color.RED);
add(rect);
GOval oval = new GOval(150, 50 + 50 / PHI, 100, 100 / PHI);
oval.setFilled(true);
oval.setColor(Color.GREEN);
add(oval);
GSquare square = new GSquare(120, 80, 60);
square.setColor(Color.black);
add(square);
GShadedRectangle gsr = new GShadedRectangle(60,90,100,120);
add(gsr);
}
/** Constant representing the golden ratio */
public static final double PHI = 1.618;
/* Standard Java entry point */
/* This method can be eliminated in most Java environments */
public static void main(String[] args) {
new FeltBoard2().start(args);
}
}

View File

@ -0,0 +1,53 @@
/*
* File: FeltBoard.java
* --------------------
* This program offers a simple example of the acm.graphics package
* that draws a red rectangle and a green oval. The dimensions of
* the rectangle are chosen so that its sides are in proportion to
* the "golden ratio" thought by the Greeks to represent the most
* aesthetically pleasing geometry.
*/
import java.awt.Color;
import acm.graphics.GRect;
import acm.graphics.GSquare2;
import acm.graphics.GStrangeRect;
import acm.graphics.GStringArray;
import acm.graphics.GStringArrayCompound;
import acm.program.GraphicsProgram;
public class FeltBoard3 extends GraphicsProgram {
/** Runs the program */
public void run() {
GRect rect = new GRect(100, 50, 100, 100 / PHI);
rect.setFilled(true);
rect.setColor(Color.RED);
add(rect);
GSquare2 sq2 = new GSquare2(100,80, 80);
sq2.setColor(Color.GREEN);
add(sq2);
GStrangeRect rect2 = new GStrangeRect(130, 80, 100, 100 / PHI);
rect2.setFilled(true);
rect2.setColor(Color.RED);
add(rect2);
String[] demo = new String[]{"Book2","Page9","Chapter 24.10","P3", "Word 17"};
// GStringArray array1 = new GStringArray(demo, 200, 200);
// add(array1);
GStringArrayCompound array2 = new GStringArrayCompound(demo, 200, 300);
array2.setColor(Color.black);
array2.markAsComplete();
add(array2);
System.err.println(array2 +"\n "+array2.getElementCount() );
}
/** Constant representing the golden ratio */
public static final double PHI = 1.618;
/* Standard Java entry point */
/* This method can be eliminated in most Java environments */
public static void main(String[] args) {
new FeltBoard3().start(args);
}
}

View File

@ -0,0 +1,34 @@
/*
* File: FlowerTurtleProgram.java
* ------------------------------
* This program draws a turtle flower by invoking a GTurtle
* object as if it were a program.
*/
import acm.graphics.*;
public class FlowerTurtleProgram extends GTurtle {
/** Runs the program. */
public void run() {
penDown();
flower();
}
/** Draws a flower with 36 squares separated by 10-degree turns. */
private void flower() {
for (int i = 0; i < 36; i++) {
square();
left(10);
}
}
/** Draws a square with four lines separated by 90-degree turns. */
private void square() {
for (int i = 0; i < 4; i++) {
forward(100);
left(90);
}
}
}

View File

@ -0,0 +1,29 @@
/*
* File: GBall.java
* ----------------
* This file defines a GObject class that represents a ball.
*/
import acm.graphics.*;
/**
* This class defines a GObject subclass that represents a ball
* whose reference point is the center rather than the upper
* left corner.
*/
public class GBall extends GCompound {
/** Creates a new ball with radius r centered at the origin */
public GBall(double r) {
GOval ball = new GOval(2 * r, 2 * r);
ball.setFilled(true);
add(ball, -r, -r);
markAsComplete();
}
/** Creates a new ball with radius r centered at (x, y) */
public GBall(double r, double x, double y) {
this(r);
setLocation(x, y);
}
}

View File

@ -0,0 +1,40 @@
/*
* File: GEye.java
* ---------------
* This file defines a GEye class that can look in a particular
* direction.
*/
import acm.graphics.*;
public class GEye extends GCompound {
/** Creates a new instance of the GEye class */
public GEye(double width, double height) {
add(new GOval(width, height), -width / 2, -height / 2);
r = PUPIL_RADIUS_FRACTION * Math.min(width, height);
pupil = new GOval(2 * r, 2 * r);
pupil.setFilled(true);
add(pupil, -r, -r);
}
/**
* Shifts the eye to look at the point (x, y). Note that x
* and y are in the coordinate system of the canvas and not
* in the local coordinate space of the compound. The call
* to getCanvasPoint returns the coordinate of the eye shifted
* to the space of the canvas.
*/
public void lookAt(double x, double y) {
GPoint pt = getCanvasPoint(0, 0);
pupil.setLocation(-r, -r);
pupil.movePolar(r, GMath.angle(x - pt.getX(), y - pt.getY()));
}
/* Pupil radius as a function of the eye size */
private static final double PUPIL_RADIUS_FRACTION = 0.2;
/* Instance variables */
private GOval pupil;
private double r;
}

View File

@ -0,0 +1,59 @@
/*
* File: GFace.java
* ----------------
* This file defines a compound GFace class.
*/
import acm.graphics.*;
/**
* This class defines a new GObject subclass called GFace, which is
* a compound consisting of an outline, two eyes, a nose, and a mouth.
* The origin point for the face is the center of the figure.
*/
public class GFace extends GCompound {
/** Construct a new GFace object with the specified dimensions */
public GFace(double width, double height) {
head = new GOval(width, height);
leftEye = new GEye(EYE_WIDTH * width, EYE_HEIGHT * height);
rightEye = new GEye(EYE_WIDTH * width, EYE_HEIGHT * height);
nose = createNose(NOSE_WIDTH * width, NOSE_HEIGHT * height);
mouth = new GRect(MOUTH_WIDTH * width, MOUTH_HEIGHT * height);
add(head, -width / 2, -height / 2);
add(leftEye, -0.25 * width, -0.25 * height);
add(rightEye, 0.25 * width, -0.25 * height);
add(nose, 0, 0);
add(mouth, -MOUTH_WIDTH * width / 2,
0.25 * height - MOUTH_HEIGHT * height / 2);
}
/* Creates a triangle for the nose */
private GPolygon createNose(double width, double height) {
GPolygon poly = new GPolygon();
poly.addVertex(0, -height / 2);
poly.addVertex(width / 2, height / 2);
poly.addVertex(-width / 2, height / 2);
return poly;
}
/** Adjusts the eyes so they look at the point (x, y) */
public void lookAt(double x, double y) {
leftEye.lookAt(x, y);
rightEye.lookAt(x, y);
}
/* Constants specifying feature size as a fraction of the head size */
private static final double EYE_WIDTH = 0.15;
private static final double EYE_HEIGHT = 0.15;
private static final double NOSE_WIDTH = 0.15;
private static final double NOSE_HEIGHT = 0.10;
private static final double MOUTH_WIDTH = 0.50;
private static final double MOUTH_HEIGHT = 0.03;
/* Private instance variables */
private GOval head;
private GEye leftEye, rightEye;
private GPolygon nose;
private GRect mouth;
}

View File

@ -0,0 +1,29 @@
import java.awt.Color;
import java.awt.Graphics;
import acm.graphics.GObject;
import acm.graphics.GRoundRect;
public abstract class GShadedObject extends GObject {
private GRoundRect rect;
public GShadedObject(double x, double y, double w, double h) {
rect = new GRoundRect(getLocation().getX()+5, getLocation().getY()+5,
getWidth(), getHeight());
rect.setFilled(true);
rect.setFillColor(Color.GRAY);
}
@Override
public void paint(Graphics g) {
if (rect == null) {
rect = new GRoundRect(getLocation().getX(), getLocation().getY(),
getWidth(), getHeight());
rect.setFilled(true);
rect.setFillColor(Color.GRAY);
}
rect.paint(g);
}
}

View File

@ -0,0 +1,31 @@
import java.awt.Color;
import java.awt.Graphics;
import acm.graphics.GRect;
import acm.graphics.GRectangle;
public class GShadedRectangle extends GShadedObject {
GRect myRect;
public GShadedRectangle(double x, double y, double w, double h) {
super(x, y, w, h);
myRect = new GRect(x, y, w, h);
myRect.setFilled(true);
myRect.setFillColor(Color.BLUE);
}
@Override
public GRectangle getBounds() {
return myRect.getBounds();
// return new GRectangle(100, 100, 200, 200);
// return new GRectangle(rect.getX(), rect.getY(),
// rect.getWidth()+5, rect.getHeight()+5);
}
public void paint(Graphics g) {
super.paint(g);
myRect.paint(g);
}
}

View File

@ -0,0 +1,39 @@
/*
* File: GStar.java
* ----------------
* This file illustrates the strategy of subclassing GPolygon by
* creating a new GObject class depicting a five-pointed star.
*/
import acm.graphics.*;
public class GStar extends GPolygon {
/**
* Creates a new GStar centered at the origin that fits inside
* a square of the specified size.
*/
public GStar(double size) {
double sinTheta = GMath.sinDegrees(18);
double b = 0.5 * sinTheta / (1.0 + sinTheta);
double edge = (0.5 - b) * size;
addVertex(-size / 2, -b * size);
int angle = 0;
for (int i = 0; i < 5; i++) {
addPolarEdge(edge, angle);
addPolarEdge(edge, angle + 72);
angle -= 72;
}
markAsComplete();
}
/**
* Creates a new GStar centered at the point (x, y) that fits inside
* a square of the specified size.
*/
public GStar(double x, double y, double size) {
this(size);
setLocation(x, y);
}
}

View File

@ -0,0 +1,23 @@
/*
* File: HelloConsole.java
* -----------------------
* This program displays the message "hello, world" and is inspired
* by the first program "The C Programming Language" by Brian
* Kernighan and Dennis Ritchie. This version displays its message
* using a console window.
*/
import acm.program.ConsoleProgram;
public class HelloConsole extends ConsoleProgram {
public void run() {
println("hello, world");
}
/* Standard Java entry point */
/* This method can be eliminated in most Java environments */
public static void main(String[] args) {
new HelloConsole().start(args);
}
}

View File

@ -0,0 +1,23 @@
/*
* File: HelloDialog.java
* ----------------------
* This program displays the message "hello, world" and is inspired
* by the first program "The C Programming Language" by Brian
* Kernighan and Dennis Ritchie. This version displays the message
* in a dialog box.
*/
import acm.program.DialogProgram;
public class HelloDialog extends DialogProgram {
public void run() {
println("hello, world");
}
/* Standard Java entry point */
/* This method can be eliminated in most Java environments */
public static void main(String[] args) {
new HelloDialog().start(args);
}
}

Some files were not shown because too many files have changed in this diff Show More