Marvin - steg 2
Programmering och problemlösning i Python. Strukturera koden i egna funktioner.
Förkunskaper
Section titled “Förkunskaper”Du har jobbat allt material i “kmom03”.
Lösningar som använder konstruktionerna list/dict comprehension eller lambda funktioner godkänns inte i denna kurs.
Varje uppgift ska lösas med grundläggande Python konstruktioner som vi går igenom i kursen. Egenskapade funktioner får användas först i kmom03 och listor får användas först i kmom04.
-
Kopiera din Marvin från föregående kursmoment och utgå från den koden.
Terminal window # Flytta till kurskatalogencd srccp -ri kmom02/marvin1/marvin.py kmom03/marvin2/cd kmom03/marvin2 -
Strukturera koden:
- Byt namn filen
marvin.py
tillmain.py
och skapa filenmarvin1.py
. main.py
ska innehålla koden för att starta ditt program och while-loopen som som utgör menyn.- Skapa funktionen
main
och lägg all kod som var i filen imain()
funktionen. - Din main fil skall sedan kalla på
main
funktion i blocket för villkoretif __name__ == "__main__"
som du lägger längst ner imain.py
.
- Byt namn filen
-
Koden för dina menyval ska nu flyttas till olika funktioner i
marvin1.py
. Med “koden för menyval” menas koden som utgör funktionaliteten för ett menyval, t.ex.marvin1.py elif choice == "1":# koden mellan kommentarerna här. Startname = input("What is your name? ")print("\nMarvin says:\n")print(f"Hello {name} - your awesomeness!")print("What can I do you for?!")# Slutelif choice == "2":Importera
marvin1.py
imain.py
och strukturera om koden för de gamla menyvalen så att de läggs i en varsin funktion, med nedanstående namn. Dessa funktionerna har itester
utöver sitt menyval som tag också “marvin1” som tag.- Menyval 1 -
greet
- Menyval 2 -
celsius_to_fahrenheit
- Menyval 3 -
points_to_grade
- Menyval 4 -
compare_numbers
- Menyval 5 -
validate_ssn
- Menyval 6 -
robber_language
Om du har gjort några av extrauppgifterna från föregående kursmoment så kan du döpa dem till ett valfritt namn.
Till exempel för menyval 1 blir det.
main.py elif choice == "1":marvin1.greet()marvin1.py def greet():name = input("What is your name? ")print("\nMarvin says:\n")print(f"Hello {name} - your awesomeness!")print("What can I do you for?!")Alla
input()
ochprint()
som används i menyvalen skall ligga i funktionen för menyvalet och inte i main funktionen.
Det är OK att bryta ut din kod till flera mindre funktioner så länge de används i funktionen som efterfrågas.- Tags:
struct
. Det går att användastruct
som tag itester <sökväg>/kmom03 --tags=struct
för att köra testerna som kollar att man har rätt filer på rätt plats.
- Menyval 1 -
-
Skapa filen
marvin2.py
. Koden för de nya menyvalen nedanför ska du skriva imarvin2.py
. Importera filen imain.py
. -
För alla nya menyval ska dina
input
anrop ligga i “main.py” filen och du ska skicka dem som argument till de specifika menyvalsfunktionerna. Varje input-anrop för ett menyval motsvarar ett argument till funktionen. Funktionerna ska också returnera resultatet så att utskriften görs imain.py
. Exempel:main.py ...elif choice == "8":string = input("Enter a string to randomize: ")print(randomize_string(string)) -
Menyval 7 -
create_ssn
: Skapa de fyra sista siffrorna till ett födelsedatum. Skapa ett nytt menyval där Marvin ber om en sträng som innehåller ett födelse datum, t.ex."910813"
. Din funktion ska skapa de fyra sista siffrorna till det,"910813-NNNN"
. För att skapa dem, använda random modulen och slumpa fram de tre första siffrorna. Använd sen Luhnalgoritmen för att räkna ut den fjärde. Den funkar nästa på samma sätt som i menyval 5.Algoritmen funkar på så sätt att varannan siffra multipliceras med 2 och 1, med start på första siffran i personnumret. Om något tal vid multiplikationen blir större än 9 ersätts det talet med dess siffersumma. Därefter summeras alla tal och här skiljer sig funktionen från menyval 5. Sista siffran erhålls genom att summan subtraheras från närmaste högre tiotal. Exempel med
811218-987
:8 1 1 2 1 8 9 8 7* 2 1 2 1 2 1 2 1 2-------------------------^ ^ ^ ^ ^ ^ ^ ^16 1 2 2 2 8 18 8 14Vilket blir
1 + 6 + 1 + 2 + 2 + 2 + 8 + 1 + 8 + 8 + 1 + 4 = 44
,50 - 44 = 6
. Personnummret blir då811218-9876
.För att subtrahera från närmsta tiotal kan man använda modulo operatorn,
%
.Som du läst finns det funktionalitet som är samma mellan menyval 5 och 7. Därför ska du skapa en ny funktion som används i koden för menyval 5 och 7. Skapa
create_ssn
som tar emot födelsedatumet och skapar tre siffror. Skapa sencalculate_luhna_sum
som tar emot en sträng med födelsedatumet och de tre siffrorna, utan-
,"811218987"
. Funktionen ska räkna ut summan och returnera den,44
. Icreate_ssn
använd summan och räkna ut sista siffran och returnera hela personnumret, med-
,811218-9876
.Uppdatera sen koden för menyval 5 så att du använder
calculate_luhna_sum
i den koden också, för att räkna ut summan som ska kollas om den är delbar med 10. Kolla om talet är delbart med 10 i menyval 5 funktionen, inte icalculate_luhna_sum
. Genom att återanvända funktioner på flera ställen kan vi få mer DRY kod.Exempel:
input: "910813" output: "910813-2201".Eftersom tre siffror slumpas fram kommer ni inte få samma sista som i exemplet. Men om ni använder det i menyval 5 ska det vara ett giltigt personnummer
-
Menyval 8 -
randomize_string
: Kasta om bokstäver. Marvin ska be dig skriva in ett ord som sedan slumpmässigt kastas om. Funktionenrandomize_string
ska bara returnera det nya slumpade ordet, inte ha med<orginal sträng> -->
. Svaret ska sedan skrivas ut i formatet<orginal sträng> --> <slumpad sträng>
, frånmain.py
. Lösningen ska vara case-sensitive, med andra ordA != a
.Tips, använd random modulen. Notera dock att ni fortfarande inte får använda listor och flera av funktionerna i random modulen returnerar listor. De funktionerna får ni inte använda.
input: "Hej" output: "Hej --> jHe"input: "Borde inte bli samma igen" output: "Borde inte bli samma igen --> eel gn rtm dBmibo saiiane" -
Koden ska validera med Ruff.
Terminal window # Kommandot funkar oavsett var du står i ditt repouv run ruff check -
Testerna som finns ska passera.
Terminal window # om du står i katalogen src/kmom03/marvin2 i ditt repouv run tester ../../../tests/kmom03/marvin2/# om du står i root katalogen i ditt repouv run tester tests/kmom03/marvin2/
Rätta eventuella fel som dyker upp och publicera igen. När det ser grönt ut så är du klar.
Extrauppgift
Section titled “Extrauppgift”-
Menyval b1 -
has_strings
: Gör så Marvin kan ta emot fyra strängar, den första strängen ska jämföras med de andra tre. Kolla om den första strängen börjar med den andra, innehåller den tredje och slutar med den sista. Lösningen ska vara case-sensitive, med andra ordA != a
. Tips, startswith(), endswith() Exempel:input: "anagram"input: "ana"input: "agr"input: "am" output: "Match"input: "isogram"input: "is"input: "gra"input: "m" output: "Match"input: "Palindrom"input: "par"input: "ind"input: "rom" output: "No match" -
Menyval b2 -
ssn_extended
: I Sverige finns det två juridiska kön, kvinna och man, som registreras för varje individ vid födsel. Det påverkar den näst sista siffran i ens personnummer. Marvin ska kunna generera de 4 sista siffrorna i ett personnummer där tredje siffran i den avslutande delen av personnumret (NNXN) ska anpassas efter könet på personen. Siffran ska fortfarande slumpas men med tilläggskravet att om det är en kvinna ska den tredje siffra vara jämn och om det är en man ska den istället vara udda.
Ändra parameterlistan tillcreate_ssn
så att det förutom födelsedatum (som är första parametern) även har en andra parameter för kön med default-argumentetNone
. Denna parameter har värdet"M"
eller"m"
om födelsedatumet tillhör en man och"K"
eller"k"
om det tillhör en kvinna. Observera att all inmatning sker i main.Exempel:
input: "910813"input: "M" output: "910813-5531".input: "661204"input: "K" output: "661204-9247".Eftersom tre siffror slumpas fram (med kravet på udda/jämnt beroende på kön för tredje siffran) kommer ni inte få samma sista som i exemplet. Men om ni använder det i menyval 5 ska det vara ett giltigt personnummer
-
Menyval B3 -
find_all_indexes
: Hitta alla index. Marvin ska be om två strängar, där den andra strängen är en del-sträng av den första. Funktionen ska returnera en kommaseparerad sträng med alla indexplatser där den andra strängen finns med i den första. Det ska inte vara ett kommatecken på slutet av strängen. Om strängen som skickas in som andra argument inte finns i första argumentet ska funktionen returnera en tom sträng.Använd sträng funktionen funktionen index() för att hitta indexplatser, notera att
index()
returnerar bara ett index åt gången, så även om en sträng finns med på två ställen returneras bara den första. För att komma runt detta och hitta alla index behöver ni anropaindex()
flera gånger och skicka med ett extra argument,start
.start
markera vilken index position funktionen ska börja leta från. Notera också attindex
funktionen lyfter ettValueError
om en söksträngen inte finns. Ni ska använda er av try-except i er funktion för att förhindra programmet från att krascha när det inträffar.Exempel:
input: "axaaczaa44aa4", "a" output: "0,2,3,6,7,10,11"input: "axaaczaa33aa3", "aa" output: "2,6,10"input: "axaaczaa55aa5", "y" output: ""
Övrigt
Section titled “Övrigt”Här finns övriga saker som är bra att tänka på.
- Använd
uv run tester tests/kmom03/marvin2 --tags <menyval>
för att bara köra testerna för menyvalet du jobbar med. Du kan användauv run tester tests/kmom03/marvin2 -s
för att se alla taggar som finns och vilka tester de kör.- Varje menyval har samma tag som dess siffra för valet.
- Gör många och små commits i ditt git repo, du kan ha ungefär 5-10 commits för en sådan här uppgift.