Lunds universitet FYTA11 Institutionen f¨or Astronomi och Teoretisk fysik HT 12
L¨osningsf¨orslag tentamen FYTA11 — Javaprogrammering
Onsdag 5 december 2012, 10:15 – 14:15
Instruktioner
Hj¨alpmedel: Papper och penna. Behandla h¨ogst en uppgift per papper och s¨att ditt namn och uppgiftens nummer p˚ a varje papper. Skriv l¨asligt och kommentera utf¨orligt vad du g¨or – det kan ge dig po¨ang ¨aven om resultatet blir fel. Tentamen omfattar fyra uppgifter som vardera kan ge upp till tio po¨ang. F¨or G och VG kr¨avs 20 respektive 30 po¨ang, inr¨aknat de h¨ogst fem bonuspo¨angen fr˚ an simulerings¨ovningarna.
Uppgift 1: Sm˚ a fel
Korrigera felen i f¨oljande kodstycken.
a.
//if(arr.length = 3) System.out.println("Length is 3");
if(arr.length == 3) System.out.println("Length is 3");
b.
//JButton button;
JButton button = new JButton();
button.setText("Click me!");
c.
public static void main(String[] args) {
if(args.length != 1) {
System.out.println("This program requires one argument!");
System.exit(1);
}
//System.out.println("argument was: " + args[1]);
System.out.println("argument was: " + args[0]);
}
d.
//int year = 60 * 60 * 24 * 365;
long year = 60 * 60 * 24 * 365; // (eller m¨ojligen double) System.out.println("medellivsl¨angd: " + year * 80 + " sekunder");
e.
private String myName = "Steve";
// ...
public boolean isMyName(String name) {
// return myName == name;
return myName.equals(name);
}
f.
//System.out.println("pi is roughly = " + 22/7);
System.out.println("pi is roughly = " + 22./7);
g.
//System.out.println("pi is roughly = " + 3 + Math.sqrt(0.02));
System.out.println("pi is roughly = " + (3 + Math.sqrt(0.02)));
h.
double x, y;
do {
x = Math.random() * 2 - 1;
y = Math.random() * 2 - 1;
// double r2 = x * x + y * y;
//} while(r2 < 1);
} while(x * x + y * y < 1);
i.
Object[] v = new Object[2];
v[0] = "Something";
v[1] = 123;
// ...
//String thing = v[0];
String thing = (String)v[0];
j.
public class Vehicle {
private String model;
public Vehicle(String model) {
this.model = model;
} }
// I en annan fil:
public class Bicycle extends Vehicle {
public Bicycle(String model) {
// this.model = model;
super(model);
} }
Uppgift 2: Median av avrundade argument
Skriv ett program som tar en upps¨attning tal som argument d˚ a det startas, och skriver ut medianen av talen efter att ha avrundat vart och ett av dem till n¨armaste heltal.
Medianen av ett udda antal tal definieras som det tal som ligger i mitten n¨ar talen sorterats. Medianen av ett j¨amnt antal tal ¨ar medelv¨ardet av de tv˚ a mittersta talen (och beh¨over allts˚ a inte vara ett heltal).
Exempelvis skall
% java Median 11.2 -33.3 12.2 0 90 skriva ut talet 11 (eller 11.0), medan
% java Median 11.2 12.2 0 90 skriver ut 11.5.
Om n˚ agot av argumenten inte ¨ar ett tal skall en varning skrivas ut men programmet f˚ ar inte avbrytas utan skall f¨ors¨oka anv¨anda resterande argument. Om det inte finns n˚ agra giltiga tal alls s˚ a skall ett felmeddelande skrivas ut.
public class Median {
public static void main(String[] args) {
// G¨or plats till s˚a m˚anga tal som det finns argument // men h˚all reda p˚a hur m˚anga som stoppats in.
double[] arr = new double[args.length];
int num = 0; // antal tal
for(int i = 0; i < args.length; ++i) { try {
// Om konverteringen lyckas sparar vi talet (avrundat) och ¨okar num double v = Double.parseDouble(args[i]);
arr[num++] = Math.rint(v);
} catch(NumberFormatException e) {
System.err.println(args[i]+ " ¨ar inte ett tal");
} }
if(num == 0) {
System.err.println("inga tal givna");
return;
}
// Sortera talen och finn medianen java.util.Arrays.sort(arr, 0, num);
if(num % 2 == 1)
System.out.println(arr[num/2]);
else
System.out.println((arr[num/2] + arr[num/2-1]) / 2);
// alternativt kan man bli av med if-satsen genom att notera att // num/2 och (num-1)/2 ¨ar identiska om num ¨ar udda:
// System.out.println((arr[num/2] + arr[(num-1)/2]) / 2);
} }
Uppgift 3: Molly Malone
Molly Malone g˚ ar med sin k¨arra och s¨aljer fisk i Dublin. Hon antecknar fisksorten och antalet vid varje f¨ors¨aljning, och vill sedan sammanst¨alla informationen med hj¨alp av ett datorprogram. Du beh¨over hj¨alpa Molly att skriva en metod som sorterar fiskarna och summerar ihop antalet av respektive sort.
I klassen FishNotes finns en inre klass FishCount som representerar en rad i Mollys anteckningar, med namnet p˚ a en fisk och antalet av den sorten. Ditt jobb ¨ar att:
(a) skriva klart metoden summarize() som skall byta ut inneh˚ allet i fishCounts s˚ a som beskrivs i koden: Efter summarize() skall fiskarna vara sorterade alfabetiskt och ihopsummerade efter fisksort (8p).
(b) beskriva i ord (eller med kod) hur du skulle g¨ora f¨or att i st¨allet sortera fiskarna efter antal (fortfarande summerade efter sort), utifr˚ an din l¨osning till (a) (2p).
Det finns flera olika s¨att att l¨osa problemet. F¨oljande sidor ger dokumentation f¨or n˚ agra olika klasser och metoder som kan vara anv¨andbara.
Minns ocks˚ a hur man itererar ¨over en Collection (som t.ex. ArrayList):
for(Iterator<?> it = c.iterator(); it.hasNext(); ) {... it.next() ...}
alternativt for(Element type e : collection) {...}
Exempel: om fishCounts inneh˚ aller (Sill, 12), (Torsk, 2), (Lax, 5), (Sill, 7) f¨ore anropet till summarize s˚ a skall fishCounts efter anropet inneh˚ alla (Lax, 5), (Sill, 19), (Torsk, 2).
Vissa dagar s¨aljer Molly otroligt m˚ anga fiskar s˚ a det ¨ar l¨ampligt att metoden inte skalar kvadratiskt (eller v¨arre) med antalet element i fishCounts.
L¨ osningsf¨ orslag till (a) finns p˚ a f¨oljande sidor. Uppgift (b) l¨oses b¨ast genom att
man sorterar med en Comparator liknande den i andra l¨osningsf¨orslaget, men med
j¨amf¨orelse av count. Om man vill kan man i andra hand (dvs om talen ¨ar lika) ocks˚ a
j¨amf¨ora fish s˚ a att fiskar med samma antal blir sorterade alfabetiskt.
En l¨osning med Comparable, med ¨andringar i FishCount:
import java.util.*;
public class FishNotes {
/** Ett par av (namn, antal) f¨or n˚agon sorts fisk */
// public class FishCount ** ¨andrad till:
public class FishCount implements Comparable<FishCount>
{
public String fish;
public int count;
public FishCount() {}
public FishCount(String f, int c) {
fish = f;
count = c;
}
// Ny metod:
public int compareTo(FishCount o) {
return fish.compareTo(o.fish);
} }
/** Listan ¨over s˚alda fiskar */
private ArrayList<FishCount> fishCounts = new ArrayList<FishCount>();
/** L¨agger till en post till fisklistan */
public void addFish(String name, int count) {
fishCounts.add(new FishCount(name, count));
}
/** Sammanst¨aller listan ¨over fiskar s˚a att fiskarna kommer i alfabetisk ordning och varje fisksort finns med en g˚ang, tillsammans med totala antalet av den sorten. */
public void summarize() {
Collections.sort(fishCounts);
ArrayList<FishCount> newfc = new ArrayList<FishCount>();
String prevfish = null;
int cnt = 0;
for(FishCount fc : fishCounts) {
if(fc.fish.equals(prevfish)) cnt += fc.count;
else {
if(prevfish != null)
newfc.add(new FishCount(prevfish, cnt));
prevfish = fc.fish;
cnt = fc.count;
} }
if(prevfish != null)
newfc.add(new FishCount(prevfish, cnt));
fishCounts = newfc;
}
/** Skriver ut fisklistan */
public void print() {
for(FishCount fc : fishCounts)
System.out.println(fc.fish + "\t" + fc.count);
} }
En l¨osning med Comparator och en anonym klass som g¨or att man slipper ¨andra utanf¨or summarize:
public void summarize() {
// Vi vill slippa hantera tomma samlingar if(fishCounts.size() < 2)
return;
// Sortera p˚a fisknamn med en anonym Comparator-klass Collections.sort(fishCounts, new Comparator<FishCount>() {
public int compare(FishCount f1, FishCount f2) {
return f1.fish.compareTo(f2.fish);
} });
// Skapa en ny samling fiskar. G˚ar igenom fisklistan och adderar upp // antalen och sparar en fisk n¨ar vi ser en v¨axling till en annan sort.
ArrayList<FishCount> newfc = new ArrayList<FishCount>();
FishCount nfc = null;
for(FishCount fc : fishCounts) {
if(nfc == null) // F¨orsta fisken, ta den (vi sabbar gamla fishCounts) nfc = fc;
else if(fc.fish.equals(nfc.fish)) // Samma fisk; ¨oka antalet nfc.count += fc.count;
else { // Annan fisk; nu kan vi spara den f¨orra med r¨att antal newfc.add(nfc);
nfc = fc;
} }
newfc.add(nfc); // Sista fisken i listan fishCounts = newfc;
}
En kortare l¨osning med TreeMap:
public void summarize() {
// Vi l¨agger fiskarna i ett tr¨ad s˚a blir de sorterade efterhand.
TreeMap<String, Integer> tree = new TreeMap<String, Integer>();
for(FishCount fc : fishCounts) {
// Om fisken redan finns i tr¨adet s˚a ¨oka dess antal.
int cnt = fc.count;
if(tree.containsKey(fc.fish)) cnt += tree.get(fc.fish);
tree.put(fc.fish, cnt);
}
// Kopiera fr˚an tr¨adet till fishCounts
fishCounts = new ArrayList<FishCount>(); // clear() vore b¨attre for(Map.Entry<String,Integer> ent : tree.entrySet())
addFish(ent.getKey(), ent.getValue());
Uppgift 4: Partiklar i potential
Du skall simulera partiklar som r¨or sig i en potential och p˚ averkar varandra. F¨or enkelhets skull antas alla partiklar ha massan 1, s˚ a acceration och kraft ¨ar ekvivalen- ta. Simuleringsrogrammet finns redan, men du beh¨over skriva kod f¨or ditt specifika system. Allting g¨ors i tv˚ a dimensioner, och klassen Pair (se n¨asta sida) anv¨ands f¨or att representera b˚ ade en punkt (x, y) och en kraftvektor (F
x, F
y).
Potentialen som du har ges av
U (r) =
( −
krr ≥ 1 k r < 1
d¨ar k ¨ar n˚ agon konstant, vilket ger accelerationen (och kraften)
a(r) =
( −k
rr3r ≥ 1 0 r < 1 f¨or en partikel i punkten r = (x, y). r ¨ar l¨angden av r.
(a) Implementera interfacet Potential (se n¨asta sida), i ¨overensst¨ammelse med ekvationerna ovan. Din klass heter l¨ampligen MyPotential, och skall ta konstanten k som argument till sin konstruktor.
(b) Potential har en metod randomPosition som beh¨ovs f¨or att kunna slumpa ut positioner p˚ a l¨ampliga positioner. Implementera den metoden s˚ a att den returnerar en slumpm¨assig position r j¨amnt f¨ordelad ¨over det omr˚ ade d¨ar 1 < r < 2.
Kraften som verkar p˚ a en partikel i till f¨oljd av v¨axelverkan med ¨ovriga partiklar ¨ar F
i= X
j6=i
(r
i− r
j)
|r
i− r
j|
3och den totala energin i v¨axelverkningarna ¨ar
E = X
i
X
j6=i
1
|r
i− r
j|
(c) L¨agg till interaktioner mellan partiklarna genom att implementera interfa-
cet InteractionPotential. De b˚ ada metoderna tar in positionerna hos samtli-
ga partiklar. getForces returnerar krafterna fr˚ an v¨axelverkan mellan partiklar-
na, med en kraftvektor per partikel. getEnergy returnerar den totala energin hos
v¨axelverkningarna.
/** Ett par av v¨arden (x,y), dvs en vektor i 2 dimensioner */
public class Pair {
public double x;
public double y;
public Pair() {}
public Pair(double xx, double yy) {
x = xx;
y = yy;
} }
public interface Potential {
/** Returnerar den potentiella energin hos en partikel p˚a den givna positionen. */
double getEnergy(Pair position);
/** Returnerar ett Pair (en vektor (Fx,Fy)) som representerar kraften som verkar p˚a en partikel p˚a den givna positionen (gradienten av -energin). */
Pair getForce(Pair position);
/** Genererar en slumpm¨assig punkt i ett l¨ampligt omr˚ade f¨or en partikel
** att starta fr˚an i simuleringen. */
Pair randomPosition();
}
L¨ osningsf¨ orslag (a-b):
public class MyPotential implements Potential {
private double k;
public MyPotential(double k) {
this.k = k;
}
// For convenience: distance to origin for a position private static double posR(Pair p)
{
return Math.sqrt(p.x * p.x + p.y * p.y);
}
public double getEnergy(Pair pos) {
double r = posR(pos);
if(r < 1) return k; // skulle ha varit -k return -k / r;
}
public Pair getForce(Pair pos) {
double r = posR(pos);
if(r < 1) return new Pair();
double a = -k / (r * r * r);
return new Pair(a * pos.x, a * pos.y);
}
public Pair randomPosition() {
double a = Math.random() * 2 * Math.PI;
double r = Math.random() + 1;
return new Pair(r * Math.cos(a), r * Math.sin(a));
public interface InteractionPotential {
/** Returnerar den totala interaktionsenergin hos en upps¨attning partiklar p˚a de givna positionerna. */
double getEnergy(Pair[] positions);
/** Returnerar ett f¨alt med lika m˚anga Pair som i argumentet. Argumentets Pair representerar partiklarnas koordinater och returv¨ardets Pair representerar de krafter som verkar p˚a var och en av partiklarna till f¨oljd av v¨axelverkan mellan dem. */
Pair[] getForces(Pair[] positions);
}
L¨ osningsf¨ orslag (c):
public class MyInteraction implements InteractionPotential {
// Avst˚andet mellan tv˚a punkter, s˚a vi slipper skriva uttrycket flera g˚anger private static double dist(Pair a, Pair b)
{
return Math.sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
public double getEnergy(Pair[] pos) {
double E = 0;
for(int i = 0; i < pos.length; ++i) {
for(int j = 0; j < pos.length; ++j) {
if(i != j)
E += 1 / dist(pos[i], pos[j]);
} }
return E;
}
public Pair[] getForces(Pair[] pos) {
Pair[] f = new Pair[pos.length];
for(int i = 0; i < pos.length; ++i) {
f[i] = new Pair();
for(int j = 0; j < pos.length; ++j) {
if(i != j) {
double d3 = Math.pow(dist(pos[i], pos[j]), 3.);
f[i].x += (pos[i].x - pos[j].x) / d3;
f[i].y += (pos[i].y - pos[j].y) / d3;
} } }
return f;
} }