Aufgabenblatt 5

This commit is contained in:
Anton Ertl
2022-05-02 12:20:50 +02:00
parent ef01f2a0fc
commit 1e789dba34
7 changed files with 573 additions and 0 deletions

107
angabe/Aufgabenblatt5.md Normal file
View File

@ -0,0 +1,107 @@
# Aufgabenblatt 5
## Allgemeine Anmerkungen
Ihre Lösung für dieses Aufgabenblatt ist bis Montag, 9.5. 11h durch `git commit` und `git push`
abzugeben. Mit der Angabe werden die Dateien `Massive.java`, `NamedBody.java`, `MassiveLinkedList.java`,
`MassiveForceHashMap.java`, `Simulation5.java` und `Aufgabe5Test.java` mitgeliefert.
Wenn Sie zusätzlich zu den gefragten Klassen weitere Klassen definieren, achten Sie darauf, dass
die Klassennamen mit `My` beginnen, um Konflikte mit späteren Aufgabenblättern zu vermeiden.
## Ziel
Ziel der Aufgabe ist die Anwendung der Konzepte: Gleichheit und Hash-Werte, Hash-Tabelle
(siehe Skriptum Seite 85-91).
## Beschreibung der gegebenen Dateien
- [Massive](../src/Massive.java) ist ein Interface, das Himmelskörper (als kohärente Massen)
beschreibt. `Massive` ist der gemeinsame Obertyp für verschiedene Klassen von Himmelkörpern. Die
meisten spezifizierten Methoden sind mit einer `default`-Implementierung definiert. Dieser
Programcode wird ausgeführt, falls die entsprechende Klasse (`Body` oder `NamedBody`) über keine
eigene Definition der Methode verfügt. Verändern Sie diese Datei bitte nicht.
- [NamedBody](../src/NamedBody.java) ist das Gerüst einer Klassendefinition. Die Klasse
repräsentiert Himmelskörper, die einen Namen haben.
- [MassiveLinkedList](../src/MassiveLinkedList.java) ist das Gerüst für eine Implementierung einer
verketteten Liste von `Massive`-Objekten. Die Liste unterscheidet sich von `BodyLinkedList`
dadurch, dass der Elementtyp statt `Body` der Obertyp `Massive` ist.
- [MassiveForceHashMap](../src/MassiveForceHashMap.java) ist das Gerüst für eine Implementierung
einer assoziativen Datenstruktur, die ein `Massive`-Objekt mit der auf das Objekt wirkenden Kraft
assoziiert.
- [Simulation5](../src/Simulation5.java) ist ein Gerüst für eine ausführbare Klasse. Hier soll
die Simulation analog zur Klasse `Simulation` implementiert werden (damit Sie Ihre [ursprüngliche
Datei](../src/Simulation.java) nicht überschreiben müssen).
- [Aufgabe5Test](../src/Aufgabe5Test.java) ist eine vorgegebene Klasse, die Sie zum Testen Ihrer
Implementierung verwenden sollten. Bei einer fehlerfreien Implementierung sollten bei der
Ausführung dieser Klasse keine Exceptions geworfen werden und alle Tests als erfolgreich ("successful")
ausgegeben werden. Entfernen Sie die Kommentarzeichen, um diese Klasse verwenden zu können. Sie
müssen diese Klasse nicht weiter verändern, können aber eigene Testfälle hinzufügen.
## Aufgaben
Ihre Aufgaben sind folgende:
**1. Implementieren Sie `Massive` in den Klassen `Body` und `NamedBody`.**
Passen Sie die bestehende Definition von `Body` so an, dass die Klasse `Massive` implementiert wird.
Vervollständigen Sie auch `NamedBody` so, dass sie `Massive` implementiert und die vorgegebene
Spezifikationen der Methoden erfüllt.
**2. Überschreiben von `equals` und `hashCode` in `NamedBody`:**
Überschreiben Sie in `NamedBody` die Methoden `equals` und `hashCode` gemäß der dort angeführten
Spezifikation. Achten Sie bei der Implementierung darauf, dass die in der Klasse `Object`
beschriebenen Bedingungen für `equals` und `hashCode` eingehalten werden. `equals` und `hashCode`
müssen zusammen passen.
**3. Vervollständigen von `MassiveLinkedList`:**
Definieren Sie `MassiveLinkedList`. Die Klasse ist wie `BodyLinkedList` aufgebaut, mit dem
Unterschied, dass der Elementtyp statt `Body` nun der Typ `Massive` ist. Die Methode `indexOf`
vergleicht Objekte mittels `equals`.
**4. Implementierung von `MassiveForceHashMap`:**
Vervollständigen Sie die Definition der Klasse `MassiveForceHashMap`, die eine Hash-Tabelle
mit Schlüssel vom Typ `Massive` und Wert vom Typ `Vector3` implementiert. Die Klasse ist ähnlich
zur Klasse `BodyForceTreeMap`. Die Unterschiede sind:
- Der Typ des Schlüssels ist der gemeinsame Obertyp von `Body` und `NamedBody` (`Massive`).
Dadurch lassen sich Objekte beider Klassen gemeinsam in der Hash-Tabelle speichern.
- Die Schlüssel-Werte-Paare sind nicht nach Masse sortiert. Stattdessen wird der Hash-Wert zur
Suche benutzt.
- Es gibt eine zusätzliche Methode `keyList()`. Die Methoden `equals` und `hashCode` werden
redefiniert.
**5. Implementierung von `Simulation5`:**
Implementieren Sie die Simulationsschleife unter Verwendung eines Objekts vom Typ
`MassiveForceHashMap`. Die Methode `keyList()` hilft beim Iterieren der Hash-Tabelle.
Kollisionen von Himmelskörpern müssen in dieser Simulation nicht berücksichtigt werden.
### Hinweise:
- Verwenden Sie bei der Implementierung von `MassiveForceHashMap` eine geeignete Kollisionsbehandlung
für gleiche Hash-Werte. Als Vorlage können Sie den Beispielcode aus dem Skriptum nutzen.
### Denkanstöße (ohne Bewertung)
1. Wie könnte man vorgehen, wenn man - wie in früheren Simulationen - Himmelskörper im Fall von
Kollisionen verschmelzen will?
2. Was ändert sich am Verhalten von `MassiveForceHashMap`, wenn man in `Body` die Methoden
`equals` und `hashCode` überschreiben würde?
#### _Punkteaufteilung_
- Implementierung von `Massive` in `NamedBody`: 1 Punkt
- Implementierung von `Massive` in `Body`: 0.5 Punkt
- Implementierung von `MassiveForceHashMap`: 2 Punkte
- Implementierung von `MassiveLinkedList`: 0.5 Punkte
- Implementierung von `Simulation5`: 1 Punkte
- Gesamt: 5 Punkte

