Eksamenssett logo
eksamenssett.noTren målrettet
  • Ungdomsskole/VGS
  • Høyskole
  • Ressurser
  • Skolenyttig
  • Forum
eksamenssett.noTren målrettet

Komplett samling av eksamensoppgaver og løsninger for norsk skole.

Om ossFAQPersonvernVilkårAngrerettKontakt

© 2025 Eksamenssett.no · Alle rettigheter forbeholdt

Innholdet er utviklet med AI-verktøy og kvalitetssikres kontinuerlig. Slik jobber vi med kvalitet →

Eksamenssett.no eies og drives av Studenthjelp Privatundervisning AS

Eksamenssett logo
eksamenssett.noTren målrettet
  • Ungdomsskole/VGS
  • Høyskole
  • Ressurser
  • Skolenyttig
  • Forum
eksamenssett.noTren målrettet

Komplett samling av eksamensoppgaver og løsninger for norsk skole.

Om ossFAQPersonvernVilkårAngrerettKontakt

© 2025 Eksamenssett.no · Alle rettigheter forbeholdt

Innholdet er utviklet med AI-verktøy og kvalitetssikres kontinuerlig. Slik jobber vi med kvalitet →

Eksamenssett.no eies og drives av Studenthjelp Privatundervisning AS

Eksamenssett logo
eksamenssett.noTren målrettet
  • Ungdomsskole/VGS
  • Høyskole
  • Ressurser
  • Skolenyttig
  • Forum
eksamenssett.noTren målrettet

Komplett samling av eksamensoppgaver og løsninger for norsk skole.

Om ossFAQPersonvernVilkårAngrerettKontakt

© 2025 Eksamenssett.no · Alle rettigheter forbeholdt

Innholdet er utviklet med AI-verktøy og kvalitetssikres kontinuerlig. Slik jobber vi med kvalitet →

Eksamenssett.no eies og drives av Studenthjelp Privatundervisning AS

Eksamenssett logo
eksamenssett.noTren målrettet
  • Ungdomsskole/VGS
  • Høyskole
  • Ressurser
  • Skolenyttig
  • Forum
eksamenssett.noTren målrettet

Komplett samling av eksamensoppgaver og løsninger for norsk skole.

Om ossFAQPersonvernVilkårAngrerettKontakt

© 2025 Eksamenssett.no · Alle rettigheter forbeholdt

Innholdet er utviklet med AI-verktøy og kvalitetssikres kontinuerlig. Slik jobber vi med kvalitet →

Eksamenssett.no eies og drives av Studenthjelp Privatundervisning AS

Eksamenssett logo
eksamenssett.noTren målrettet
  • Ungdomsskole/VGS
  • Høyskole
  • Ressurser
  • Skolenyttig
  • Forum
  1. Hjem
  2. Informasjonsteknologi
  3. IT 2 – Python
  4. Løsning Vår 2025
VG3

Løsningsforslag Informasjonsteknologi IT 2 – PythonVår 2025

Se eksamensoppgaven
Høst 2024Eldre
Om løsningsforslaget: Dette er et veiledende løsningsforslag laget av eksamenssett.no for REA3049-PY Vår 2025. Vi gir korrekte svar på flervalgsoppgavene (1–4) med begrunnelse, fullstendig kode for programmeringsoppgavene (5b, 6, 8, 9), og eksempelsvar på drøftingsoppgaven (7). Husk at det finnes flere gode måter å løse de åpne oppgavene på.

Løsningsforslag – IT 2 Python Vår 2025

Eksamen: REA3049-PY | Semester: Vår 2025 | Varighet: 5 timer | Tema: Pseudokode, OOP, Caesar-chiffer, bibliotek, friluftsdatasett, skogbrann-simulering

Oppgave 1 – Pseudokode (TrommeLom)

Oppgaven: Hva blir resultatet av sjekkTall(6)? Pseudokoden bygger en streng der tall delelig med både 2 og 3 erstattes med "TrommeLom", bare 2 med "Tromm", bare 3 med "Lom", og resten beholdes som tall.
Riktig svar: 1 Tromm Lom Tromm 5 TrommeLom

Sporing trinn for trinn

ii % 2i % 3Hvilken gren?Lagt til
111else"1 "
202else if i%2==0"Tromm "
310else if i%3==0"Lom "
401else if i%2==0"Tromm "
512else"5 "
600første if (begge)"TrommeLom "

