Lab11

Forberedelser
Innlevering og automatisk retting

Repetisjon: oppgave 1

I filen uke_11_oppg_1.py skriv funksjonen dot_product(a, b) som regner ut prikk-produkuktet av av to like lange lister a og b (a[0] * b[0] + a[1] * b[1] + …)

print("Tester dot_product... ", end="")

assert(32 == dot_product([1, 2, 3], [4, 5, 6]))
assert(12 == dot_product([0, 6, 1], [400, 1, 6]))
assert(657 == dot_product([43, 6, 1], [15, 1, 6]))

print("OK")
Repetisjon: oppgave 2

I filen uke_11_oppg_2.py, skriv en funksjon som heter add_markers(filename) som åpner en fil med navn filename og lagrer innholdet til filen som én streng med >>> foran hver linje og <<< etter. Returner denne strengen. (Hvor det er linjeskift i tekstfilen skal det også være det i strengen.)

Eksempelkjøring med askeladden.txt:

add_markers(filename)

print("Tester add_markers... ", end="")
assert("""\
>>>Det var en gang en konge, og den kongen hadde hørt snakk om et skip \
som gikk like fort til lands som til vanns.<<<
>>>Så ville han også ha slikt et, og til den som kunne bygge det, lovte \
han ut kongsdattera og halve kongeriket, og det lyste han ut på kirkebakken \
ved alle kirkesogn over hele landet.<<<
>>>Det var mange som prøvde, kan du skjønne, for halve riket kunne være \
godt å ha, mente de vel, og kongsdattera kunne være bra å få i tillegg. Men \
ille gikk det med de fleste.<<<
""" == add_markers("askeladden.txt"))
print("OK")
Repetisjon: oppgave 3

Denne er en tilpasset fra Advent of Code 2021 Day 2 https://adventofcode.com/2021/day/2:

Gratulerer! Du lærer å styre en ubåt.

Ubåten kan ta en rekke kommandoer som for eksempel forward 1, down 2 eller up 3:

Legg merke til at siden du er på en ubåt, påvirker ned og opp dybden din, og dermed får de det motsatte resultatet av det du kanskje forventer (down -> økt dybde).

Ubåten har allerede en planlagt kurs (din input). Du bør nok finne ut hvor det går. For eksempel en fil som inneholder:

forward 5   
down 5
forward 8
up 3
down 8
forward 3

Din horisontale posisjon (x-koordinat) og dybde (y-koordinat) starter begge på 0. Trinnene ovenfor vil da endre dem som følger:

Etter å ha fulgt disse instruksjonene vil du ha en horisontal posisjon på 15 og en dybde på 10. (Å multiplisere disse sammen gir 150.)

Del A

I filen uke_11_oppg_3.py, skriv funksjonen sub_course_positions(path) som tar som input en .txt kurs-fil og returnerer et oppslagsverk som inneholder den horisontale posisjonen og dybden du vil ha etter å ha fulgt den planlagte kursen fra filen. Bruk forward og depth som nøklene til oppslagsverket du returnerer.

Eksempelkjøring med filen sub-path-sample.txt:

print("Tester sub_course_positions... ", end="")
result = sub_course_positions("sub-path-sample.txt")
assert({'forward': 15, 'depth': 10} == result)
print("OK")

Del B

I filen uke_11_oppg_3.py, skriv funksjonen sub_course(path) som ta som input en .txt kurs-fil, multipliserer den endelige horisontale posisjonen din med den endelige dybden, og returnerer en int. Bruk gjerne funksjonen fra forrige deloppgave som en hjelpemetode i denne funksjonen.

Eksempelkjøring med filen sub-path-sample.txt:

print("Tester sub_course... ", end="")
assert(150 == sub_course("sub-path-sample.txt"))
print("OK")
Repetisjon: oppgave 4

Del A

I filen uke_11_oppg_4.py skriv funksjonen simplified_pig_latin(word) som tar et engelsk ord som argument, og deretter konverterer ordet til forenklet pig-latin.

print("Tester simplified_pig_latin... ", end="")
assert("ellohay" == simplified_pig_latin("Hello"))
assert("imagehay" == simplified_pig_latin("Image"))
print("OK")

Del B

I filen uke_11_oppg_4.py skriv funksjonen sentence_to_simplified_pig_latin(sentence) med en streng-parameter som representerer en setning. Oversett setningen til forenklet pig-latin. Vi kan anta at setningen ikke inneholder spesielle symboler, men kun består av ord skilt med mellomrom.

sentence = "My name is Sylvia Lavrans"
expected_value ="ymay amenay ishay ylviasay avranslay"
print("Tester sentence_to_simplified_pig_latin... ", end="")
assert(expected_value == sentence_to_simplified_pig_latin(sentence))
print("OK")
Oppgave 5

I filen uke_11_oppg_5.py skal du bruke modulen decimals til å skrive et program som produserer en kvittering fra en butikk.

