Lab9

Forberedelser
Innlevering og automatisk retting

Repetisjon: oppgave 1

Tone ser etter drømmejobben, men har noen begrensninger.

I filen uke_09_oppg_1.py, skrive funksjonen will_work(city, salary) som tar inn sted og lønn som parametere og returnerer True hvis Tone ville tatt jobben, False hvis ikke.

print("Tester will_work...", end="")
assert(will_work('Bergen', 400_000))
assert(not will_work('Bergen', 399_999))
assert(not will_work('Kristiansand', 590_000))
assert(will_work('Bodø', 900_000))
assert(will_work('Tromsø', 600_000))
assert(not will_work('Bodø', 899_999))
assert(will_work('Verdensrommet', 10))
print("OK")
Repetisjon: oppgave 2

I filen uke_09_oppg_2.py skriv en funksjon mase_for_is() som spør brukeren om den kan få en is. Funksjonen maser på brukeren ved å si «Vær så snill, si ja!» helt til hen sier «ja». Da sier programmet «Tusen takk!» og avslutter.

Eksempelkjøring:

mase_for_is()

Kan jeg få en is?
Nei!   
Vær så snill, si ja!
Nope
Vær så snill, si ja!
Jeg vil ikke det!
Vær så snill, si ja!
ja
Tusen takk!

Se løsningsforslaget til oppgave 3 på lab 3.

Repetisjon: oppgave 3

I filen uke_09_oppg_3.py skriv en ikke-destruktiv funksjon rotate(grid) som tar et rutenett som parameter og returnerer en rotert kopi slik at første kolonne blir første rad, andre kolonne blir til andre rad, og så videre.

print("Tester rotate... ", end="")
# Test 1
a = [
    ["a", "c"],
    ["b", "d"]
]
assert([
    ["a", "b"],
    ["c", "d"],
] == rotate(a))

# Test 2
a = [
    [1, 4],
    [2, 5],
    [3, 6],
]
assert([
    [1, 2, 3],
    [4, 5, 6],
] == rotate(a))
# Sjekk at a ikke er mutert
assert([[1, 4], [2, 5], [3, 6]] == a)
print("OK")

  • Begynn med å opprette en ny tom liste (den du skal returnere på slutten av funksjonen).

  • Les i kursnotatene om flerdimensjonelle lister om hvordan du kan hente ut en kolonne fra en 2d-liste.

  • For hver kolonne i rutenettet, hent ut kolonnen og legg den til i resultatlisten.


Oppgave 4

Del A

I filen uke_09_oppg_4.py, lag funksjonen shopping_list_to_dict med en parameter shopping_list_as_string som er en streng som innholder en handleliste. Funksjonen skal returnere et oppslagsverk med varer som nøkler og antall som verdier. Du kan anta at strengen består av flere linjer, hvor hver linje (som ikke er tom) består av først et heltall, deretter et mellomrom, og deretter navnet på varen (uten mellomrom).

print("Tester shopping_list_to_dict... ", end="")
shopping_list_as_string = """\
2 brød
3 pizza
10 poteter
1 kaffe
1 ost
14 epler
"""
shopping_list_as_dict = shopping_list_to_dict(shopping_list_as_string)
assert({
    "brød": 2,
    "pizza": 3,
    "poteter": 10,
    "kaffe": 1,
    "ost": 1,
    "epler": 14,
} == shopping_list_as_dict)
print("OK")

  • Les kursnotater om oppslagsverk.

  • Begynn med å opprette et tomt oppslagsverk (som skal returneres på slutten av funksjonen).

  • Bruk en løkke over hver av linjene i strengen; les kursnotater om løkker over strenger for å finne en egnet måte å gå gjennom linjene i strengen på.

  • Inne i løkken, sjekk at linjen ikke er den tomme strengen (hvis den er det, bruk f. eks. continue for å hoppe over denne linjen og fortsette med neste).

  • Inne i løkken, bruk linjen num, food_name = line.split(" ") for å dele opp strengen i to biter; da blir num en variabel som holder en streng med antallet (f. eks. "2"), og food_name blir en streng som inneholder navnet på maten (f. eks. "brød").

  • I oppslagsverket, legg til food_name som en nøkkel med verdien int(num).

Del B

I filen uke_09_oppg_4.py, lag funksjonen shopping_list_file_to_dict med en parameter path som er en streng som representerer en filsti til en fil som inneholder en handleliste.

For å teste funksjonen, last ned filen handleliste.txt og legg den i samme mappe programmet kjøres fra (husk at dette ikke nødvendigvis er samme mappe hvor uke_09_oppg_4.py ligger med mindre du har åpnet VSCode i den samme mappen).

print("Tester shopping_list_file_to_dict... ", end="")
shopping_list_as_dict = shopping_list_file_to_dict("handleliste.txt")
assert({
    "brød": 2,
    "pizza": 3,
    "poteter": 10,
    "kaffe": 1,
    "ost": 1,
    "epler": 13,
} == shopping_list_as_dict)
print("OK")