Sammensetningen blir "1 Tromm Lom Tromm 5 TrommeLom". Dette er en variant av det klassiske FizzBuzz-problemet.

Oppgave 2 – Klasserelasjoner i OOM

Oppgaven: Objekter av en klasse eksisterer og brukes kun innenfor objekter av en annen klasse. Hvilken relasjon er dette?
Riktig svar: komposisjon

Begrunnelse: Komposisjon er en sterk «inneholder»-relasjon (whole–part) der den indre delens livssyklus er bundet til den ytre helheten. Når den ytre delen ødelegges, ødelegges også de indre delene. Dette skiller komposisjon fra:

  • Assosiasjon: Generell «vet om»-relasjon, uavhengige livssykluser.
  • Aggregering (svakere variant av komposisjon): Inneholder, men delene kan eksistere alene.
  • Generalisering: «Er en»-relasjon (arv) – ikke om livssyklus.
  • Avhengighet: Klassen bruker en annen midlertidig (f.eks. som parameter), men «eier» den ikke.

Oppgave 3 – OOP-prinsipp: samme metodenavn i super- og subklasse

Oppgaven: Hvilket prinsipp gjør at metoder kan ha samme navn i superklasse og subklasse og likevel kalles riktig på objektene?
Riktig svar: polymorfisme

Begrunnelse: Polymorfisme («mange former») betyr at samme metodenavn kan ha forskjellig oppførsel avhengig av objektets faktiske type. Når du kaller dyr.lyd() på et Hund-objekt, kjøres Hund.lyd(); på et Katt-objekt kjøres Katt.lyd(). De andre prinsippene:

  • Abstraksjon: Skjuler detaljer ved å fokusere på det vesentlige.
  • Innkapsling: Skjuler interne data og eksponerer kun et grensesnitt.
  • Arv: Selve mekanismen som lar subklassen «overstyre» metoden – men polymorfisme er prinsippet som beskriver kallet.

Oppgave 4 – OOP-prinsipp: skjule interne detaljer

Oppgaven: Hvilket prinsipp innebærer å skille mellom grensesnittet og de interne detaljene til et objekt?
Riktig svar: innkapsling

Begrunnelse: Innkapsling (encapsulation) handler nettopp om å skjule den interne implementasjonen og kun eksponere et veldefinert grensesnitt utad. I Python uttrykkes dette gjerne med understrek-prefiks (_navn for «privat», __navn for name-mangling) og getter/setter-metoder eller @property. Innkapsling gir robusthet: implementasjonen kan endres uten å bryte koden som bruker objektet.

Oppgave 5 – Caesar-chiffer

Oppgave 5a – Forklaring

Oppgaven: Forklar hva algoritmen behandleTekst(tekst, n) gjør.

Algoritmen er et enkelt Caesar-chiffer tilpasset det norske alfabetet. Den tar inn en tekst og et heltall n, og forskyver hver bokstav n plasser framover i et alfabet på 29 tegn (a–å). Bokstaver som ikke er bokstaver – mellomrom, tall, tegnsetting – blir værende uendret.

Manipuleringsfunksjonen finner posisjonen til hver bokstav i alfabettstrengen, legger til n, og bruker modulo 29 ((posisjon + n) % 29) slik at vi «pakker rundt» når vi går forbi å. Eksempel: med n = 3 blir a til d, og å blir til c (den «runder» tilbake til starten).

Merk en svakhet i pseudokoden: alfabetstrengen inneholder både små og store bokstaver, men store bokstaver står på posisjonene 29–57. Modulo 29 vil derfor «kollapse» store og små bokstaver til samme indeksposisjon. I en god implementasjon bør man behandle store og små bokstaver hver for seg, og bevare opprinnelig store/små bokstaver i resultatet.

Oppgave 5b – Implementasjon i Python

Oppgaven: Implementer algoritmen i Python. Programmet skal ta inn en tekst og et heltall n og vise resultatet.
# oppgave5b.py — Caesar-chiffer for norsk alfabet

ALFABET_SMA = "abcdefghijklmnopqrstuvwxyzæøå"
ALFABET_STORE = ALFABET_SMA.upper()
ALFABET_LENGDE = len(ALFABET_SMA)  # 29