Koden din vil sannsynligvis ikke fungere hvis du ikke bruker decimals-modulen for å lagre tall, siden avrundingsfeil er veldig viktig å unngå, samtidig som vi skal bruke desimal-tall.

Ta utgangspunt i koden nedenfor.

def receipt_content(prices_filename, cash_register_filename):
    """Construct contents of a receipt of the cash register events,
    given the store prices."""

    # din kode her


def receipt(prices_filename, cash_register_filename):
    """Construct a receipt of the cash register events,
    given the store prices."""

    # get receipt content from receipt_content()
    purcases_returns, total, vat, payment, change = receipt_content(
        prices_filename, cash_register_filename
    )

    # the formatted lines of the receipt
    receipt_lines = [f"{'Nr.':>4}  {'Item':18}  {'Price':>10}"]

    for nr, item, price in purcases_returns:
        receipt_lines.append(f"{nr:4d}  {item:18}  {price:10.2f}")

    receipt_lines.append(f"Total: {total}")
    receipt_lines.append(f"Of which VAT: {vat:.2f}")
    receipt_lines.append(f"Payment: {payment}")
    receipt_lines.append(f"Change {change}")

    # add some dividers
    max_len = max(len(line) for line in receipt_lines)
    divider = "-" * max_len
    receipt_lines.insert(1, divider)
    receipt_lines.insert(-4, divider)
    receipt_lines.insert(-2, divider)

    return "\n".join(receipt_lines)

Du skal skrive koden til funksjonen receipt_content() som beregner inneholdet i kvitteringen utifra en fil med butikkens priser og en fil med hendelsene ved kassen. Argumentet prices_filename er en streng med navnet til filen som inneholder prisene. Argumentet cash_register_filename er en streng med navnet til filen som inneholder hendelsene ved kassen.

Funksjonen receipt_content() skal returnere en tupel som inneholder følgende (i denne rekkefølgen):

  1. En liste med tupler som inneholder (i følgende rekkefølge) antall, produkt og total pris, først for alle ting som har blitt kjøpt, i alfabetisk orden, og så for alle ting som har blitt returnert, i alfabetisk orden (se eksempelkvittering nedenfor). For de returnerte produktene blir det negative tall.
  2. Den totale prisen.
  3. Hvor mye av den totale prisen som er mva.
  4. Hvor mye som har blitt betalt.
  5. Hvor mye som blir betalt tilbake (her blir det ikke-positive tall).

Filen med butikkens priser er formattert slik som eksempelfilen prices.txt (som du kan bruke til å teste programmet ditt). Først står produkt, så semikolon (;), og så prisen. Dette er egentlig en CSV-fil som bruker semikolon som skilletegn.

Filen med hendelsene ved kassen er formattert slik som eksempelfilen cash_register.txt (som du kan bruke til å teste programmet ditt). Først står hva som skjer (kjøp, retur eller betaling), så semikolon (;), og så produkten/verdien. Dette er også egentlig en CSV-fil som bruker semikolon som skilletegn.

Funksjonen receipt() skal du ikke endre. Den bruker receipt_content() til å beregne inneholdet i kvitteringen og så produserer receipt() en pen kvittering utifra det innholdet. Du skal bare skrive kode til receipt_content().

Om din kode til receipt_content() er riktig så skal denne testen passere:

print("Tester receipt... ", end="")
expected_value = """\
 Nr.  Item                     Price
------------------------------------
   2  apple                    10.00
   1  chips                    24.30
   1  dish soap                26.20
   1  frozen pizza             54.40
   1  peanuts                  18.50
   1  toilet paper             34.00
   3  tomato                   30.00
  -1  pocket book            -149.00
  -1  toothpaste              -13.70
------------------------------------
Total: 34.70
Of which VAT: 6.94
------------------------------------
Payment: 100.00
Change -65.30"""
assert(expected_value == receipt("prices.txt", "cash_register.txt"))
print("OK")

  • Du må bruke biblioteket decimals for at beregningene skal bli riktige (prøv hvordan kvitteringen blir om du bruker float).

  • Decimals aksepterer både float og string for å lage decimals. Prøv hvordan kvitteringen blir om du gir decimals en float. Hvorfor skjer dette?

  • Det er mulig at betaling skjer flere ganger underveis ved kassen.

  • Du kan anta at alle betalinger ved kassen har positiv verdi.

  • Du kan anta at det ikke er noen feil i filene som inneholder prisene og hendelsene ved kassen.

  • Det er mulig at den totale prisen blir negativt (om kunden for eksempel bare returnerer ting).

  • Gitt en pris inklusive mva så multipliserer du prisen med 0.2 for å finne ut hvor mye av prisen som er mva.

  • Det kan være lurt å bruke dictionaries til prislisten og det som blitt kjøpt og det som blitt returnert.

  • Du må ikke skrive all kode innen funksjonen receipt_content(). Du kan dele opp koden i flere funksjoner på en måte du synes føles naturlig.

Oppgave 6