Denne funksjonen består av 1-3 linjer med kode avhengig av hvor kompakt du skriver.

  • Begynn med å lese inn hele filen som en enkelt streng (du kan kopiere og kalle på funksjonen read_file fra kursnotater om lesing og skriving til fil).

  • Bruk denne strengen og kall på funksjonen du skrev i forrige deloppgave.

  • Returner resultatet.

Oppgave 5

Collatz-sekvensen er definert som følger:

  1. Start med et tall \(n\)
  2. Hvis \(n\) er jevnt så er neste tall \(\frac{n}{2}\), ellers så er neste tall \(3n +1\)
  3. Repeter steg \(2\) med det nye tallet helt til du får \(1\). Da er du ferdig.

Her er en funksjon som beregner Collatz-sekvensen gitt en en startverdi \(n\):

def collatz_sequence(n):
    sequence = [n]
    while n > 1:
        if n % 2 == 0:
            n = n // 2
        else:
            n = 3 * n + 1
        sequence.append(n)
    return sequence

I filen uke_09_oppg_5.py, skriv en funksjon som heter collect_collatz(a, b) som bruker collatz_sequence -funksjonen gitt over til å beregne Collatz-sekvensen for alle tall fra og med \(a\) og opp til (men ikke inkludert) \(b\). Sekvensene skal returneres i form av et oppslagsverk hvor startverdiene er nøkler.

print("Tester collect_collatz... ", end="")
assert({
    1: [1],
    2: [2, 1], 
    3: [3, 10, 5, 16, 8, 4, 2, 1],
} == collect_collatz(1, 4))
assert({
    3: [3, 10, 5, 16, 8, 4, 2, 1],
    4: [4, 2, 1],
    5: [5, 16, 8, 4, 2, 1],
} == collect_collatz(3, 6))
print("OK")

  • Begynn med å opprette et tomt oppslagsverk (som du skal returnere på slutten av funksjonen, når det er ferdig fylt opp med nøkler og verdier).

  • Bruk en løkke for å gå gjennom alle tall fra og med \(a\) opp til men ikke inkludert \(b\) (se kursnotater om løkker).

  • Inne i løkken: gjør et kall til collatz_sequence -metoden med iteranden som argument. Oppdater oppslagsverket slik at iteranden blir en ny nøkkel med returverdien fra kallet til collatz_sequence som verdi.

Oppgave 6

I denne oppgaven skal vi undersøke slektskapet mellom oppslagsverk og lister. En nøkkel spiller på mange måter samme rolle for et oppslagsverk som en indeks gjør for en liste.

Del A

I filen uke_09_oppg_6.py, skriv funksjonen key_value_getter(d) som tar inn en dictionary d, og skriver ut til skjermen nøklene, verdiene og nøkkel/verdi-par. Eksempelkjøring:

key_value_getter({
  "monday": 0,
  "tuesday": 0.7,
  "wednesday": 0,
  "thursday": 4.7,
  "friday": 10
})

skal gi utskriften:

Dictionary keys:
monday
tuesday
wednesday
thursday
friday

Dictionary values:
0
0.7
0
4.7
10

Dictionary keys/value:
monday 0
tuesday 0.7
wednesday 0
thursday 4.7
friday 10

Del B

I filen uke_09_oppg_6.py, skriv funksjonen index_value_getter(a) som tar inn en liste a og skriver ut til skjermen indeksene, verdiene og indeks/verdi -parene. Eksempelkjøring:

index_value_getter([7.0, 8.0, 10.0, 9.0, 10.0])

skal gi utskriften:

List indices:
0
1
2
3
4

List values:
7.0
8.0
10.0
9.0
10.0

List indices/value:
0 7.0
1 8.0
2 10.0
3 9.0
4 10.0

Oppgave 7

I denne oppgaven skal vi bruke et oppslagsverk som igjen inneholder oppslagsverk med informasjon om værstasjoner:

weather_stations = {
    "Bergen": {
        "Wind speed": 3.6,
        "Wind direction": "northeast",
        "Precipitation": 5.2,
        "Device": "WeatherMaster500"
    },
    "Trondheim": {
        "Wind speed": 8.2,
        "Wind direction": "northwest",
        "Precipitation": 0.2,
        "Device": "ClimateDiscoverer3000"
    },
    "Svalbard": {
        "Wind speed": 7.5,
        "Wind direction": "southwest",
        "Precipitation": 1.1,
        "Device": "WeatherFinder5.0"
    },
}

I filen uke_09_oppg_7.py, lag et funksjonen weather_report(weather_stations, city) som tar in en bynavn og skriver ut værrapporten for denne byen. Eksempelkjøring:

weather_report(weather_stations, "Bergen")