def manipuler_bokstav(bokstav: str, n: int) -> str:
    """Forskyv én bokstav n plasser framover, med wrap-around."""
    if bokstav in ALFABET_SMA:
        ny_pos = (ALFABET_SMA.index(bokstav) + n) % ALFABET_LENGDE
        return ALFABET_SMA[ny_pos]
    if bokstav in ALFABET_STORE:
        ny_pos = (ALFABET_STORE.index(bokstav) + n) % ALFABET_LENGDE
        return ALFABET_STORE[ny_pos]
    return bokstav  # tall, mellomrom, tegnsetting beholdes


def behandle_tekst(tekst: str, n: int) -> str:
    return "".join(manipuler_bokstav(b, n) for b in tekst)


def main() -> None:
    tekst = input("Skriv inn tekst: ")
    while True:
        try:
            n = int(input("Forskyvning n (heltall): "))
            break
        except ValueError:
            print("Ugyldig — skriv et heltall.")

    resultat = behandle_tekst(tekst, n)
    print(f"Original:  {tekst}")
    print(f"Kryptert:  {resultat}")
    print(f"Dekryptert verifisering: {behandle_tekst(resultat, -n)}")


if __name__ == "__main__":
    main()
Eksempel-kjøring:
Skriv inn tekst: Hei på deg
Forskyvning n (heltall): 3
Original: Hei på deg
Kryptert: Khl rb gho
Dekryptert verifisering: Hei på deg

Oppgave 6 – Bibliotek (Bok og Låner)

Oppgave 6a – Klassediagram

Oppgaven: Lag klassediagram med riktig relasjon mellom Bok og Låner.

Relasjonen er en assosiasjon (toveis): en Bok kan være utlånt til én Låner, og en Låner kan ha referanser til flere Bok-objekter. Begge klassene eksisterer uavhengig av hverandre (en bok kan stå urørt i hylla; en låner kan finnes uten å ha lånt noe).

+----------------------+              +-------------------------+
|        Bok           |              |        Låner            |
+----------------------+              +-------------------------+
| - tittel: str        |    0..*      | - lånerID: int          |
| - forfatter: str     |<-------------| - lånteBøker: [Bok]     |
| - utlånt: Låner|None |   0..1       +-------------------------+
+----------------------+              | + lånBok(b: Bok)        |
| + visInfo()          |              | + leverTilbakeBok(b)    |
+----------------------+              +-------------------------+

Kardinalitet: én låner kan låne 0 eller flere bøker (0..*); én bok er utlånt til 0 eller én låner (0..1).

Oppgave 6b – Implementasjon av klassene

# bibliotek.py — implementasjon av Bok og Låner


class BibliotekFeil(Exception):
    """Base-unntak for bibliotek-relaterte feil."""


class Bok:
    def __init__(self, tittel: str, forfatter: str) -> None:
        self.tittel = tittel
        self.forfatter = forfatter
        self.utlant: "Laner | None" = None

    def vis_info(self) -> None:
        status = (
            f"utlånt til {self.utlant.navn} (ID {self.utlant.laner_id})"
            if self.utlant
            else "tilgjengelig"
        )
        print(f"'{self.tittel}' av {self.forfatter} — {status}")

    def __repr__(self) -> str:
        return f"Bok({self.tittel!r}, {self.forfatter!r})"


class Laner:
    def __init__(self, laner_id: int, navn: str) -> None:
        self.laner_id = laner_id
        self.navn = navn
        self.lante_boker: list[Bok] = []

    def lan_bok(self, bok: Bok) -> None:
        if bok.utlant is not None:
            raise BibliotekFeil(
                f"'{bok.tittel}' er allerede utlånt til {bok.utlant.navn}."
            )
        bok.utlant = self
        self.lante_boker.append(bok)

    def lever_tilbake_bok(self, bok: Bok) -> None:
        if bok not in self.lante_boker:
            raise BibliotekFeil(
                f"{self.navn} har ikke lånt '{bok.tittel}'."
            )
        bok.utlant = None
        self.lante_boker.remove(bok)

    def __repr__(self) -> str:
        return f"Laner({self.laner_id}, {self.navn!r}, {len(self.lante_boker)} bøker)"

Oppgave 6c – Testprogram

# test_bibliotek.py
from bibliotek import Bok, Laner, BibliotekFeil


