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 2024
VG3

Løsningsforslag Informasjonsteknologi IT 2 – PythonVår 2024

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

Løsningsforslag – IT 2 Python Vår 2024

Eksamen: REA3049-PY | Semester: Vår 2024 | Varighet: 5 timer | Tema: OOP, pseudokode, Fibonacci, kalkulator, deepfakes, tidsbruk-datasett, Game of Life

Oppgave 1 – Hva er en klasse?

Oppgaven: Hvilket alternativ beskriver best en klasse i OOP?
Riktig svar: En klasse er en mal eller en prototype for objekter.

En klasse definerer hvilke egenskaper og metoder objektene skal ha — selve objektet er en instans av klassen. De andre alternativene blander begrepene: et objekt er en instans av klassen (ikke omvendt), en klasse er ikke en funksjon, og en klasse handler om mer enn bare datalagring.

Oppgave 2 – Arv og klasserelasjoner

Oppgaven: Klasse B arver fra klasse A. Hva er riktig betegnelse for B i forhold til A?
Riktig svar: B er en spesialisering av A.

Når B arver fra A, er B en mer spesialisert versjon av A — B utvider A med ny eller endret funksjonalitet. Generaliseringen går motsatt vei: A er generaliseringen av B (det felles, abstrakte). Termene «assosiert» og «avhengig» beskriver andre relasjonstyper og passer ikke for arv.

Oppgave 3 – Sporing av pseudokode

Oppgaven: b=4, c=5; FOR a fra 2 til 4: DISPLAY c, DECREMENT b, SET c TO c+b. Hva blir vist?
Riktig svar: 5 8 10
aDISPLAY cb etter DECREMENTc etter c+b
2535+3 = 8
3828+2 = 10
410110+1 = 11

Display-sekvensen blir 5, 8, 10. Verdien 11 vises ikke fordi DISPLAY skjer før de to siste operasjonene i siste iterasjon.

Oppgave 4 – Sortering av pseudokode

Oppgaven: Sorter linjene slik at programmet skriver ut "X er positivt/negativt/null og partall/oddetall" for X = -2, -1, 0, 1, 2.
Riktig rekkefølge:
SET num to -2
FOR hver num LESSER THAN OR EQUAL TO 2
  IF num LESSER THAN 0
    IF num % 2 EQUAL TO 0
      DISPLAY num + " er negativt og partall"
    ELSE
      DISPLAY num + " er negativt og oddetall"
    ENDIF
  ELSE IF num EQUAL TO 0
    DISPLAY num + " er null"
  ELSE
    IF num % 2 EQUAL TO 0
      DISPLAY num + " er positivt og partall"
    ELSE
      DISPLAY num + " er positivt og oddetall"
    ENDIF
  ENDIF
ENDFOR

Den ytre FOR-løkken iterer fra -2 til 2. Den ytre IF-strukturen skiller på fortegn (negativ / null / positiv), og de to indre IF-strukturene skiller på partall/oddetall innenfor hver gren. ENDIF-ene speiler nestingen.

Oppgave 5 – Fibonacci-tall

Oppgave 5a – Hva blir vist?

Oppgaven: n=10, a[0]=0, a[1]=1, a[i]=a[i-1]+a[i-2] for i=2..10. Hva blir DISPLAY a[10]?
Riktig svar: 55

Sekvensen er Fibonacci-tall: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55. a[10] = 55.

Oppgave 5b – Forklaring av algoritmen

Algoritmen genererer Fibonacci-tallene. Hvert nytt tall er summen av de to foregående, med startverdiene 0 og 1. Dette er en av de mest kjente sekvensene i matematikk og dukker opp i naturen (blomsterblader, kongleskjell, kanin-populasjoner). Algoritmen bruker iterativ tabulering: vi fyller opp en liste fra bunnen og opp, slik at vi unngår den eksponensielle tidsbruken man får ved naiv rekursjon. Tidskompleksiteten er O(n), plass O(n).

Oppgave 5c – De ti første Fibonacci-partall + flytskjema

# oppgave5c.py — første ti Fibonacci-partall


