Eksamen: REA3049 | Semester: Høst 2024 | Tema: OOP, palindrom-test, batteri-klasse, velferdsteknologi, befolkningsdatasett, virusspredning
Arv er mekanismen som gjør at en subklasse arver egenskaper og metoder fra superklassen. I Java skrives dette som class B extends A.
Trace: −1+2−3+4−5+6−7 = −4.
IF temperatur GREATER THAN 25 DISPLAY "Det er varmt." ELSE IF temperatur GREATER THAN OR EQUAL TO 10 DISPLAY "Det er mildt." ELSE IF temperatur GREATER THAN OR EQUAL TO 0 DISPLAY "Det er kjølig." ELSE DISPLAY "Det er kaldt." ENDIF
Algoritmen sjekker om et tall er et palindrom (leses likt forfra og bakfra). Den bygger opp den reverserte versjonen av tallet og sammenligner med originalen. 121 → 121 (True), 123 → 321 (False).
// Palindrom.java
public class Palindrom {
public static boolean erPalindrom(int h) {
int t = h, s = 0;
while (h != 0) {
s = s * 10 + h % 10;
h /= 10;
}
return t == s;
}
public static void main(String[] args) {
int antall = 0;
for (int n = 100; n < 1000; n++) if (erPalindrom(n)) antall++;
System.out.println("Antall tresifrede palindromer: " + antall);
// Forventet: 90
}
}
Resultat: 90 tresifrede palindromer. Matematisk: 9 valg for første/siste siffer × 10 for midten = 90.
// Batteri.java — energilager med private felter (innkapsling)
public class Batteri {
private final double kapasitet;
private double energinivaa;
public Batteri(double kapasitet, double startNiva) {
if (kapasitet <= 0) throw new IllegalArgumentException("Kapasiteten må være positiv.");
if (startNiva < 0 || startNiva > kapasitet)
throw new IllegalArgumentException("Startnivå må være mellom 0 og " + kapasitet);
this.kapasitet = kapasitet;
this.energinivaa = startNiva;
}
public void lad(double energi) {
if (energi < 0) throw new IllegalArgumentException("Negativ energi ikke tillatt.");
energinivaa = Math.min(energinivaa + energi, kapasitet);
}
public void bruk(double energi) {
if (energi < 0) throw new IllegalArgumentException("Negativ energi ikke tillatt.");
if (energi > energinivaa)
throw new IllegalStateException("Ikke nok energi: forsøkt " + energi + ", tilgjengelig " + energinivaa);
energinivaa -= energi;
}
public void visStatus() {
System.out.printf("Batteri: %.1f / %.1f kWh (%.0f %%)%n",
energinivaa, kapasitet, energinivaa / kapasitet * 100);
}
}
// TestBatteri.java
public class TestBatteri {
public static void main(String[] args) {
Batteri b = new Batteri(10, 5);
b.visStatus();
b.lad(3); b.visStatus();
b.lad(5); b.visStatus(); // cap til 10
b.bruk(7.5); b.visStatus();
try { b.bruk(10); }
catch (IllegalStateException e) { System.out.println("OK – fanget: " + e.getMessage()); }
try { b.lad(-1); }
catch (IllegalArgumentException e) { System.out.println("OK – fanget: " + e.getMessage()); }
try { new Batteri(-5, 0); }
catch (IllegalArgumentException e) { System.out.println("OK – fanget: " + e.getMessage()); }
System.out.println("Alle tester passert.");
}
}
Identifiserte feil/unntak: (1) Bruk av mer energi enn tilgjengelig — IllegalStateException. (2) Negativ ladnings-/bruksverdi — IllegalArgumentException. (Unntak) Ugyldige verdier ved opprettelse — IllegalArgumentException. private final sikrer ekte innkapsling og at kapasiteten ikke kan endres etter opprettelsen.
Velferdsteknologi — fallsensorer, GPS-armbånd, automatiske medisindispensere — gir både muligheter og dilemmaer.
Fordeler: Økt selvstendighet og trygghet, raskere varsling, frigjør tid for helsepersonell til oppgaver som krever menneskelig nærvær.
Etiske dilemmaer:
Konklusjon: Velferdsteknologi bør innføres etter prinsippet «teknologi som verktøy, ikke erstatning». Krever solid juridisk rammeverk, opplæring av brukere og pleiere, og bevisst arbeidsdeling.
// Oppgave9.java — befolkningsutvikling 1945–2024
/* Forberedelse av datasettet:
* - Datasettet inneholder årlige tall for fødsler, innflyttinger og utflyttinger.
* - Vi konverterer numeriske kolonner til int (fjerner mellomrom som tusenskille).
* - Netto folkevekst beregnes som fødsler + innflyttinger − utflyttinger. */
import java.io.*;
import java.util.*;
public class Oppgave9 {
record AarsRad(int aar, int fodte, int inn, int ut) {
public int netto() { return fodte + inn - ut; }
}
private static List<AarsRad> lesData(String filsti) throws IOException {
List<AarsRad> result = new ArrayList<>();
try (BufferedReader br = new BufferedReader(new FileReader(filsti))) {
br.readLine(); // hopp over header
String linje;
while ((linje = br.readLine()) != null) {
String[] v = linje.split(";");
result.add(new AarsRad(
Integer.parseInt(v[0]),
Integer.parseInt(v[1].replace(" ", "")),
Integer.parseInt(v[2].replace(" ", "")),
Integer.parseInt(v[3].replace(" ", ""))
));
}
}
return result;
}
private static void visTabell(List<AarsRad> data) {
System.out.printf("%n%-6s%10s%10s%10s%12s%n", "År", "Fødte", "Inn", "Ut", "Netto");
System.out.println("-".repeat(48));
for (AarsRad r : data) {
System.out.printf("%-6d%,10d%,10d%,10d%,12d%n", r.aar(), r.fodte(), r.inn(), r.ut(), r.netto());
}
}
private static void tegnDiagram(List<AarsRad> data, String kolonne, int fra, int til) throws IOException {
List<AarsRad> valgt = data.stream().filter(r -> r.aar() >= fra && r.aar() <= til).toList();
if (valgt.isEmpty()) { System.out.println("Ingen data."); return; }
java.util.function.ToIntFunction<AarsRad> verdi = switch (kolonne) {
case "fødselstall" -> AarsRad::fodte;
case "innflyttinger" -> AarsRad::inn;
case "utflyttinger" -> AarsRad::ut;
case "netto folkevekst" -> AarsRad::netto;
default -> throw new IllegalArgumentException("Ukjent kolonne");
};
int bredde = 800, hoyde = 400, padding = 60;
int minV = valgt.stream().mapToInt(verdi).min().getAsInt();
int maksV = valgt.stream().mapToInt(verdi).max().getAsInt();
double xSteg = (double) (bredde - padding * 2) / (valgt.size() - 1);
StringBuilder punkter = new StringBuilder();
for (int i = 0; i < valgt.size(); i++) {
double x = padding + i * xSteg;
double y = hoyde - padding - ((double) (verdi.applyAsInt(valgt.get(i)) - minV) / Math.max(1, maksV - minV)) * (hoyde - padding * 2);
if (i > 0) punkter.append(" ");
punkter.append(String.format("%.1f,%.1f", x, y));
}
String svg = "<svg xmlns='http://www.w3.org/2000/svg' width='" + bredde + "' height='" + hoyde + "'>"
+ "<text x='" + bredde / 2 + "' y='30' text-anchor='middle' font-weight='bold'>" + kolonne + " " + fra + "–" + til + "</text>"
+ "<polyline points='" + punkter + "' fill='none' stroke='#1976D2' stroke-width='2'/></svg>";
String filnavn = "diagram_" + kolonne.replace(" ", "_") + "_" + fra + "_" + til + ".svg";
try (FileWriter fw = new FileWriter(filnavn)) { fw.write(svg); }
System.out.println("Diagram lagret som " + filnavn);
}
public static void main(String[] args) throws IOException {
List<AarsRad> data = lesData("befolkning.csv");
visTabell(data);
Scanner sc = new Scanner(System.in);
System.out.print("Kolonne (fødselstall / innflyttinger / utflyttinger / netto folkevekst): ");
String kolonne = sc.nextLine().trim().toLowerCase();
System.out.print("Fra år: ");
int fra = Integer.parseInt(sc.nextLine().trim());
System.out.print("Til år: ");
int til = Integer.parseInt(sc.nextLine().trim());
tegnDiagram(data, kolonne, fra, til);
}
}
// Virusspredning.java
import javax.swing.*;
import java.awt.*;
import java.util.Random;
enum Tilstand { FRISK, SMITTET, SYK, IMMUN, DOD }
class Person {
final int r, k;
Tilstand tilstand = Tilstand.FRISK;
int dager = 0;
Person(int r, int k) { this.r = r; this.k = k; }
void smitt() {
if (tilstand == Tilstand.FRISK) { tilstand = Tilstand.SMITTET; dager = 0; }
}
void nesteDag(Random rng) {
if (tilstand == Tilstand.FRISK || tilstand == Tilstand.IMMUN || tilstand == Tilstand.DOD) return;
dager++;
if (tilstand == Tilstand.SMITTET && dager >= 3) {
tilstand = Tilstand.SYK; dager = 0;
} else if (tilstand == Tilstand.SYK) {
if (rng.nextDouble() < 0.01) tilstand = Tilstand.DOD;
else if (dager >= 4) { tilstand = Tilstand.IMMUN; dager = 0; }
}
}
}
public class Virusspredning extends JPanel {
private static final int RUTER = 40, CELLE = 14;
private static final double SMITTE_PROB = 0.3;
private static final int SMITTE_RADIUS = 2;
private final Person[][] personer = new Person[RUTER][RUTER];
private final Random rng = new Random();
private int dag = 0;
private final JLabel statusLbl = new JLabel();
public Virusspredning() {
for (int r = 0; r < RUTER; r++)
for (int k = 0; k < RUTER; k++) personer[r][k] = new Person(r, k);
for (int i = 0; i < 5; i++)
personer[rng.nextInt(RUTER)][rng.nextInt(RUTER)].smitt();
setPreferredSize(new Dimension(RUTER * CELLE, RUTER * CELLE));
new Timer(200, e -> { enDag(); repaint(); oppdaterStatus(); }).start();
}
private void enDag() {
// 1) Smitt naboer av smittebærere
for (int r = 0; r < RUTER; r++)
for (int k = 0; k < RUTER; k++) {
Person p = personer[r][k];
if (p.tilstand == Tilstand.SMITTET || p.tilstand == Tilstand.SYK) {
for (int dr = -SMITTE_RADIUS; dr <= SMITTE_RADIUS; dr++)
for (int dk = -SMITTE_RADIUS; dk <= SMITTE_RADIUS; dk++) {
int nr = r + dr, nk = k + dk;
if ((dr != 0 || dk != 0) && nr >= 0 && nr < RUTER && nk >= 0 && nk < RUTER) {
if (rng.nextDouble() < SMITTE_PROB) personer[nr][nk].smitt();
}
}
}
}
// 2) Oppdater hver person
for (int r = 0; r < RUTER; r++)
for (int k = 0; k < RUTER; k++) personer[r][k].nesteDag(rng);
dag++;
}
private void oppdaterStatus() {
int[] teller = new int[Tilstand.values().length];
for (Person[] rad : personer) for (Person p : rad) teller[p.tilstand.ordinal()]++;
statusLbl.setText(String.format("Dag %d | Frisk %d Smittet %d Syk %d Immun %d Død %d",
dag, teller[0], teller[1], teller[2], teller[3], teller[4]));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (int r = 0; r < RUTER; r++)
for (int k = 0; k < RUTER; k++) {
g.setColor(switch (personer[r][k].tilstand) {
case FRISK -> Color.LIGHT_GRAY;
case SMITTET -> new Color(244, 143, 177);
case SYK -> new Color(229, 57, 53);
case IMMUN -> Color.DARK_GRAY;
case DOD -> Color.BLACK;
});
g.fillRect(k * CELLE, r * CELLE, CELLE, CELLE);
}
}
public static void main(String[] args) {
JFrame f = new JFrame("Virusspredning");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Virusspredning sim = new Virusspredning();
f.setLayout(new BorderLayout());
f.add(sim, BorderLayout.CENTER);
f.add(sim.statusLbl, BorderLayout.SOUTH);
f.pack(); f.setLocationRelativeTo(null); f.setVisible(true);
}
}
Person (Del 1 — tilstandsmaskin), Virusspredning (Del 2+3 — populasjon og visning).123456/
├── oppgave5b/Palindrom.java
├── oppgave6/Batteri.java + TestBatteri.java
├── oppgave9/Oppgave9.java + befolkning.csv
├── oppgave10/Virusspredning.java
└── README.md (Java 17+ for record + switch-expression)