125
src/Aufgabe5Test.java Normal file
View File

@ -0,0 +1,125 @@
public class Aufgabe5Test {
public static void main(String[] args) {
/* //TODO: uncomment for testing
//test classes NamedBody and MassiveForceHashMap
// create 12 named bodies
NamedBody sun1, mercury1, venus1, earth1, moon1, mars1, deimos1, phobos1, vesta1,
pallas1, hygiea1, ceres1;
// create a nameless body
Body earth2 = new Body(5.972E24, new Vector3(-6.13135922534815E10,-1.383789852227691E11,
2.719682263474911E7), new Vector3(26832.720535473603,-11948.23168764519,1.9948243075997851));
// create the same 12 named body-force pairs
sun1 = new NamedBody("Sun",1.989E30, new Vector3(0.0,0.0,0.0)
, new Vector3(0.0,0.0,0.0));
earth1 = new NamedBody("Earth",5.972E24,
new Vector3(-6.13135922534815E10,-1.383789852227691E11,2.719682263474911E7), new Vector3(26832.720535473603,-11948.23168764519,1.9948243075997851));
moon1 = new NamedBody("Moon",7.349E22,
new Vector3(-6.132484773775896E10,-1.387394951280871E11,1.701046736294776E7), new Vector3(27916.62329282941,-12020.39526008238,-94.89703264508708));
mars1 = new NamedBody("Mars",6.41712E23,
new Vector3(-1.7923193702925848E11,1.726665823982123E11,7.991673845249474E9), new Vector3(-15925.78496403673,-15381.16179928219,68.67560910598857));
deimos1 = new NamedBody("Deimos",1.8E20,
new Vector3(-1.792255010450533E11,1.726891122683271E11,7.990659337380297E9), new Vector3(-17100.476719804457,-15020.348656808,631.2927851249581));
phobos1 = new NamedBody("Phobos",1.08E20,
new Vector3(-1.792253482539647E11,1.72661109673625E11,7.987848354800322E9), new Vector3(-14738.203714241401,-13671.17675223948,-411.0012490555253));
mercury1 = new NamedBody("Mercury",3.301E23,
new Vector3(-5.167375560011926E10,-4.217574885682655E10,1.14808913958168E9), new Vector3(21580.25398577148,-34951.03632847389,-4835.225596525241));
venus1 = new NamedBody("Venus",4.86747E24,
new Vector3(-3.123150865740532E10,1.0395568504115701E11,3.173401325838074E9), new Vector3(-33748.180519629335,-10014.25141045021,1809.94488874165));
vesta1 = new NamedBody("Vesta",2.5908E20,
new Vector3(-3.337493557929893E11,-4.7147908276077385E10,4.1923010146878105E10), new Vector3(4440.54247538484,-19718.49074006637,48.06573124543601));
pallas1 = new NamedBody("Pallas",2.14E20,
new Vector3(4.3452066613895575E11,-2.057319365171432E11,1.0549957423213101E11), new Vector3(5058.947582097117,11184.45711782372,-8183.524138259704));
hygiea1 = new NamedBody("Hygiea",8.32E19,
new Vector3(-3.983943433707043E11,2.325833000024021E11,-2.233667695713672E10), new Vector3(-6931.864585548552,-15686.8108598699,-690.5791992347208));
ceres1 = new NamedBody("Ceres",9.394E20,
new Vector3(3.781372641419032E11,1.96718960466285E11,-6.366459168068592E10), new Vector3(-8555.324226752316,14718.33755980907,2040.230135060142));
System.out.println("Test1:");
NamedBody sun2 = new NamedBody("Sun",1.9895E30, new Vector3(0.1,0.0,0.0)
, new Vector3(0.0,0.0,0.0));
NamedBody earth3 = new NamedBody("Earth", 1, new Vector3(0,0,0), new Vector3(0,0,0));
testValue(sun1.equals(sun2), true);
testValue(sun1.hashCode(), sun2.hashCode());
testValue(earth1.equals(earth3), true);
testValue(earth1.hashCode(), earth3.hashCode());
// check basic functions of 'MassiveForceHashMap'
System.out.println("Test2:");
MassiveForceHashMap map = new MassiveForceHashMap();
map.put(sun1, new Vector3(0,0,0));
map.put(mercury1, new Vector3(0,0,0));
map.put(venus1, new Vector3(0,0,0));
map.put(earth1, new Vector3(0,0,0));
map.put(moon1, new Vector3(0,0,0));
map.put(mars1, new Vector3(0,0,0));
map.put(deimos1, new Vector3(0,0,0));
map.put(phobos1, new Vector3(0,0,0));
map.put(vesta1, new Vector3(0,0,0));
map.put(pallas1, new Vector3(0,0,0));
map.put(hygiea1, new Vector3(0,0,0));
map.put(ceres1, new Vector3(0,0,0));
map.put(mars1, new Vector3(0,0,0)); // inserted twice
testValue(map.keyList().size(), 12);
System.out.println("Test3:");
testValue(map.toString().contains("Mars"), true);
testValue(map.toString().contains("Deimos"), true);
testValue(map.toString().contains("Moon"), true);
testValue(map.toString().contains("Earth"), true);
System.out.println("Test4:");
MassiveLinkedList bl = map.keyList();
boolean allThere = true;
while (bl.size() > 0) {
allThere &= map.containsKey(bl.pollFirst());
}
testValue(allThere, true);
testValue(map.containsKey(new Body(0,new Vector3(0,0,0), new Vector3(0,0,0))),
false);
testValue(map.containsKey(new NamedBody("Omuamua",0,new Vector3(0,0,0), new Vector3(0,0,
0))),
false);
System.out.println("Test5:");
Vector3 f = new Vector3(5,5,5);
map.put(earth3, f);
testValue(map.get(earth1), f);
testValue(map.get(earth2), null);
*/ //TODO: uncomment
}
public static void testComparison(Object first, Object second, boolean expected) {
boolean real = first == second;
if (real == expected) {
System.out.println("Successful comparison");
} else {
System.out.println("Comparison NOT successful! Expected value: " + expected + " / Given value: " + real);
}
}
public static void testValue(Object given, Object expected) {
if (given == expected) {
System.out.println("Successful test");
} else {
System.out.println("Test NOT successful! Expected value: " + expected + " / Given value: " + given);
}
}
public static void testValue(double given, double expected) {
if (given < expected + (expected + 1) / 1e12 && given > expected - (expected + 1) / 1e12) {
System.out.println("Successful test");
} else {
System.out.println("Test NOT successful! Expected value: " + expected + " / Given value: " + given);
}
}
}