def fibonacci_partall(antall: int = 10) -> list[int]:
    a, b = 0, 1
    partall = []
    while len(partall) < antall:
        if a % 2 == 0:
            partall.append(a)
        a, b = b, a + b
    return partall


if __name__ == "__main__":
    print(fibonacci_partall())
    # [0, 2, 8, 34, 144, 610, 2584, 10946, 46368, 196418]
Flytskjema (oppsummert): Start → SET a=0, b=1, partall=tom liste → LOOP: er len(partall) < 10? → JA: er a % 2 == 0? → JA: legg a i partall → uansett: oppdater (a, b) ← (b, a+b) → tilbake til LOOP. NEI: SKRIV partall → Slutt.

Oppgave 6 – Kalkulator-klasse

# kalkulator.py


class KalkulatorFeil(Exception):
    """Egendefinert feil for kalkulator-operasjoner."""


class Kalkulator:
    def pluss(self, a: float, b: float) -> float:
        return a + b

    def minus(self, a: float, b: float) -> float:
        return a - b

    def gange(self, a: float, b: float) -> float:
        return a * b

    def dele(self, a: float, b: float) -> float:
        if b == 0:
            raise KalkulatorFeil("Kan ikke dele på null.")
        return a / b


def test_kalkulator() -> None:
    k = Kalkulator()
    assert k.pluss(2, 3) == 5
    assert k.minus(10, 4) == 6
    assert k.gange(3, 7) == 21
    assert k.dele(20, 4) == 5

    # Feil 1: Deling på null
    try:
        k.dele(10, 0)
    except KalkulatorFeil as e:
        print(f"OK – fanget: {e}")

    # Feil 2: Ikke-tall input (TypeError fra Python selv)
    try:
        k.pluss("to", 3)  # type: ignore[arg-type]
    except TypeError as e:
        print(f"OK – fanget TypeError: {e}")

    # Feil 3: Overflow (oppstår sjelden i Python pga. arbitrary precision int)
    # I språk med fast int-størrelse må man være obs på dette.

    print("Alle tester passert.")


if __name__ == "__main__":
    test_kalkulator()

Identifiserte feil/unntak: (1) ZeroDivisionError ved dele(x, 0) – håndtert med KalkulatorFeil. (2) TypeError hvis brukeren sender inn ikke-numeriske argumenter – Python kaster den selv. (3) OverflowError kan oppstå i andre språk; i Python støtter int arbitrær størrelse, men float kan gi inf ved svært store tall.

Oppgave 7 – Deepfakes (flervalg)

Spm.Riktig svarBegrunnelse
a) Hva er deepfakes?manipulerte medierDeepfakes er video, lyd eller bilde manipulert med KI/maskinlæring.
b) Mulig konsekvens?økt risiko for politisk manipuleringSom artikkelen viser (Sivertsen, Grut) – deepfakes brukes for å sverte politiske motstandere og spre desinformasjon.
c) Hvordan avsløre?ved å bruke teknikker fra kildekritikkSjekke avsender, søke etter samme video andre steder, vurdere sannsynlighet, lete etter visuelle artefakter.

Oppgave 8 – Deepfakes (drøfting)

Oppgave 8a – Avsløre og forebygge svindel

Hvordan avsløre: I jobbintervjuet kan jeg trekke fram konkrete teknikker for å avsløre deepfake-svindel: lytte etter unaturlige pauser, robotiske intonasjoner og lyd som ikke matcher leppene perfekt. På video bør man se etter ujevn belysning på ansiktet, kanter mellom ansikt og bakgrunn som «flimrer», unaturlige blunkemønstre og hender/ører som ikke ser riktige ut. Ved kritiske beslutninger – særlig økonomiske transaksjoner – bør man alltid verifisere gjennom en annen kanal: ringe tilbake på et kjent telefonnummer, sjekke gjennom intern chat, eller kreve fysisk møte.