def test_bibliotek() -> None:
    bok1 = Bok("Sofies verden", "Jostein Gaarder")
    bok2 = Bok("Naiv. Super.", "Erlend Loe")
    bok3 = Bok("Beatles", "Lars Saabye Christensen")
    emma = Laner(1, "Emma")
    ola = Laner(2, "Ola")

    # 1) Lån ut
    emma.lan_bok(bok1)
    emma.lan_bok(bok2)
    bok1.vis_info()  # 'Sofies verden' av Jostein Gaarder — utlånt til Emma (ID 1)
    assert bok1 in emma.lante_boker
    assert bok1.utlant is emma

    # 2) Lever tilbake
    emma.lever_tilbake_bok(bok1)
    bok1.vis_info()  # tilgjengelig
    assert bok1 not in emma.lante_boker
    assert bok1.utlant is None

    # 3) Allerede utlånt — skal kaste feil
    ola.lan_bok(bok3)
    try:
        emma.lan_bok(bok3)
    except BibliotekFeil as e:
        print(f"OK — fanget feil: {e}")
    else:
        raise AssertionError("Skulle kastet BibliotekFeil")

    # 4) Lever tilbake bok som ikke er lånt — skal kaste feil
    try:
        emma.lever_tilbake_bok(bok3)
    except BibliotekFeil as e:
        print(f"OK — fanget feil: {e}")

    print("Alle tester passert.")


if __name__ == "__main__":
    test_bibliotek()

Oppgave 6d – Feilhåndtering

Programmet håndterer to typer feil ved å kaste det egendefinerte unntaket BibliotekFeil:

  • Forsøk på å låne en bok som allerede er utlånt
  • Forsøk på å levere tilbake en bok som låneren ikke har lånt

Ved å definere et eget unntak (i stedet for å bruke ValueError eller Exception) kan kallende kode skille bibliotek-feil fra andre feil med except BibliotekFeil. Testene over bekrefter at både den positive flyten (lån, tilbakelevering) og feilstiene fungerer som forventet.

Oppgave 7 – VR-briller og sosial angst (etiske dilemmaer)

Oppgaven: Drøft to etiske dilemmaer ved bruk av VR-teknologi for å behandle sosial angst hos ungdom (Emma, 16 år).

Innledning

VR-baserte behandlingsverktøy som det Emma deltar i, gir ny mulighet for trygg eksponering, men reiser også etiske spørsmål som bør drøftes før teknologien tas i utbredt bruk. Jeg vil her diskutere to sentrale dilemmaer: (1) personvern og datasikkerhet, og (2) overføringsverdi versus teknologiavhengighet.

Dilemma 1: Personvern og biometri

VR-headset registrerer mer enn bare bilde og lyd: blikkretning, hodebevegelser, hudkonduktans i tilkoblede sensorer og pulsmålinger. For en ungdom med sosial angst betyr det at sensitive data om frykt-respons og kroppslige reaksjoner samles inn. Etter GDPR (artikkel 9) regnes dette som spesielt beskyttede helseopplysninger. Hvem eier dataene – sykehuset, leverandøren av VR-utstyret, eller Emma selv? Brukes de bare til behandling, eller også til å trene maskinlæringsmodeller som kan kommersialiseres? At Emma er mindreårig (16) skjerper kravet til reelt informert samtykke fra både henne og foresatte. Et sterkt argument for bruk er at behandlingen kan hjelpe henne ut av en alvorlig lidelse; mot taler at innsamlede biometriske data, hvis de lekker eller misbrukes, kan følge henne resten av livet.

Dilemma 2: Overføringsverdi versus teknologiavhengighet

Casen sier eksplisitt at Emma «føler seg tryggere i virtuelle situasjoner, men er usikker på hvordan hun vil håndtere virkelige presentasjoner». Dette peker på et grunnleggende spørsmål: fungerer VR-eksponeringen som en stillas mot virkelig mestring, eller blir den et trygt unndrag der man slipper å konfrontere det skarpere ubehaget i en ekte klasse? Forskning på eksponeringsterapi viser at habituering må generaliseres til reelle situasjoner for at angsten skal varig avta. Hvis Emma blir avhengig av VR-rommet, kan teknologien forsterke unngåelsesatferd – det motsatte av målet. Etisk er det viktig at behandlingen designes med en tydelig overgang fra virtuell til reell øvelse, og at framgang måles i hverdagslige situasjoner, ikke kun i simuleringen.