skal skrive ut:

The weather in Bergen:
The wind speed is 3.6m/s in the northeast direction and the precipitation is 5.2mm.
The measurement was done using the WeatherMaster500 weather station.
Oppgave 8

I filen uke_09_oppg_8.py skriv en funksjon som heter word_comparison() og som tar to ord (strenger) som argumenter. Funksjonen skal så sammenligne bokstavene i ordene og returnere en dictionary som sier hvilke bokstaver finnes i begge ordene, hvilke bokstaver som finnes i kun det første ordet og hvilke bokstaver som finnes i kun det andre ordet (som set). Husk at rekkefølgen ikke spiller noen rolle i mengder:

print("Tester word_comparison... ", end="")
assert({
  "In common": {"e", "c"},
  "Unique to first word": {"r", "u", "t", "p", "o", "m"},
  "Unique to second word": {"s", "i", "n"},
} == word_comparison("computer", "science"))
print("OK")
Oppgave 9

Fantasy Game Inventory fra boken https://automatetheboringstuff.com/2e/chapter5/

Du lager et fantasy-videospill. Datastrukturen for å modellere spillerens beholdning skal være en dictionary hvor nøklene er strings som beskriver tingene i beholdningen, og verdiene er integers som forteller hvor mange av hver ting som spilleren har. For eksempel, verdiene i dictionary {'rope': 1, 'torch': 6, 'gold coin': 42, 'dagger': 1, 'arrow': 12} betyr at spilleren har 1 rope, 6 torches, 42 gold coins, etc.

I filen uke_09_oppg_9.py og skriv funksjonen displayInventory() som tar inn en dictionary av beholdningen og returneres totalt antall i formaten i eksempelkjøringen nedenfor.

stuff = {"rope": 1, "torch": 6, "gold coin": 42, "dagger": 1, "arrow": 12}
print(displayInventory(stuff))
Inventory:
1 rope
6 torch
42 gold coin
1 dagger
12 arrow
62

Funksjonen skal i dette eksemplet returnere tallet \(62\) (den siste linjen)

Oppgave 10

Dragon Hoard fra boken https://automatetheboringstuff.com/2e/chapter5/

Skatten til en beseiret drage er representert som en liste med strenger som dette: dragonLoot = ['gold coin', 'dagger', 'gold coin', 'gold coin', 'ruby']

I filen uke_09_oppg_10.py skrive funksjonen som heter addToInventory(inventory, addedItems), hvor inventory parameteren er en dictionarien av spillerens beholdning og addedItems parameteren er en liste som f.eks dragonLoot.

addToInventory() funksjonen skal returnere en dictionary som representerer den oppdaterte beholdningen. Merk at listen over tilleggsartikler kan inneholde flere av samme element.

Om du kaller displayInventory() etter å ha oppdatert beholdingen med addToInventory() funksjonen skal du få ut likt som nedenfor:

inv = {"gold coin": 42, "rope": 1}
dragonLoot = ["gold coin", "dagger", "gold coin", "gold coin", "ruby"]
inv = addToInventory(inv, dragonLoot)
print(displayInventory(inv))
Inventory:
45 gold coin
1 rope
1 dagger
1 ruby
48

og displayInventory() skal returnere tallet \(48\).

Oppgaver på Kattis (frivillige)

For å lese input i oppgaven «adding words»:

import sys
all_input_as_string = sys.stdin.read()

  • Bruk ett oppslagsverk som går fra ord til verdi, og ett annet som går fra verdi til ord.
  • Når den samme variabelen blir definert på nytt, husk å slette gammel nøkkel fra verdi-til-ord -oppslagsverket

I filen kattis-recount.py lag en funksjon count(votes) votes vil da være en string hvor alle navn er skilt med newline. Funksjonen skal returne navnet til den med flest stemmer, hvis flere personer har like mange stemmer skal den returne Runoff!. Funksjonen skal kun lese frem til første linje som inneholder 3 stjerner (***).

Data for recount oppgaven.

data_1 = "Penny Franklin\nMarti Graham\nConnie Froggatt\nJoseph Ivers\nConnie Froggatt\nPenny Franklin\nConnie Froggatt\nBruce Stanger\nConnie Froggatt\nBarbara Skinner\nBarbara Skinner\n***"

data_2 = "Penny Franklin\nConnie Froggatt\nBarbara Skinner\nConnie Froggatt\nJose Antonio Gomez-Iglesias\nConnie Froggatt\nBruce Stanger\nBarbara Skinner\nBarbara Skinner\n***"

data_3 = "Penny Franklin\nConnie Froggatt\nBarbara Skinner\nConnie Froggatt\nJose Antonio Gomez-Iglesias\n***\nConnie Froggatt\nBruce Stanger\nBarbara Skinner\nBarbara Skinner\n***"

Output

Connie Froggatt
Runoff!
Connie Froggatt