64
src/Massive.java Normal file
View File

@ -0,0 +1,64 @@
// Represents a coherent mass with a mass center in 3D space. Has two naming schemes for its
// methods. Please, do not change this interface definition!
//
public interface Massive extends Drawable {
// Returns the mass.
default double mass() {
return getMass();
}
// Returns the mass center.
default Vector3 massCenter() {
return getMassCenter();
}
// Returns the mass.
default double getMass() {
return mass();
}
// Returns the mass center.
default Vector3 getMassCenter() {
return massCenter();
}
// Returns the approximate radius of 'this', assuming it is a coherent round mass.
// (It is assumed that the radius r is related to the mass m by r = m ^ 0.5,
// where m and r measured in solar units.)
default double getRadius() {
return radius();
}
// Returns the approximate radius of 'this', assuming it is a coherent round mass.
// (It is assumed that the radius r is related to the mass m by r = m ^ 0.5,
// where m and r measured in solar units.)
default double radius() {
return SpaceDraw.massToRadius(mass());
}
// Returns a vector representing the gravitational force exerted by 'b' on this mass.
// The gravitational Force F is calculated by F = G*(m1*m2)/(r*r), with m1 and m2 being the
// masses of the objects interacting, r being the distance between the centers of the masses
// and G being the gravitational constant.
default Vector3 gravitationalForce(Massive b) {
Vector3 direction = b.massCenter().minus(this.massCenter());
double distance = direction.length();
direction.normalize();
double force = Simulation.G*this.mass()*b.mass()/(distance * distance);
return direction.times(force);
}
// Centers this mass at a new position, according to the specified force vector 'force' exerted
// on it, and updates the current velocity vector accordingly.
// (Velocity depends on the mass of 'this', its current velocity and the exerted force.)
void move(Vector3 force);
}