Andre relevante hensyn

Tidlig innsats er normalt et gode – sosial angst rammer ofte i 14–16-årsalderen og blir lettere å behandle tidlig. Men man bør være varsom med å patologisere normal sjenanse hos ungdom. Like tilgang er et tredje moment: VR-utstyr koster penger og krever teknisk kompetanse; en behandlingsform som bare når elever på enkelte skoler skaper sosial ulikhet i helsehjelp.

Konklusjon

VR-teknologi for behandling av sosial angst er etisk forsvarlig dersom den kombineres med streng datakontroll, reell overføring til ekte situasjoner, og likeverdig tilgang. Uten disse rammene risikerer man både personverninngrep og at teknologien blir et komfortabelt unngåelsesrom som forsterker problemet den skulle løse.

Oppgave 8 – Friluftsaktiviteter (datasett)

Oppgaven: Les inn datasett med friluftsaktiviteter fordelt på fylker (1000 personer per fylke). Lag program som (a) viser totalt antall per aktivitet, (b) lar bruker velge fylke og viser sortert liste med antall + prosent, (c) viser topp 3 i et stolpediagram.

Oppgave 8a – Total per aktivitet

# oppgave8.py — friluftsaktiviteter
import csv
from pathlib import Path

DATAFIL = Path("friluftsaktiviteter_2024.csv")


def les_data(filsti: Path = DATAFIL) -> list[dict[str, str]]:
    """Les CSV-fil og returner liste av rader (én per fylke)."""
    with filsti.open(encoding="utf-8") as f:
        leser = csv.DictReader(f, delimiter=";")
        return list(leser)


def aktivitetsnavn(data: list[dict]) -> list[str]:
    """Alle kolonnenavn unntatt 'Fylke' regnes som aktiviteter."""
    return [k for k in data[0].keys() if k != "Fylke"]


def totaler_per_aktivitet(data: list[dict]) -> dict[str, int]:
    aktiviteter = aktivitetsnavn(data)
    return {a: sum(int(rad[a]) for rad in data) for a in aktiviteter}


def vis_totaltabell(totaler: dict[str, int]) -> None:
    print(f"\n{'Aktivitet':<28}{'Total':>10}")
    print("-" * 38)
    for aktivitet, total in sorted(totaler.items(), key=lambda x: x[1], reverse=True):
        print(f"{aktivitet:<28}{total:>10,}".replace(",", " "))

Oppgave 8b – Sortert per fylke (antall + prosent)

def vis_fylke(data: list[dict], fylke: str) -> None:
    rad = next((r for r in data if r["Fylke"].lower() == fylke.lower()), None)
    if rad is None:
        print(f"Fylket '{fylke}' ble ikke funnet i datasettet.")
        return

    aktiviteter = aktivitetsnavn(data)
    par = sorted(((a, int(rad[a])) for a in aktiviteter), key=lambda x: x[1])
    total = sum(antall for _, antall in par) or 1  # unngå deling på 0

    print(f"\nAktiviteter i {rad['Fylke']} (sortert stigende):")
    print(f"{'Aktivitet':<28}{'Antall':>8}{'Prosent':>10}")
    print("-" * 46)
    for aktivitet, antall in par:
        print(f"{aktivitet:<28}{antall:>8}{antall/total*100:>9.1f} %")

Oppgave 8c – Topp 3 som stolpediagram

import matplotlib.pyplot as plt


def topp_tre_diagram(data: list[dict], fylke: str) -> None:
    rad = next((r for r in data if r["Fylke"].lower() == fylke.lower()), None)
    if rad is None:
        print(f"Fylket '{fylke}' ble ikke funnet.")
        return

    aktiviteter = aktivitetsnavn(data)
    topp3 = sorted(
        ((a, int(rad[a])) for a in aktiviteter),
        key=lambda x: x[1], reverse=True,
    )[:3]

    navn = [n for n, _ in topp3]
    verdier = [v for _, v in topp3]

    plt.figure(figsize=(8, 5))
    plt.bar(navn, verdier, color=["#2196F3", "#4CAF50", "#FFC107"])
    plt.title(f"Topp 3 friluftsaktiviteter i {rad['Fylke']} (2024)")
    plt.ylabel("Antall deltakere")
    plt.xticks(rotation=15)
    plt.tight_layout()
    plt.savefig(f"topp3_{rad['Fylke'].replace(' ', '_')}.png", dpi=120)
    plt.show()