Hva bedriften kan gjøre forebyggende:

  • Verifikasjonsrutine: Innfør obligatorisk «callback»-prosedyre for alle pengetransaksjoner over et terskelnivå – ingen overføring kun basert på et videomøte eller en e-post.
  • Kodeord: Etabler hemmelige fraser som ledergruppen bruker til å bekrefte identitet i sanntid.
  • Opplæring: Regelmessige treningsøkter om deepfakes og social engineering, gjerne med simulerte angrep.
  • Tekniske verktøy: Vurder deepfake-deteksjon i videomøteplattformene (Microsoft, Intel og andre tilbyr slike verktøy).
  • To-faktor-autentisering: Beslutninger som tidligere ble tatt på ett møte, krever nå godkjenning fra to ulike kanaler.
  • Hendelsesplan: Klar protokoll for hva man gjør ved mistanke om deepfake-svindel.

Oppgave 8b – Deepfakes i jobbsøkerprosessen

Bedriften beskriver en prosess der deepfakes brukes i intervjuet for å vurdere kandidatens reaksjoner. Dette reiser flere etiske spørsmål.

Argumenter for: Realistiske press-scenarier kan avsløre faglig modenhet og sosial kompetanse bedre enn et tradisjonelt intervju. I noen yrker (sikkerhet, ledelse, krisehåndtering) er nettopp evnen til å håndtere uventede situasjoner kritisk. Hvis prosessen er åpen og kandidaten har samtykket, kan det være et legitimt verktøy.

Argumenter mot:

  • Samtykke og transparens: Hvis kandidaten ikke vet at hen møter deepfakes, krenkes prinsippet om informert samtykke. Personvernforordningen (GDPR art. 5) krever rettferdig og åpen behandling av personopplysninger.
  • Bruk av kandidatens stemme/ansikt: Å lage deepfakes av kandidaten krever særskilt grunnlag etter GDPR art. 9 (biometriske data). Hvor lagres modellen? Slettes den etter intervjuet?
  • Strukturell skjevhet: Hvis simuleringene representerer enkelte kjønn, etnisiteter eller dialekter på bestemte måter, kan de forsterke fordommer i utvelgelsen.
  • Stress og psykologisk belastning: Deepfake-scenarier kan være ekstra belastende fordi de utfordrer kandidatens virkelighetsoppfatning. For personer med angstlidelser kan det være direkte skadelig.
  • Tillit: En ansatt som har vært utsatt for deepfake-vurdering, kan utvikle en grunnleggende mistillit til arbeidsgiveren.

Konklusjon: Deepfakes i ansettelsesprosesser kan ha legitime formål, men forutsetter eksplisitt samtykke, klare retningslinjer for sletting av biometriske data, og en grundig etisk evaluering før innføring. Uten disse rammene er ulempene større enn fordelene.

Oppgave 9 – Tidsbruk-datasett

Oppgaven: Datasett med tidsbruk på aktiviteter (timer.minutter) per kjønn. (a) tabell, (b) kjønnsfilter, (c) stolpe + sektordiagram.
# oppgave9.py — analyse av SSB-tidsbruk-datasett (2000)
import csv
import matplotlib.pyplot as plt
from pathlib import Path

DATAFIL = Path("tidsbruk_2000.csv")


def tid_til_minutter(verdi: str) -> int:
    """Konverter f.eks. '7.30' (7 timer, 30 min) til 450 minutter."""
    if not verdi:
        return 0
    timer, _, minutter = verdi.partition(".")
    return int(timer) * 60 + (int(minutter) if minutter else 0)


def minutter_til_tid(minutter: int) -> str:
    h, m = divmod(minutter, 60)
    return f"{h}.{m:02d}"


def les_data(filsti: Path = DATAFIL) -> list[dict]:
    with filsti.open(encoding="utf-8") as f:
        return list(csv.DictReader(f, delimiter=";"))


def vis_tabell(data: list[dict], kjonn: str = "Alle") -> None:
    rader = data if kjonn == "Alle" else [r for r in data if r["Kjønn"] == kjonn]
    print(f"\n{'Aktivitet':<28}{'Kjønn':<10}{'Tidsbruk':>10}")
    print("-" * 48)
    for r in rader:
        print(f"{r['Aktivitet']:<28}{r['Kjønn']:<10}{r['Tidsbruk']:>10}")