View File

@ -0,0 +1,72 @@
// A hash map that associates a 'Massive'-object with a Vector3 (typically this is the force
// exerted on the object). The number of key-value pairs is not limited.
//
public class MassiveForceHashMap {
// TODO: define missing parts of this class.
// Initializes 'this' as an empty map.
public MassiveForceHashMap() {
// TODO: implement constructor.
}
// Adds a new key-value association to this map. If the key already exists in this map,
// the value is replaced and the old value is returned. Otherwise 'null' is returned.
// Precondition: key != null.
public Vector3 put(Massive key, Vector3 value) {
// TODO: implement method.
return null;
}
// Returns the value associated with the specified key, i.e. the method returns the force vector
// associated with the specified key. Returns 'null' if the key is not contained in this map.
// Precondition: key != null.
public Vector3 get(Massive key) {
// TODO: implement method.
return null;
}
// Returns 'true' if this map contains a mapping for the specified key.
public boolean containsKey(Massive key) {
// TODO: implement method.
return false;
}
// Returns a readable representation of this map, with all key-value pairs. Their order is not
// defined.
public String toString() {
// TODO: implement method.
return "";
}
// Compares `this` with the specified object for equality. Returns `true` if the specified
// `o` is not `null` and is of type `MassiveForceHashMap` and both `this` and `o` have equal
// key-value pairs, i.e. the number of key-value pairs is the same in both maps and every
// key-value pair in `this` equals one key-value pair in `o`. Two key-value pairs are
// equal if the two keys are equal and the two values are equal. Otherwise `false` is returned.
public boolean equals(Object o) {
// TODO: implement method.
return false;
}
// Returns the hashCode of `this`.
public int hashCode() {
//TODO: implement method.
return 0;
}
// Returns a list of all the keys in no specified order.
public MassiveLinkedList keyList() {
// TODO: implement method.
return null;
}
}

