Hur man programmerar TDDC66 Datorsystem och programmering Föreläsning 3 Peter Dalenius Institutionen för datavetenskap 2014-09-05
Översikt Problemlösning: Hur ska man tänka? Datatyper Listor (forsätter i föreläsning 7) Iteration och rekursion över listor Mallar för iteration och rekursion 2
Programutvecklingsprocessen Analys Förstå vilket problem som ska lösas! Specifikation Beskriv vad programmet ska göra! Design Beskriv hur programmet ska lösa problemet! Implementation Översätt designen till ett datorprogram! Testning Prova programmet och rätta eventuella fel! Underhåll Fortsätt utveckla programmet vid behov! 3
Exempel Analys Specifikation Design Pelle tänkte gå en kurs i EcoDriving för att bli bättre på att köra sin bil mer bränslesnålt. Han har tyvärr en gammal bil som inte visar hur mycket bensin den drar, men han vill ändå kunna hålla koll på bränsleförbrukningen. För att göra det hela lite mer spännande vill han ha ett Python-program som hjälper honom. Implementation Testning Underhåll 4
Exempel Analys Specifikation Pelle vill ha ett enkelt program som tar en körd sträcka (i km) och hur mycket han har tankat (i liter). Programmet ska sedan räkna ut bränsleförbrukningen och skriva ut den. Design Implementation Testning Underhåll 5
Exempel Analys Specifikation Design Programmet kommer bestå av tre delar: Inmatning av information från användaren Uträkning av förbrukning enligt formeln förbrukning = bensinmängd/sträcka Utskrift av resultatet Implementation Testning Underhåll 6
Exempel Analys Specifikation Design Implementation def fuel_efficiency(): dist = eval(input("sträcka (km): ")) cons = eval(input("förbrukning (l): ")) eff = cons/(dist/10) print("din bil drar", eff, "liter/mil") Testning Underhåll 7
Exempel Analys Specifikation Design Implementation Testning >>> fuel_efficiency() Sträcka (km): 800 Förbrukning (l): 52 Din bil drar 0.65 liter/mil Underhåll 8
Hur kan vi tillämpa detta? Analys Specifikation Tänk efter innan du börjar koda! Använd papper och penna. Skriv pseudokod. Design Implementation Testning Experimentera gärna! Lös ett annat, lite enklare problem först. Testa mycket, ändra om det inte funkar. Lär känna dig själv! Hur brukar jag tänka? Vad funkar? Underhåll 9
Information som programmet använder x = 35 i en variabel i molnet Hur ser informationen ut? zaza4 <14> cat data.txt Kalle 14 p Lisa 23 p Achmed 19 p Pierre 21 p SQL Server i en fil i en databas 10
Datatyper En datatyp är en väldefinierad sorts information som ett datorprogram kan använda. Datatypen talar om vilka dataobjekt som ingår i typen (vilken domän som typen har) samt vilka operationer som är tillåtna. Datatypen svarar alltså på frågorna: Hur ser objekten ut? Vad kan man göra med dem? De flesta programspråk har ett antal inbyggda datatyper (som ofta är ganska lika) samt möjligheter för programmeraren att definiera egna typer. 11
Några datatyper i Python Datatyp Domän Exempel på objekt enkla sammansatta int Heltal 4711 float Flyttal 3.14 str Strängar 'spam' list Listor [1, 2, 75, 6, 7] test av datatyp >>> type(2.78) <class 'float'> >>> type(5) == int True >>> isinstance([1,2,3],list) True 12
Variabler deklararas inte I en del andra programspråk behöver man deklarera variabler, d.v.s. ange vilken datatyp de ska ha. Det behöver vi inte i Python. En variabel har egentligen ingen datatyp, utan är bara en platshållare. Det är innehållet som har en datatyp och en variabel kan ha innehåll av många olika typer under sin livstid. >>> a = 4711 >>> b = ['spam', 'spam'] >>> a = b >>> print(a) ['spam', 'spam'] 13
Datatypen lista Listan är en mycket användbar sammansatt datatyp. I många andra språk kallar man listor för arrayer. Listor kan innehålla obegränsat många element. Man behöver inte i förväg ange hur många som ska få plats, och storleken kan växa och krympa allt efter behov. Elementen i listan kan vara av olika datatyper, t.ex. kan en lista innehålla andra listor. Konstanta listor inleds och avslutas med hakparenteser och elementen separeras med komma. Exempel: a = [1, 'foo', 4.76] En lista som inte innehåller några element kallas tomma listan och betecknas [ ]. 14
Indexering av listor >>> rainbow = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'] >>> rainbow[2] 'yellow' >>> rainbow[2:5] ['yellow', 'green', 'blue'] >>> rainbow[-3] 'blue' >>> rainbow[4:] ['blue', 'indigo', 'violet'] >>> rainbow[:3] ['red', 'orange', 'yellow'] >>> [rainbow[1]] + ['apple', 'banana'] ['orange', 'apple', 'banana'] lista[n] hämtar elementet på plats n, där n även kan vara negativt lista[start:slut] skapar en dellista från start till strax innan slut, där både start och slut är frivilliga red orange yellow green blue indigo violet 0 1 2 3 4 5 6 15
Fler listoperationer >>> for element in [12, 'spam', 3.75]:... print(element)... 12 spam 3.75 >>> a = ['one', 'two', 'three'] >>> a[1] = 2 >>> a ['one', 2, 'three'] >>> len(a) 3 16
Upprepning: Iteration och rekursion Förra föreläsningen genomförde vi upprepningar över tal med iteration (konstruktionen for) och rekursion (funktioner som anropar sig själva). Nu ska vi titta på motsvarande metoder för att upprepa något för varje element i en lista. Hur kan man tänka? Iteration handlar om att hela tiden ha ett delresultat och uppdatera det varje gång man gör upprepningssteget. Rekursion handlar om att försöka omvandla det existerande problemet till ett lite mindre problem och starta om, till dess att problemet är så litet att det är trivialt. Vi ska nu gå igenom en funktion som beräknar längden av en lista på två olika sätt: iterativt och rekursivt. 17
Iterativ beräkning 0123 a b c def length(sequence): result = 0 for element in sequence: result = result + 1 return result I detta exempel beräknar vi längden av listan [ a, b, c ] med iterativ metod. 18
Hur lång är listan [ a, b, c ]? Tack så mycket! Iterativ beräkning a b c Först förbereder vi en räknare. 0123 I 3 Sedan går vi igenom listan ett element i taget. detta exempel beräknar vi längden av listan [ a, b, c ] med iterativ metod. 19
Rekursiv beräkning Testa om listan är tom med if not sequence 1 +? 1 + a b def length(sequence): if not sequence: return 0 else: return 1 + length(sequence[1:])? c 1 + 0? [ ] Resten av listan motsvarar sequence[1:] I detta exempel beräknar vi längden av listan [ a, b, c ] med rekursiv metod. 20
Hur lång är listan [ a,...]? 3 Tack så mycket! Rekursiv beräkning I detta exempel beräknar vi längden av listan [ a, b, c ] med rekursiv metod. 1 + längden av resten Hur lång är listan [ b,...]? 2 1 + längden av resten Hur lång är listan [ c,...]? 1 + längden av resten 1 Hur lång är listan [ ]? 0 21
Mallar för upprepning över en talserie z = startvärde för beräkning (0 om vi kombinerar med +, 1 om vi kombinerar med *) op = operation för att kombinera ihop resultatet, t.ex. + eller * def iter(n): res = z for i in range(n): res = op(i,res) return res def rec(n): if n == 0: return z else: return op(n,rec(n 1)) Mallar för upprepning över en lista op = operation som ska utföras på varje element i listan def iter(seq): res = [] for elem in seq: res = res+[op(elem)] return res def rec(seq): if not seq: return [] else: return [op(seq[0])]+rec(seq[1:]) 22
Utökade mallar för upprepning över en lista med villkor op1, op2 = operationer som ska utföras på varje element i listan cond = villkor som avgör om det är op1 eller op2 som ska användas def iter(seq): res = [] for elem in seq: if cond(elem): res = res+[op1(elem)] else: res = res+[op2(elem)] return res def rec(seq): if not seq: return [] elif cond(seq[0]): return [op1(seq[0])]+rec(seq[1:]) else: return [op2(seq[0])]+rec(seq[1:]) 23
Exempel som använder den utökade mallen Vi vill ha en funktion count som kan räkna hur många gånger ett visst element förekommer i en lista. Exempel: >>> count([1,2,1,3,5],1) 2 def count(seq,goal): result = 0 for element in seq: if element == goal: result = result + 1 return result def count(seq,goal): if not seq: return 0 elif seq[0] == goal: return 1 + count(seq[1:],goal) else: return count(seq[1:],goal) 24
Söndra och härska Dela upp lösningen i flera funktioner, så att varje funktion kan få ett vettigt namn. Använd gärna terminologin från problemet. Gör varje funktion lagom stor så att det är lätt att överblicka och testa varje funktion för sig, men dela inte upp lösningen i allt för många små bitar. Då blir det svårt att få överblick och man riskerar att få onödigt ineffektiva lösningar. Skriv funktioner som är generella och går att återanvända i andra projekt. Du tjänar ofta på att försöka lösa ett lite större problem än du faktiskt har. 25
Exempel: Beräkning av perfekta tal Vi säger att ett tal k delar ett tal n om det finns ett tal a sådant att ak = n. Lite enklare kan man säga att k går jämnt upp i n. Vi säger att ett tal n är perfekt som summan av alla delarna är lika med n. Det finns inte särskilt många perfekta tal. De tre minsta är: 6 (med delarna 1, 2 och 3) 28 (med delarna 1, 2, 4, 7 och 14) 496 (med delarna 1, 2, 4, 8, 16, 31, 62, 124 och 248) Vi vill ha en Python-funktion perfect som tar reda på om ett heltal är perfekt eller inte. Hur kan vi dela upp det problemet i mindre bitar? 26
Ett möjligt sätt att lösa problemet 28 Hitta alla delare till n [1, 2, 4, 7, 14] Testa om k delar n Summera tal i en lista 28 Jämför två tal True 27
Implementation # Check if k divides n def divides(k, n): return n % k == 0 # Return a list of all dividers of n >>> divides(3,24) True >>> divides(3,25) False >>> dividers(10) [1, 2, 5] def dividers(n): result = [] for i in range(1,n//2+1): if divides(i,n): result = result + [i] return result 28
Implementation # Return the sum of a list of numbers def sum(list): if not list: return 0 else: return list[0] + sum(list[1:]) # Checks if n is a perfect number >>> sum([1,2,3,4]) 10 >>> sum(dividers(10)) 8 >>> perfect(10) False >>> perfect(6) True def perfect(n): return n == sum(dividers(n)) 29
Sammanfattning Problemlösning: Hur ska man tänka? steg för steg söndra och härska Datatyper (domän + operationer) int float str list Grundläggande listoperationer, främst indexering s[4] och sånt Iteration och rekursion över listor, inklusive mallar 30
Bildkällor: http://commons.wikimedia.org/wiki/file:%d0%a0%d1%83%d1%81%d1%81%d0%ba%d0 %B0%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D1%91%D1%88%D0%BA%D0%B0.jpg www.liu.se