I filen uke_11_oppg_6.py skrive funksjonen add_numbers() som spør brukeren for heltall (så mange som brukeren vil) og så skal funksjonen skrive ut summen av alle tallene. Her må vi bruke try-except for at ikke programmet skal krasje om brukeren angir noe som ikke er et heltall. Det som kan lage en exception i dette tilfellet er om vi forsøker å konvertere en streng som ikke tilsvarer et heltall, til et heltall. Da får vi ValueError. Derfor må vi fange det med hjelp av except ValueError.

Eksempelkjøring:

add_numbers()

Give me an integer (q to quit):  29   
Give me an integer (q to quit):  2   
Give me an integer (q to quit):  43  
Give me an integer (q to quit):  1  
Give me an integer (q to quit):  a 
That was not an integer. Please try again. 
Give me an integer (q to quit):  3 
Give me an integer (q to quit):  % 
That was not an integer. Please try again. 
Give me an integer (q to quit):  q 
The sum is 78.
Oppgave 7

Du kan bruke matplotlib til å visualisere data. Les gjerne utforskning om pyplot parallelt med at du løser denne oppgaven.

I denne oppgaven skal vi ta utgangspunk i den følgende koden:

import matplotlib.pyplot as plt
from math import sin

# liste med x-verdier
xs = [n / 10 for n in range(101)]
# 2 ulike lister med y-verdier
ys_1 = [sin(x) for x in xs]
ys_2 = [3 * sin(x) for x in xs]

plt.plot(xs, ys_1, "-.r")
plt.plot(xs, ys_2, "--b")

# savefig lagrer filene
plt.savefig("test.png")
plt.savefig("test.pdf")

# interaktivt vindu
plt.show() # Hva skjer om vi ikke har med den raden: plt.show()?

Denne koden produserer følgende plot:

Denne koden produserer følgende plot:

Del A

I filen uke_11_oppg_7a.py endre på koden i eksempel overfor slik at grafene tegnes med en annen farge og stil. Du kan velge farge og stil selv. Filen du leverer er uke_11_oppg_7a.py og Du skal laste opp png-filen med plotten, med filnavnet uke_11_oppg_7a.png.

Del B

I filen uke_11_oppg_7b.py, ta koden fra eksemplet overfor og legg til minor ticks (undermerker) til x og y-aksen. Filen du leverer skal hete uke_11_oppg_7b.py og du skal også laste opp png-filen med plotten, med filnavnet uke_11_oppg_7b.png.

Eksempel figure:

Denne koden produserer følgende plot:

Del C

I filen uke_11_oppg_7c.py,ta koden fra eksemplet overfor og legg til en pil til det første interseksjon-punktet etter (\(0,0\)) med kommentaren: Første interseksjonen. Du trenger ikke å regne ut posisjonen i programmet, du kan estimere den. Husk å søke på matplotlib-dokumentasjonen. Lever også bildet i filen uke_11_oppg_7c.png

Eksempel figure:

Denne koden produserer følgende plot:
Oppgave 8

I filen Statistikk_Tilsyn_ar.csv finner du en oversikt over tilsyn gjennomført av Arbeidstilsynet fra 2015-2021, fordelt på år, fylke, hovednæring og virksomhetsstørrelse. Her finnes også oversikt over andelen tilsyn som har medført minst én reaksjon fra Arbeidstilsynet, og antallet reaksjoner totalt. En reaksjon er Arbeidstilsynets krav til virksomheter om å rette opp i brudd på arbeidsmiljøregelverket. Datasettet består av: Årstall (Ar), Antall gjennomførte tilsyn (AntallTilsyn), Antall gjennomførte tilsyn med reaksjon (AntallMedReaksjon). Data og beskrivelsen er hentet fra Felles Datakatalog

I filen uke_11_oppg_8.py skriv et program som leser inn datasettet og plotter det som vist i figuren nedenfor:

Denne koden produserer følgende plot:
Oppgave 9

Filen airport-codes.csv er en CSV-fil som inneholder en oversikt over mange flyplasser i verden.

I filen uke_11_oppg_9.py skal programmet ditt gjøre det følgende:

  1. Les data fra filen inn i passende datastrukturer (list / dict / …). Vi trenger kun informasjonen fra de 3 kolonnene som er nevnt ovenfor. Det er nyttig å splitte koordinatene i lengde og bredde allerede her.

  2. Bruk matplotlib for å plotte posisjonen til de ulike flyplassene på en kart. Bruk en liten prikk for de mellomstore flyplassene, og en større prikk for de store flyplassene. Velg en lys farge for prikkene.

  3. Bruk matplotlib.annotate(iata_code, (lengde, bredde)) i en løkke over alle store flyplassene for å skrive IATA-navnet på bildet.

  4. Sett inn en tittel og aksebeskrivelser.

  5. Avslutt med matplotlib.show() for å åpne interaktivt modus.

Eksempelkjøring:

Uten zoom:

Denne koden produserer følgende plot:

Zoomet inn (du trenger ikke å programmere dette, brukes kun interaktivt):

Denne koden produserer følgende plot: