Göm menyn

1. Komma igång med programmering

1.1 Inledning

OBS! Innan du börjar med labbövningarna, backa ett steg och titta igenom Regler för redovisning och komplettering. Kom tillbaka hit när du har gjort det.

Syftet med denna första laborationsomgång är att introducera programmering i allmänhet och programspråket Python synnerhet. I början är det extra viktigt att du lägger ner mycket tid på att göra övningar för att snabbt skaffa dig en uppfattning om hur Python fungerar. Programmering är ett hantverk som man lär sig bäst genom att skriva många program, snarare än genom att enbart läsa en bok. Du bör försöka göra så många som möjligt av de övningar som finns i laborationen, men för att bli godkänd räcker det att du redovisar de två uppgifter som finns i slutet av laborationen. Notera att även testningsbitarna i uppgifterna ska genomföras.

Denna labb behandlar material från kapitel 1-7 i studiematerialet och de tre första kapitlen i läroboken.

OBS! Om du vill öva mer på detta, finns extraövningar till labb 1 att tillgå.

1.2 Inledande övningar

Se till att du har tillgång till en Python-interpretator, antingen genom att starta den från kommandoraden med python3 eller genom att öppna en Python-fil i Emacs och köra Switch to interpreter i Python-menyn.

Övning 101 Skriv in följande rader vid Python-prompten, en i taget. Försök förutsäga vad Python kommer att svara innan du trycker Enter.

4 - 2 2 * 5.0 (2 - 4) * 5.0 10 / 2 11 / 3 a = 2 * 3 a - 2.0

Övning 102 Kopiera funktionen find_root från kapitlet satser och uttryck i studiematerialet. Ändra funktionen så att den kan skriva ut en valfri multiplikationstabell istället. Tanken är att funktionen ska fungera så här:

>>> table() This program prints out a multiplication table. Enter a number: 7 0 * 7 = 0 1 * 7 = 7 2 * 7 = 14 3 * 7 = 21 4 * 7 = 28 5 * 7 = 35 6 * 7 = 42 7 * 7 = 49 8 * 7 = 56 9 * 7 = 63

1.3 Definition av funktioner

Vi ska nu öva på att definiera egna funktioner som returnerar värden, d.v.s. skickar tillbaka information till oss som anropat dem. Om man ska vara noga så ligger det egentligen i själva begreppet funktion att den faktiskt ska returnera något, men vi säger ibland "funktion" även om kod som inte skickar tillbaka något.

>>> def plus(x, y): ... return x + y ... >>> plus(2, 5) 7

I ovanstående exempel har vi definierat en funktion plus. Den tar två argument som vi har kallat x och y. Det som händer inne i funktionen är att vi beräknar summan av dessa och med hjälp av konstruktionen return skickar tillbaka summan till den som anropat funktionen. Vi provar att anropa funktionen och skickar in två argment. När vi trycker Enter får vi se returvärdet.

Glöm inte bort att använda return i slutet av funktionen. Prova gärna att ta bort det och se vad som händer.

I det här avsnittet vill vi ha enkla och rena funktioner som fungerar i princip som matematiska funktioner. Det innebär att vi inte använder någon form av inmatning eller utskrift. Vi tar in indata via argumenten och skickar ut resultat som returvärde, inget annat.

Övning 103 Definiera en funktion average med två argument x och y som returnerar medelvärdet av x och y.

>>> average(2, 4) 3.0

Vägval med if

En av de vanligaste sakerna man behöver kunna göra i ett datorprogram är att göra jämförelser och baserat på resultatet välja bland olika alternativ. Detta kan vi göra med en if-sats:

>>> a=45 >>> if a == 45: ... print("yes") ... else: ... print("no") ... yes

Det är viktigt att komma ihåg att både raden med if och raden med else ska avslutas med kolon, samt att raderna som uttrycker vad som ska hända i de två alternativen är indenterade. Notera också att vi använder jämförelseoperatorn == för att testa om två saker är lika. Det är inte samma sak som tilldelning med bara ett =. Denna konstruktion kan vara användbar i följande övningar.

Övning 104 Definiera en funktion max2 med två argument x och y som returnerar det största av argumenten.

>>> max2(8, 4) 8

Övning 105 Definiera en funktion max3 med tre argument x, y och z som returnerar det största av de tre argumenten. Använd dig gärna av funktionen max2 från föregående övning.

>>> max3(3, 7, 9) 9 >>> max3(1, 3, 2) 3

Fler matematiska operationer

Förutom de vanliga fyra räknesätten finns det i Python några ytterligare matematiska operatorer. Operatorn // utför heltalsdivision, d.v.s. den gör en division och kastar bort decimaldelen. Besläktad med denna är operatorn % som kallas modulo. Den beräknar resten vid heltalsdivision.

>>> 10 // 3 3 >>> 10 % 3 1

Övning 106 Definiera två funktioner unit (ental) och ten (tiotal) som givet ett heltal plockar fram entals- och tiotalssiffran.

>>> unit(123) 3 >>> ten(123) 2

Övning 107 Definiera en funktion swap_unit_ten som med hjälp av funktionerna från föregående övning byter plats på entalet och tiotalet i ett heltal.

>>> swap_unit_ten(123) 132

1.4 Upprepning med iteration och rekursion

I de följande övningarna och uppgifterna kommer du att skriva lite längre funktioner. Om du inte redan har börjat med det, kan det vara en god idé att nu skriva dina funktionsdefinitioner i en separat fil, hellre än att definiera dem direkt vid Python-prompten. Det gör det lättare att ändra dem och rätta eventuella fel.

Övning 108 Definiera funktionen "upphöjt till". Kalla den power och låt den ta två heltalsargument. Gör två olika varianter, en iterativ och en rekursiv.

>>> power(2, 3) 8 >>> power(5, 2) 25

Du kan testa att du gjort rätt genom att jämföra med den inbyggda operatorn ** som beräknar just "upphöjt till". (Givetvis får du inte använda dig av den i funktionen power.)

Övning 109 Definiera en funktion sum_first som adderar ihop de första n heltalen. Summan av de n första heltalen kan också beräknas med formeln n(n+1)/2 men i den här övningen vill vi att du summerar talen ett i taget med hjälp av någon form av upprepning (iteration eller rekursion). Gör två olika varianter, en iterativ och en rekursiv.

>>> sum_first(6) 21 >>> sum_first(0) 0

Övning 110 Skriv en funktion sum_numbers som summerar de element på en lista som är tal. Allt annat som finns på listan ska ignoreras. Gör två olika varianter, en iterativ och en rekursiv.

Så här kontrollerar du om något är ett tal:

import numbers def isnumber(x): return isinstance(x, numbers.Number)

Nu kan du testa om saker är tal med anrop som isnumber(5.324),

>>> sum_numbers(["a", 1, "b", 2, [["b", 4], 2], 3]) 6

Övning 111 Skriv en funktion find_letter som returnerar ett sant värde (True) om en given bokstav (egentligen en sträng) finns i ett ord, annars ett falskt värde (False). Ordet representeras som en lista. Gör två olika varianter, en iterativ och en rekursiv.

>>> find_letter("u", ["h", "u", "s"]) True >>> find_letter("a", ["b", "i", "l"]) False

Övning 112 Skriv en funktion remove_vowels som tar en lista med bokstäver (egentligen strängar) och returnerar en ny lista med vokalerna borttagna. Det kanske går lättare om du föreställer dig att du ska skapa en ny lista med endast konsonanter snarare än att ta bort vokalerna. Gör två olika varianter, en iterativ och en rekursiv. Tips: Använd dig av find_letter som du definierat ovan!

>>> remove_vowels(["b", "i", "r", "g", "i", "t", "t", "a"]) ['b', 'r', 'g', 't', 't']

Övning 113 Skriv en rekursiv funktion range_product som beräknar produkten av alla heltal från nmin till nmax. Produkten av heltal från 2 till 5 räknas inklusive gränserna, och är alltså 2 * 3 * 4 * 5 = 120. Funktionen ska vara rekursiv, d.v.s. du får inte använda konstruktioner som for eller liknande.

>>> range_product(5, 10) 151200

Övning 114 Skriv en funktion factorial som beräknar fakulteten av ett heltal n. Fakulteten av 0 definieras som 1. Funktionen ska vara rekursiv, och får gärna anropa funktioner du definierat tidigare.

>>> factorial(5) 120 >>> factorial(0) 1

1.5 Uppgifter

Titta gärna på Regler för redovisning och komplettering för information om hur du ska redovisa dina resultat från uppgifterna nedan.

Uppgift 1A - Pokerhänder

En pokerhand består av 5 kort och en kortlek har 52 kort. Hur många olika pokerhänder kan dras ur en vanlig kortlek? Mer allmänt, på hur många sätt kan man välja k element bland n stycken, utan återläggning och utan ordningen bland de k elementen spelar roll? Som man får lära sig i grundkurser i diskret matematik är svaret (n k) vilket utläses "n över k" och definieras så här:

Din uppgift är att skriva en rekursiv funktion choose som tar två positiva heltal n och k (n >= k) och ger (n k). Lösningen ska vara strikt funktionell, och du får inte använda konstruktioner som for eller liknande.

En klurighet är att din funktion ska klara relativt stora tal. Om man inte tänker efter kan detta göra att delberäkningar blir väldigt - till och med ohanterligt - stora, även om det slutliga svaret är hanterbart.

>>> choose(5, 3) 10 >>> choose(1000, 1) 1000 >>> choose(52, 5) 2598960 >>> choose(1000, 4) 41417124750 >>> choose(1000, 800) 661715556065930365627163346132458831897321703017638669364788134708891795956 726411057801285583913163781806953211915554723373931451847059830252175887712 457307547649354135460619296383882957897161889636280577155889117185 >>> choose(1000, 999) 1000

Ledning: Skriv ned - på papper - hur du beräknar (10 3), (10 5), (10 7), (10 1). Finns det några förenklingar eller omskrivningar som du kan göra? Finns det några tal som blir likadana, men där den ena beräkningen är mycket lättare att göra?

Testning För att se till att din funktion klarar av uppgiften finns det ett pythonprogram som kör automatisk testning på din kod. Programmet kan antingen hämtas (test_1.py) om du inte befinner dig på datorerna i SU-salarna eller köras direkt från filsystemet (~TDDC66/tester/test_1.py) om du befinner dig på en av datorerna i ovannämnda salar. Öppna filen med valfri texteditor och läs instruktionerna för hur man för att se hur man kör programmet och kör det sedan för att testa labb 1A.

Uppgift 1B - Personnummer

Skriv en funktion check_pnr som tar ett personnummer i form av en lista med tio siffror på formen [å, å, m, m, d, d, x, x, x, k] och kontrollerar att kontrollsiffran, den sista siffran, är korrekt. Dela upp uppgiften i flera mindre funktioner som du kan testköra för sig. Om funktionerna utför någon form av upprepning får du själv välja metod, iteration eller rekursion.

Metoden för att räkna ut kontrollsiffran i personnummer är enligt följande. Multiplicera alla siffror utom den sista med omväxlande 2 och 1. Summera de enskilda siffrorna i produkterna (dvs om produkten är 2*5 = 10 så summerar vi 1 och 0). Kontrollsiffran är skillnaden mellan nästa högre (eller samma) tiotal och summan av siffrorna.

Personnummer: 7 2 0 1 2 3 1 2 3 Viktsiffror: 2 1 2 1 2 1 2 1 2 ------------------------------------- Produkt: 14 2 0 1 4 3 2 2 6 Siffersumma: 1+4+2+0+1+4+3+2+2+6 = 25 Närmast högre tiotal: 30 Kontrollsiffra: 30-25 = 5

>>> check_pnr([7, 4, 0, 2, 1, 7, 4, 8, 2, 0]) True >>> check_pnr([7, 4, 0, 2, 1, 7, 4, 8, 2, 1]) False

Testning För att se till att din funktion klarar av uppgiften finns det ett pythonprogram som kör automatisk testning på din kod. Programmet kan antingen hämtas (test_1.py) om du inte befinner dig på datorerna i SU-salarna eller köras direkt från filsystemet (~TDDC66/tester/test_1.py) om du befinner dig på en av datorerna i ovannämnda salar. Öppna filen och läs instruktionerna för hur man för att se hur man kör programmet och kör det sedan för att testa labb 1B.

Feedback För att ständigt förbättra undervisningen uppskattar vi om ni fyller i följande formulär. Notera att det är friviligt och inte påverkar betygen på något sätt.


Sidansvarig: Peter Dalenius
Senast uppdaterad: 2016-12-09