def main() -> None:
    data = les_data()
    vis_totaltabell(totaler_per_aktivitet(data))
    fylke = input("\nVelg et fylke (f.eks. Oslo): ").strip()
    vis_fylke(data, fylke)
    topp_tre_diagram(data, fylke)


if __name__ == "__main__":
    main()
Mappestruktur ved innlevering (oppgave 8):
oppgave8/
├── oppgave8.py
├── friluftsaktiviteter_2024.csv
└── topp3_Oslo.png  (eksempelutdata)

Oppgave 9 – Skogbrann-simulering

Oppgaven: Lag en objektorientert simulering på et 40×40 rutenett. Hver celle kan være tom, ha et tre, eller brenne. Trær vokser med sannsynlighet ~0,3 % per tomme celle per trinn. Lyn slår ned i et tre med sannsynlighet ~0,03 % og starter brann. Brannen sprer seg til naboruter med trær.
# skogbrann.py — objektorientert simulering av skogbrann
from __future__ import annotations
import random
import tkinter as tk
from enum import Enum
from dataclasses import dataclass

# --- Konstanter ---
RUTER = 40
CELLE_PX = 14
P_VOKS = 0.003      # 0,3 % sjanse for at en tom celle blir et tre
P_LYN = 0.0003      # 0,03 % sjanse for at et tre treffes av lyn
TICK_NORMAL_MS = 100  # normal vekstrate
TICK_BRANN_MS = 40    # raskere mens det brenner


class Tilstand(Enum):
    TOM = "tom"
    TRE = "tre"
    BRANN = "brann"


@dataclass
class Celle:
    rad: int
    kol: int
    tilstand: Tilstand = Tilstand.TOM


class Skog:
    def __init__(self, rader: int = RUTER, kolonner: int = RUTER) -> None:
        self.rader = rader
        self.kolonner = kolonner
        self.rutenett: list[list[Celle]] = [
            [Celle(r, k) for k in range(kolonner)]
            for r in range(rader)
        ]

    def naboer(self, c: Celle) -> list[Celle]:
        """4-naboer (von Neumann). Bytt til 8 hvis diagonal-spredning ønskes."""
        retninger = [(-1, 0), (1, 0), (0, -1), (0, 1)]
        resultat = []
        for dr, dk in retninger:
            r, k = c.rad + dr, c.kol + dk
            if 0 <= r < self.rader and 0 <= k < self.kolonner:
                resultat.append(self.rutenett[r][k])
        return resultat

    def brenner_noe(self) -> bool:
        return any(c.tilstand == Tilstand.BRANN for rad in self.rutenett for c in rad)

    def tick(self) -> None:
        # Beregn neste tilstand uten å forstyrre nåværende.
        ny: list[list[Tilstand]] = [
            [c.tilstand for c in rad] for rad in self.rutenett
        ]
        det_brenner = self.brenner_noe()

        for rad in self.rutenett:
            for c in rad:
                if c.tilstand == Tilstand.BRANN:
                    # Brennende celle blir tom; antenner naboer som er trær
                    ny[c.rad][c.kol] = Tilstand.TOM
                    for n in self.naboer(c):
                        if n.tilstand == Tilstand.TRE:
                            ny[n.rad][n.kol] = Tilstand.BRANN
                elif c.tilstand == Tilstand.TRE:
                    # Lyn kan slå ned (uavhengig av om brann pågår)
                    if random.random() < P_LYN:
                        ny[c.rad][c.kol] = Tilstand.BRANN
                elif c.tilstand == Tilstand.TOM and not det_brenner:
                    # Trær vokser bare når det IKKE brenner — tidsskala-kravet
                    if random.random() < P_VOKS:
                        ny[c.rad][c.kol] = Tilstand.TRE

        for rad in self.rutenett:
            for c in rad:
                c.tilstand = ny[c.rad][c.kol]