def stolpediagram(data: list[dict], kjonn: str) -> None:
    # Bruk kun aktivitetene (ikke kategoriene som er summer)
    rader = [r for r in data if r["Kjønn"] == kjonn and r.get("Type", "aktivitet") == "aktivitet"]
    navn = [r["Aktivitet"] for r in rader]
    minutter = [tid_til_minutter(r["Tidsbruk"]) for r in rader]

    plt.figure(figsize=(10, 6))
    plt.bar(navn, minutter, color="#1976D2")
    plt.title(f"Tidsbruk per aktivitet — {kjonn}")
    plt.ylabel("Minutter per dag")
    plt.xticks(rotation=45, ha="right")
    plt.tight_layout()
    plt.savefig(f"stolpe_{kjonn.lower()}.png", dpi=120)
    plt.show()


def sektordiagram(data: list[dict], kjonn: str) -> None:
    # Bruk kategoriene (med summer)
    rader = [r for r in data if r["Kjønn"] == kjonn and r.get("Type") == "kategori"]
    navn = [r["Aktivitet"] for r in rader]
    minutter = [tid_til_minutter(r["Tidsbruk"]) for r in rader]

    plt.figure(figsize=(8, 8))
    plt.pie(minutter, labels=navn, autopct="%1.1f%%", startangle=90)
    plt.title(f"Andel av døgnet per kategori — {kjonn}")
    plt.axis("equal")
    plt.tight_layout()
    plt.savefig(f"sektor_{kjonn.lower()}.png", dpi=120)
    plt.show()


def main() -> None:
    data = les_data()
    kjonn = input("Velg kjønn (Alle / Menn / Kvinner): ").strip().capitalize()
    if kjonn not in {"Alle", "Menn", "Kvinner"}:
        print("Ugyldig valg, viser Alle.")
        kjonn = "Alle"
    vis_tabell(data, kjonn)
    if kjonn != "Alle":
        stolpediagram(data, kjonn)
        sektordiagram(data, kjonn)


if __name__ == "__main__":
    main()
Forberedelse av datasettet: Format «timer.minutter» med punktum er ikke decimaltall. Funksjonen tid_til_minutter konverterer til minutter for korrekte beregninger og diagrammer. Skill mellom kategorier (med innrykk) og enkelt-aktiviteter ved å lese inn en ekstra kolonne Type, eller ved å filtrere på navn-prefiks.

Oppgave 10 – Game of Life

Oppgaven: Conways Game of Life på todimensjonalt rutenett. Klikkbar visning, automatisk neste generasjon, fire regler om underpopulasjon, overlevelse, overpopulasjon og reproduksjon.
# game_of_life.py — Conways Game of Life (objektorientert)
from __future__ import annotations
import random
import tkinter as tk

RUTER = 30
CELLE_PX = 18
START_LEVENDE_SANNSYNLIGHET = 1 / 3
TICK_MS = 200


class Celle:
    def __init__(self, rad: int, kol: int, levende: bool = False) -> None:
        self.rad = rad
        self.kol = kol
        self.levende = levende

    def veksle(self) -> None:
        self.levende = not self.levende


class Spillebrett:
    def __init__(self, rader: int = RUTER, kolonner: int = RUTER) -> None:
        self.rader = rader
        self.kolonner = kolonner
        self.celler: list[list[Celle]] = [
            [Celle(r, k, random.random() < START_LEVENDE_SANNSYNLIGHET)
             for k in range(kolonner)]
            for r in range(rader)
        ]

    def tom(self) -> None:
        for rad in self.celler:
            for c in rad:
                c.levende = False

    def _levende_naboer(self, c: Celle) -> int:
        antall = 0
        for dr in (-1, 0, 1):
            for dk in (-1, 0, 1):
                if dr == 0 and dk == 0:
                    continue
                r, k = c.rad + dr, c.kol + dk
                if 0 <= r < self.rader and 0 <= k < self.kolonner:
                    if self.celler[r][k].levende:
                        antall += 1
        return antall

    def neste_generasjon(self) -> None:
        # Beregn ny status for alle celler simultant.
        ny: list[list[bool]] = [[False] * self.kolonner for _ in range(self.rader)]
        for rad in self.celler:
            for c in rad:
                naboer = self._levende_naboer(c)
                if c.levende:
                    ny[c.rad][c.kol] = naboer in (2, 3)
                else:
                    ny[c.rad][c.kol] = naboer == 3

        for rad in self.celler:
            for c in rad:
                c.levende = ny[c.rad][c.kol]