View File

@ -0,0 +1,95 @@
// A list of massive objects implemented as a linked list.
// The number of elements of the list is not limited.
public class MassiveLinkedList {
//TODO: declare variables.
// Initializes 'this' as an empty list.
public MassiveLinkedList() {
//TODO: define constructor.
}
// Initializes 'this' as an independent copy of the specified list 'list'.
// Calling methods of this list will not affect the specified list 'list'
// and vice versa.
// Precondition: list != null.
public MassiveLinkedList(BodyLinkedList list) {
//TODO: define constructor.
}
// Inserts the specified element 'body' at the beginning of this list.
public void addFirst(Massive body) {
//TODO: implement method.
}
// Appends the specified element 'body' to the end of this list.
public void addLast(Massive body) {
//TODO: implement method.
}
// Returns the last element in this list.
// Returns 'null' if the list is empty.
public Massive getLast() {
//TODO: implement method.
return null;
}
// Returns the first element in this list.
// Returns 'null' if the list is empty.
public Massive getFirst() {
//TODO: implement method.
return null;
}
// Retrieves and removes the first element in this list.
// Returns 'null' if the list is empty.
public Massive pollFirst() {
//TODO: implement method.
return null;
}
// Retrieves and removes the last element in this list.
// Returns 'null' if the list is empty.
public Massive pollLast() {
//TODO: implement method.
return null;
}
// Inserts the specified element at the specified position in this list.
// Precondition: i >= 0 && i <= size().
public void add(int i, Massive m) {
//TODO: implement method.
}
// Returns the element at the specified position in this list.
// Precondition: i >= 0 && i < size().
public Massive get(int i) {
//TODO: implement method.
return null;
}
// Returns the index of the first occurrence of the specified element in this list, or -1 if
// this list does not contain the element.
public int indexOf(Massive m) {
//TODO: implement method.
return -2;
}
// Returns the number of elements in this list.
public int size() {
//TODO: implement method.
return -1;
}
}

42
src/NamedBody.java Normal file
View File

@ -0,0 +1,42 @@
public class NamedBody /* TODO: add clause(s) */
{
// TODO: add missing parts of this class.
// Initializes this with name, mass, current position and movement. The associated force
// is initialized with a zero vector.
public NamedBody(String name, double mass, Vector3 massCenter, Vector3 currentMovement) {
// TODO: implement constructor.
}
// Returns the name of the body.
public String getName() {
// TODO: implement method.
return "";
}
// Compares `this` with the specified object. Returns `true` if the specified `o` is not
// `null` and is of type `NamedBody` and both `this` and `o` have equal names.
// Otherwise `false` is returned.
public boolean equals(Object o) {
//TODO: implement method.
return false;
}
// Returns the hashCode of `this`.
public int hashCode() {
//TODO: implement method.
return 0;
}
// Returns a readable representation including the name of this body.
public String toString() {
//TODO: implement method.
return "";
}
}

68
src/Simulation5.java Normal file
View File