class SkogVisning:
    FARGER = {
        Tilstand.TOM: "#e8d7b9",    # sandfarget bakgrunn
        Tilstand.TRE: "#2e7d32",    # grønn
        Tilstand.BRANN: "#e53935",  # rød
    }

    def __init__(self, skog: Skog) -> None:
        self.skog = skog
        self.root = tk.Tk()
        self.root.title("Skogbrann-simulering")
        self.canvas = tk.Canvas(
            self.root,
            width=skog.kolonner * CELLE_PX,
            height=skog.rader * CELLE_PX,
            bg=self.FARGER[Tilstand.TOM],
            highlightthickness=0,
        )
        self.canvas.pack()
        self.celleids: dict[tuple[int, int], int] = {}
        self._tegn_init()

    def _tegn_init(self) -> None:
        for rad in self.skog.rutenett:
            for c in rad:
                x1, y1 = c.kol * CELLE_PX, c.rad * CELLE_PX
                rid = self.canvas.create_rectangle(
                    x1, y1, x1 + CELLE_PX, y1 + CELLE_PX,
                    fill=self.FARGER[c.tilstand], outline="",
                )
                self.celleids[(c.rad, c.kol)] = rid

    def oppdater(self) -> None:
        for rad in self.skog.rutenett:
            for c in rad:
                self.canvas.itemconfig(
                    self.celleids[(c.rad, c.kol)],
                    fill=self.FARGER[c.tilstand],
                )

    def kjor(self) -> None:
        def tick():
            self.skog.tick()
            self.oppdater()
            forsinkelse = TICK_BRANN_MS if self.skog.brenner_noe() else TICK_NORMAL_MS
            self.root.after(forsinkelse, tick)
        self.root.after(TICK_NORMAL_MS, tick)
        self.root.mainloop()


def main() -> None:
    skog = Skog()
    SkogVisning(skog).kjor()


if __name__ == "__main__":
    main()
Designvalg som er verdt å trekke fram for sensor:
  • Klassefordeling: Skog håndterer simuleringslogikken (modell), SkogVisning håndterer Tkinter (view) — separation of concerns.
  • Synkron oppdatering: Vi beregner ny-rutenettet før vi skriver tilbake, slik at en celle som blir antent i samme trinn ikke smitter videre i samme tick (ellers «løper» brannen tvers over kartet på ett trinn).
  • Tidsskala: Trær vokser kun når det ikke brenner (kravet i oppgaven), og brann-ticken er raskere enn vekst-ticken slik at brannen ser dramatisk ut.
  • Naboer: 4-naboer (von Neumann) gir mer realistisk spredning. Bytt til 8 (Moore) hvis du vil at brannen kan hoppe diagonalt.
  • Sannsynlighetene ligger som konstanter øverst og kan justeres uten å rote i logikken.

Oppgave 10 – Innlevering

Oppgaven: Last opp ett komprimert arkiv (.zip/.tar/.7z/.gz/.rar) med svarene på 5b, 6, 8 og 9.

Foreslått mappestruktur (kandidatnummer som arkivnavn, f.eks. 123456.zip):

123456/
├── oppgave5b/
│   └── caesar_chiffer.py
├── oppgave6/
│   ├── bibliotek.py
│   └── test_bibliotek.py
├── oppgave8/
│   ├── oppgave8.py
│   ├── friluftsaktiviteter_2024.csv
│   └── topp3_Oslo.png
├── oppgave9/
│   └── skogbrann.py
└── README.md   (kort om hvordan man kjører hver fil)
Sjekkliste før innlevering:
  • Alle filer kjører uten endringer i filnavn/stier hos sensor
  • Ingen navn eller brukernavn i kode eller metadata (eksamen er anonym)
  • Datasett (CSV/JSON) ligger sammen med oppgave 8-koden
  • Kommentarer i koden forklarer designvalg
  • Arkivet er < 500 MB
Laster…
Eldre løsning
Høst 2024

Alle løsningsforslag for IT 2 – Python

Vår 2025Høst 2024Vår 2024Høst 2023
Se eksamensoppgaven
eksamenssett.noTren målrettet

Komplett samling av eksamensoppgaver og løsninger for norsk skole.

Om ossFAQPersonvernVilkårAngrerettKontakt

© 2025 Eksamenssett.no · Alle rettigheter forbeholdt

Innholdet er utviklet med AI-verktøy og kvalitetssikres kontinuerlig. Slik jobber vi med kvalitet →

Eksamenssett.no eies og drives av Studenthjelp Privatundervisning AS