class Spill:
    def __init__(self, brett: Spillebrett) -> None:
        self.brett = brett
        self.kjorer = False
        self.root = tk.Tk()
        self.root.title("Game of Life")
        self.canvas = tk.Canvas(
            self.root,
            width=brett.kolonner * CELLE_PX,
            height=brett.rader * CELLE_PX,
            bg="white", highlightthickness=0,
        )
        self.canvas.pack()
        self.canvas.bind("<Button-1>", self._klikk)

        knapper = tk.Frame(self.root)
        knapper.pack(pady=6)
        tk.Button(knapper, text="Start/Pause", command=self._toggle).pack(side="left", padx=4)
        tk.Button(knapper, text="Tøm", command=self._tom).pack(side="left", padx=4)
        tk.Button(knapper, text="Steg", command=self._ett_steg).pack(side="left", padx=4)

        self.celleids: dict[tuple[int, int], int] = {}
        self._tegn_init()

    def _tegn_init(self) -> None:
        for rad in self.brett.celler:
            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._farge(c), outline="#bbb",
                )
                self.celleids[(c.rad, c.kol)] = rid

    def _farge(self, c: Celle) -> str:
        return "#1a2b4a" if c.levende else "#fafafa"

    def _oppdater_tegning(self) -> None:
        for rad in self.brett.celler:
            for c in rad:
                self.canvas.itemconfig(self.celleids[(c.rad, c.kol)], fill=self._farge(c))

    def _klikk(self, event) -> None:
        kol = event.x // CELLE_PX
        rad = event.y // CELLE_PX
        if 0 <= rad < self.brett.rader and 0 <= kol < self.brett.kolonner:
            self.brett.celler[rad][kol].veksle()
            self._oppdater_tegning()

    def _toggle(self) -> None:
        self.kjorer = not self.kjorer
        if self.kjorer:
            self._loop()

    def _tom(self) -> None:
        self.kjorer = False
        self.brett.tom()
        self._oppdater_tegning()

    def _ett_steg(self) -> None:
        self.brett.neste_generasjon()
        self._oppdater_tegning()

    def _loop(self) -> None:
        if not self.kjorer:
            return
        self.brett.neste_generasjon()
        self._oppdater_tegning()
        self.root.after(TICK_MS, self._loop)

    def kjor(self) -> None:
        self.root.mainloop()


if __name__ == "__main__":
    Spill(Spillebrett()).kjor()
Hovedpunkter for sensor:
  • Modell og view skilt: Celle/Spillebrett håndterer regler; Spill-klassen håndterer Tkinter-GUI.
  • Synkron oppdatering (alle celler sjekkes mot samme generasjon før noen endres) – kritisk for korrekt Game of Life.
  • Tre operasjoner i del b: «Tøm» (alle døde), klikk på celle (veksler tilstand), «Steg»/«Start» (kjør neste generasjon).
  • De fire reglene implementeres kompakt i neste_generasjon som levende → naboer in (2, 3) og død → naboer == 3.

Oppgave 11 – Innlevering

Foreslått mappestruktur (kandidatnummer.zip):

123456/
├── oppgave5c/
│   ├── fibonacci_partall.py
│   └── flytskjema.pdf
├── oppgave6/
│   └── kalkulator.py
├── oppgave9/
│   ├── oppgave9.py
│   ├── tidsbruk_2000.csv
│   └── stolpe_menn.png
├── oppgave10/
│   └── game_of_life.py
└── README.md
Laster…
Nyere løsning
Høst 2024
Eldre løsning
Høst 2023

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