@ -0,0 +1,68 @@
import codedraw.CodeDraw;
import java.awt.*;
import java.util.Random;
// Simulates the formation of a massive solar system.
//
public class Simulation5 {
// gravitational constant
public static final double G = 6.6743e-11;
// one astronomical unit (AU) is the average distance of earth to the sun.
public static final double AU = 150e9; // meters
// one light year
public static final double LY = 9.461e15; // meters
// some further constants needed in the simulation
public static final double SUN_MASS = 1.989e30; // kilograms
public static final double SUN_RADIUS = 696340e3; // meters
public static final double EARTH_MASS = 5.972e24; // kilograms
public static final double EARTH_RADIUS = 6371e3; // meters
// set some system parameters
public static final double SECTION_SIZE = 10 * AU; // the size of the square region in space
public static final int NUMBER_OF_BODIES = 22;
public static final double OVERALL_SYSTEM_MASS = 20 * SUN_MASS; // kilograms
// all quantities are based on units of kilogram respectively second and meter.
// The main simulation method using instances of other classes.
public static void main(String[] args) {
// simulation
CodeDraw cd = new CodeDraw();
// create solar system with 12 bodies
NamedBody sun = new NamedBody("Sun",1.989E30, new Vector3(0.0,0.0,0.0), new Vector3(0.0,0.0,0.0));
NamedBody earth = new NamedBody("Earth",5.972E24, new Vector3(-6.13135922534815E10,-1.383789852227691E11,2.719682263474911E7), new Vector3(26832.720535473603,-11948.23168764519,1.9948243075997851));
NamedBody moon = new NamedBody("Moon",7.349E22, new Vector3(-6.132484773775896E10,-1.387394951280871E11,1.701046736294776E7), new Vector3(27916.62329282941,-12020.39526008238,-94.89703264508708));
NamedBody mars = new NamedBody("Mars",6.41712E23, new Vector3(-1.7923193702925848E11,1.726665823982123E11,7.991673845249474E9), new Vector3(-15925.78496403673,-15381.16179928219,68.67560910598857));
NamedBody deimos = new NamedBody("Deimos",1.8E20, new Vector3(-1.792255010450533E11,1.726891122683271E11,7.990659337380297E9), new Vector3(-17100.476719804457,-15020.348656808,631.2927851249581));
NamedBody phobos = new NamedBody("Phobos",1.08E20, new Vector3(-1.792253482539647E11,1.72661109673625E11,7.987848354800322E9), new Vector3(-14738.203714241401,-13671.17675223948,-411.0012490555253));
NamedBody mercury = new NamedBody("Mercury",3.301E23, new Vector3(-5.167375560011926E10,-4.217574885682655E10,1.14808913958168E9), new Vector3(21580.25398577148,-34951.03632847389,-4835.225596525241));
NamedBody venus = new NamedBody("Venus",4.86747E24, new Vector3(-3.123150865740532E10,1.0395568504115701E11,3.173401325838074E9), new Vector3(-33748.180519629335,-10014.25141045021,1809.94488874165));
NamedBody vesta = new NamedBody("Vesta",2.5908E20, new Vector3(-3.337493557929893E11,-4.7147908276077385E10,4.1923010146878105E10), new Vector3(4440.54247538484,-19718.49074006637,48.06573124543601));
NamedBody pallas = new NamedBody("Pallas",2.14E20, new Vector3(4.3452066613895575E11,-2.057319365171432E11,1.0549957423213101E11), new Vector3(5058.947582097117,11184.45711782372,-8183.524138259704));
NamedBody hygiea = new NamedBody("Hygiea",8.32E19, new Vector3(-3.983943433707043E11,2.325833000024021E11,-2.233667695713672E10), new Vector3(-6931.864585548552,-15686.8108598699,-690.5791992347208));
NamedBody ceres = new NamedBody("Ceres",9.394E20, new Vector3(3.781372641419032E11,1.96718960466285E11,-6.366459168068592E10), new Vector3(-8555.324226752316,14718.33755980907,2040.230135060142));
// create some additional bodies
Body[] bodies = new Body[NUMBER_OF_BODIES];
Random random = new Random(2022);
for (int i = 0; i < bodies.length; i++) {
bodies[i] = new Body(Math.abs(random.nextGaussian()) * OVERALL_SYSTEM_MASS / bodies.length,
new Vector3(0.2 * random.nextGaussian() * AU, 0.2 * random.nextGaussian() * AU, 0.2 * random.nextGaussian() * AU),
new Vector3(0 + random.nextGaussian() * 5e3, 0 + random.nextGaussian() * 5e3, 0 + random.nextGaussian() * 5e3));
}
//TODO: implementation of this method according to 'Aufgabenblatt5.md'.
// Add both, NamedBody- and Body-objects, to your simulation.
}
}