diff --git a/.gitignore b/.gitignore index bc12a958..14b4c993 100644 --- a/.gitignore +++ b/.gitignore @@ -281,3 +281,6 @@ TSWLatexianTemp* # Makeindex log files *.lpz + +# Jetbrains +.idea/* diff --git a/_data/navigation.yml b/_data/navigation.yml index c48efd4a..eb7c2328 100644 --- a/_data/navigation.yml +++ b/_data/navigation.yml @@ -7,6 +7,14 @@ modules: title: Översikt path: /modules/overview/kurspm prev: index + next: helloworld + helloworld: + path: /modules/helloworld/lab + prev: overview + next: helloworld-tutorial + helloworld-tutorial: + path: /modules/helloworld/tutorial + prev: helloworld next: variables variables: title: Variabler och funktioner diff --git a/adm/assemsg.md b/adm/assemsg.md new file mode 100644 index 00000000..a4271e16 --- /dev/null +++ b/adm/assemsg.md @@ -0,0 +1,49 @@ +Ledsen för sent svar, har haft för mycket att göra! + +Kul att ni är intresserade! Ja, vi behöver fortfarande fler assar. + +Ni kan lägga så mycket eller lite tid på detta som ni har tid för. Bara +att boka upp er i bokningsarket: + + https://docs.google.com/spreadsheets/d/1GfwYBTJ2_D8TDap6HpWvoXuEP_lOMRTRnahC iXTk3hE/edit#gid=1060580342 + +Om ni bara känner för att hjälpa studenterna med labbar bokar ni bara in +er på sådana pass. Brukar även bli att ta redovisningar på de passen, +men det är tidsbokning och bara vissa pass. Sedan blir det p-uppgift +någon gång i slutet av november. + +Ni får gärna vara med på övningarna också. Då finns det förberedda +uppgifter som ni jobbar igenom med studenterna i klassrummet. (Men ni +får givetvis anpassa undervisningen som ni märker att studenterna +behöver det också, väldigt fria händer.) + +Det är alltid andra assar med också. Är det något ni är osäkra på så går +det alltid att fråga någon annan. Vi brukar kommunicera via Zulip (som +Slack): + + https://prgx22.zulipchat.com/join/ahiouanit2q2kp6nuxskwdhm/ + +Färgkoderna i bokningsarket är följande: + + - KTH-blå: ämnar vara på campus + - Naturgrön: ämnar vara online i zoom + +Vi försöker att ha balans. Så om det kvittar om ni är på campus eller online, +välj campus men räkna med att någon måste hålla koll på eventuella studenter +online. + +Om det är första gången ni assar får ni även betalt för en sex timmar +lång crashcourse. Men man behöver inte vara klar med den innan man +börjar assa. + +Om ni signar upp på tillräckligt med pass (~4 h/vecka i medel under två +månader) så kan ni få en amanuenstjänst. Då slipper vi timrapporter, ni får 10% +extra tid (betald egenutveckling), KTH:s julbord (alltid något :-)) och +friskvårdsbidrag. + +Om ni även är intresserade att vara med på DD1310, som är exakt samma +kurs som ges för CMAST och CITEH, så kan ni även boka in er här: + + https://docs.google.com/spreadsheets/d/18-afYjlI--e8hDwzSp9VcHjatc7SPvBFW0fH 9JRrZ-4/edit#gid=1755336853 + +Det är samma Zulip för båda kurserna. diff --git a/adm/examinatorskursen.md b/adm/examinatorskursen.md new file mode 100644 index 00000000..abbbab69 --- /dev/null +++ b/adm/examinatorskursen.md @@ -0,0 +1,355 @@ +# Målrelaterad bedömning och validitet + +Validitet i examination: Det exempel som ges är bra, men det skulle behöva +kompletteras av ytterligare ett exempel. Det behövs ett exempel på låg +validitet (för att ge den nödvändiga kontrasten enligt variationsteorin). +Majoriteten av tentor som ges på KTH har med stor sannolikhet låg validitet, då +många är utformade på följande sätt. Vi ger basfallet med två lärandemål och +resten följer av induktion. + + Lärandemål: + - Efter godkänd kurs ska studenten kunna redogöra för X. + - Efter godkänd kurs ska studenten kunna analysera Y. + + Examination: + - Tio frågor på ett prov, utformade så att måluppfyllelse kan visas. + - Fem täcker X och fem täcker Y. + + Operationellt bedömningskriterium: + - Minst 6 av dessa 10 frågor ska vara korrekt besvarade för godkänt. + +Denna utformning ger låg validitet då en student kan besvara fem frågor om X +korrekt, men bara en fråga om Y; och trots detta får godkänt. Genom induktion +får vi att detsamma gäller för N lärandemål. Således ger tentor som +slentrianmässigt har 50% av poängen för E låg validitet. + +Låt oss även utforska tillämpningen av bonuspoäng. Om bonuspoängen ges som +extra poäng på provet, godtyckligt, utan att motsvara en specifik fråga (dvs +ett specifikt lärandemål), då förstör även detta validiteten i examinationen, +på samma sätt som ovan. För att bonuspoängen inte ska degradera validiteten +måste varje bonuspoäng motsvara en specifik fråga som motsvarar ett specifikt +lärandemål. Uppgiften som ger bonus måste också examinera just det +lärandemålet. Dvs ett korrekt utformat bonussystem flyttar (delar av) +examinationen av lärandemål från ett tillfälle till ett annat. + +## Fördjupad läsning + +Kursutveckling.se finns inte längre, `whois` ger: + +``` +# Copyright (c) 1997- The Swedish Internet Foundation. +# All rights reserved. +# The information obtained through searches, or otherwise, is protected +# by the Swedish Copyright Act (1960:729) and international conventions. +# It is also subject to database protection according to the Swedish +# Copyright Act. +# Any use of this material to target advertising or +# similar activities is forbidden and will be prosecuted. +# If any of the information below is transferred to a third +# party, it must be done in its entirety. This server must +# not be used as a backend for a search engine. +# Result of search for registered domain names under +# the .se top level domain. +# This whois printout is printed with UTF-8 encoding. +# +state: deactivated +domain: kursutveckling.se +holder: jansve7609-00001 +created: 2006-04-24 +modified: 2023-05-04 +expires: 2023-04-24 +transferred: 2019-02-13 +deactivationdate: 2023-05-04 +date_to_delete: 2023-07-03 +date_to_release: 2023-07-10 +nserver: a.ns.ip-only.net 212.112.160.42 +nserver: b.ns.ip-only.net 212.112.163.90 +nserver: c.ns.ip-only.net 212.112.165.178 +nserver: dns3.slu.se 193.10.100.16 +dnssec: unsigned delegation +registry-lock: unlocked +status: pendingDelete +status: serverHold +registrar: Loopia AB +``` + + +# Rättssäker examination + +## Rättssäkerhet + +### Proportionalitetsprincipen + +Kan vi motivera användningen av bonuspoäng? + + - Behövs åtgärden för att myndigheten ska uppnå de mål som gäller för den? + + - Nej, vi kan examinera ändå. + - Ja, för vi vill ha genomströmning. + + - Finns det mindre ingripande alternativ som ger samma eller nästan samma + resultat? + + - Ja, vi kan lära studenterna att planera sin tid, vilket dessutom borde + vara mer värdefullt. + + - Är skadorna som uppstår rimliga i förhållande till det mål som uppnås? + + - Nej, det orsakar onödig stress och förstör möjligheten att planera för + studenterna när vi har överdrivet mycket examination och det är + examination hela tiden som ska vara klar just då för att få bonuspoäng. + (Istället för att vi låter dem ansvara själv för sitt lärande.) + +Vi kan även fråga oss om vi behöver all den redundanta examination som vi har i +programmeringskurserna (labbar, datorprov och p-uppgift) och andra kurser. + +Vi återkommer till detta. + +### Likhetsprincipen + +Är det motiverat att tillämpa bonuspoäng sett ur likhetsprincipens perspektiv? +(Denna diskussion är även högst relevant för området Likvärdig examination, det +området borde vara en konsekvens av denna princip.) Det är lättare för en +barnlös 20-åring att hinna med alla deadlines skapade av bonuspoäng jämfört med +en ensamstående småbarnsmamma. + +Rent teoretiskt borde inte bonuspoängen i sig inte ge några fördelar ur +examinationens perspektiv. Detta är dock inte sant, men vi återkommer till det. +Låt oss anta att det är sant, då borde den ensamstående småbarnsmamman kunna +få samma betyg som den barnlösa 20-åringen utan skillnad i prestation. Men då +kan vi fråga varför vi har bonuspoängen överhuvudtaget? + +Om man tillämpar bonuspoängen på ett korrekt sätt så innebär de bara att man +flyttar examination (eller delar av) från ett tillfälle till ett annat: I +fallet med ett prov (eller tenta, som är vanligast att använda bonuspoäng till) +så flyttar man examinationen av en fråga (lärandemål) från provet till +tillfället då studenten kunde tillgodogöra sig bonuspoängen. + +Till och med här, i det optimala fallet, har den ensamstående småbarnsmamman +missgynnats med *mindre tid per fråga* på provet, jämfört med den barnlösa +20-åringen. Detta då tiden för provet är konstant i praktiken, medan antalet +frågor varierar på grund av bonuspoängen. Vi kan även ta upp påverkan av andra +faktorer som stress, även om de är svårare att kvantifiera. + +Låt oss nu titta på en mindre optimal tillämpning av bonuspoäng som är mer lik +hur bonuspoäng tillämpas i praktiken i många kurser. + +Bonuspoängen ges som extra poäng på provet, godtyckligt, utan att motsvara +specifika lärandemål. Som sagt ovan [Målrelaterad bedömning och validitet], +förstör detta validiteten i examinationen. Detta får ytterligare effekter sett +ur likhetsperspektiv, då bonussystemet nu inte längre flyttar examinationen +från ett tillfälle till ett annat. Att hinna i tid kan ge fördelar i helt andra +delar av examinationen. Det kan dessutom göra så att den barnlösa 20-åringen +kan få poäng för samma kunskaper/färdigheter två gånger (om studenten gör +frågan som motsvarar bonuspoängen igen på tentan utan att detta dras av), +vilket kan påverka betyget till det högre. + +Sedan kan vi ju återvända till proportionalitetsprincipen för att diskutera om +fördelarna för de barnlösa 20-åringarna väger över nackdelarna för de +ensamstående småbarnsföräldrarna. Med tanke på att den sociala +snedrekryteringen till högskolan är ett genomgående problem, skulle jag säga +att det inte är värt det. + + +## Utdrag ur högskoleförordningen + +Texten "och om det inte innebär att betyget sänks" bör nog ges viss emfas, då +detta sannolikt är mindre känt än övriga delar av texten. Iofs lär quizzet +efteråt befästa detta. + + +# Likvärdig examination + +Diskriminering: Det som jag finner intressant är att fokus här väldigt lätt +låses till de olika diskrimineringsgrunderna. I min värld är +diskrimineringsgrunderna lågvattenmärket vi behöver hålla, helst bör vi göra +bättre än bara de sex diskrimineringsgrunderna. Exempelvis, den sociala +snedrekryteringen är inte diskriminering, men vi bör ändå göra något åt det. +Det är lite som med fokuset på mansdominansen inom akademin/teknikområdet/etc., +vilket leder fokuset till män och kvinnor, men helt glömmer bort icke-binära +och könsidentitet generellt. (En anledning är väl att det inte går att mäta, då +vi inte får fråga om det datat; medan personnumret kan användas för att läsa ut +man eller kvinna.) + +Diskrimineringsgrunderna måste man ta hänsyn till för att få ett E. Men vi bör +ha ambitionen att hamna på A. + +## Strategier för likvärdig examination + +En väldigt bra sida, men ... + +"Vi kan *lära mer om* olika studentgrupper för att bättre lära känna våra +studenter och utforma examinationen inkluderande, vi kan anpassa examinationen +för olika studentgrupper", men det blir svårt att lära känna de studenter som +är exkluderade på grund av utbildningens/undervisningens generella utformande +(campus kl 8--17 med obligatorisk närvaro). + +Policyn att deadline alltid ska vara kl 19 på vardagar är ett intressant steg. +Dock så vet jag inte om det hjälper småbarnsföräldrar så som det är avsett. I +min erfarenhet är det flexibiliteten som underlättar för dem, rigida strukturer +med tighta deadlines är svåra oavsett när på dygnet de är. + +En sak vi behöver göra på detta område är att se över hur mycket tid våra +kurser faktiskt tar i anspråk. Finns det faktiskt tid över till att göra +uppgifter utanför schemalagd tid? Vissa program är i vissa perioder schemalagda +kl 8--17, varje dag---då finns inte tid att göra något på kursen när man inte +är schemalagd. + +I mitt eget fall schemalade jag egen studietid för att skydda studenterna från +andra kurser. Visade sig att de ändå bara hade tid för två timmar utanför +kursens ordinarie schemalagda tillfällen (en föreläsning, en labb och en +övning). + +## Inkluderande examination + +"Ett annat exempel på inkluderande examination är att ge gott om tid för +inlämningsuppgifter, alltså från det att uppgiften publiceras (givet att +studenterna då har nödvändiga kunskaper för att utföra uppgiften) och deadline +för inlämning." Detta kommer också att betyda att vi sannolikt behöver minska +antalet uppgifter studenterna behöver göra. Min uppfattning är att det är +väldigt mycket uppgifter i de kurser som går parallellt med mina kurser, vilket +tillintetgör vad detta syftar till att åstadkomma. + +Men detta är nödvändigt enligt diskussionen om strategier för likvärdig +examination ovan. + +## Varierad examination + +Vanligtvis är examinationsformerna varierade i en kurs. Det finns normalt +labbar (muntlig eller skriftlig redovisning), seminarier, projekt (ofta med +skriftlig och muntlig redovisning), tentamen. Dock måste alla +examinationsformer genomföras av alla studenter och med godkänt resultat i +samtliga. Detta tar lite udden av vad vi vill uppnå med varierad examination. + +Sett ur detta perspektiv bör vi ha examination som är varierad, men att en +student inte behöver få godkänt i varje examinationsmoment som rör samma +lärandemål. Detta skulle således motsvara en slags "maximum"-policy för +betygskriterierna (eller "mastery-based grading"). Det räcker med att ha nått +A-nivån i betygskriterierna på *en* examinationsuppgift för ett lärandemål, man +behöver inte nå A på samtliga examinationsuppgifter för det lärandemålet. Rent +krasst skulle en student då bara behöva göra de uppgifter som examineras på det +sätt som passar dem bäst. De måste dock klara en uppgift per lärandemål, då +alla lärandemål måste examineras. + +Notera att detta dock inte säger något om hur A på ett lärandemål och C på ett +annat ska sammanfattas i ett slutbetyg för hela kursen. Men de två mest +resonliga policyerna är "minimum"- eller "medel"-policyn. "Minimum" tar den +lägsta betygsnivån uppnådd i alla lärandemål. "Medel" tar istället medel; dvs +på några lärandemål uppnådde studenten mer, på andra mindre. Om man tittar på +användbarheten för det sammanfattande betyget så är "mimimum"-policyn mest +relevant, då vet man att studenten ligger på minst den nivån i alla lärandemål. +"Medel"-policyn tappar för mycket information. + +Man bör definitivt reflektera över varför vi examinerar på ett visst sätt och +fundera över alternativ. + +## Normkritiskt förhållningssätt + +I de flesta fall i min examination har nog kvinnliga studenter mest fördelar. +Men det är nog för att jag upplever dem som bättre; de kan tänka utanför lådan, +se olika perspektiv, förklara och berätta saker bättre än de manliga +studenterna. + +Det jag tänker mest på i normkritisk mening i min egen praktik är att inte +skräddarsy utbildningarna efter barnlösa gymnasieungdomar, vilket är +normstudenten på våra utbildningar. + +## Fördjupad läsning om likvärdig examination + +Som nämndes ovan, fokuset på förhållandet mellan kvinnor och män osynliggör +icke-binära (och andra som inte följer normen): + + "Data från KTH: Antal studerande kvinnor respektive män på KTH: KTH i + siffror" + +Men som sagt, vi får väl inte mäta könsidentitet heller. Men då allt data +handlar om det så påverkar det ju fokus. + +# Lokala regler för examination + +Angående frågan i det andra quizzet: + + Anta att det i examinationen i din kurs ingår en inlämningsuppgift och att + det i betygskriterierna står att om studenterna är sena med att lämna in den + så sänks deras betyg på den uppgiften, även om uppgiftens kvalitet (det + studenterna presterat) motsvarar ett högre betyg. Kan man sänka betyget på + inlämningsuppgiften enbart baserat på att den kommer in efter deadline? + +Även om examinator får göra det betyder det inte att examinator bör göra det. +Betygen ska reflektera lärandemålen, där betygskriterierna ställer upp någon +typ av progression relaterad till respektive lärandemål. Om tiden är en viktig +aspekt ska den vara en del av lärandemålen, exempelvis att ett lärandemål +handlar om projektledning (där tidsaspekten är relevant). Man skulle också +kunna argumentera för att nivån av skicklighet kan relateras till hur snabbt en +uppgift kan lösas. + +I båda dessa fall ska i sådant fall tidsmätningen göras på ett korrekt och +gediget sätt. De individuella förutsättningarna ska också tas i beaktande: det +vore inte särskilt rättvisande om en student får ett sämre betyg bara för att +en närstående gått bort under kursens gång. Dessa förutsättningar är dessutom +såpass individuella så att det är svårt att sätta upp några rättssäkra +kriterier kring dem. Följaktligen måste tidsmätningen anpassas. + +En annan aspekt hittar vi i kap 6 högskoleförordningen: + + Antal prov m.m. + + 21 § Om en högskola begränsar det antal tillfällen som en student får + genomgå prov för att få godkänt resultat på en kurs eller del av en kurs, + skall antalet tillfällen bestämmas till minst fem. Om godkänt resultat på en + kurs eller del av en kurs förutsätter att studenten genomgått praktik eller + motsvarande utbildning med godkänt resultat, skall antalet praktik- eller + motsvarande utbildningsperioder bestämmas till minst två. + Förordning (2006:1053). + +Det vill säga, en student har alltid rätt att göra ett nytt prov. Då +tidsaspekten är ett lärandemål som ska mätas och tidsmätningen bör göras +korrekt, så måste även tidsmätningen göras om från början. Tidsmätningen kan +inte fixeras till kursens början, *utan till (om-)provets början*. + +Man kan ha viss tidsaspekt med i betygskriterierna även om det inte är ett +direkt lärandemål. Exempelvis att lösa ett problem och betyget avgörs hur +snabbt man löser problemet. Men då måste det vara en kontrollerad och korrekt +tidsmätning som inte påverkas av irrelevanta faktorer (exempelvis +planeringsförmåga eller skicklighet att hantera oförutsägbara händelser i +privatlivet). + +Redan här finner jag det således absurt att tidsaspekten ska påverka betyget i +majoriteten av fall. Men vi hittar ytterligare intressanta aspekter i UKÄ:s +vägledning för rättssäker examination (sidan 34): + + UKÄ konstaterar att högskoleförfattningarna visserligen inte reser några + formella hinder mot att tillämpa olika betygsskalor vid prov respektive + omprov. Men mot bakgrund av de starka invändningar som kan resas + mot en ordning med olika betygsskalor bör ett lärosäte noggrant + överväga alla aspekter och konsekvenser innan man inför en sådan + ordning på en kurs. Om lärosätet väljer att införa en ordning med olika + betygsskalor på en kurs, bör det framgå av kursplanen. + +Några av argumenten från de positiva lärosätena är (sidan 34): + + Det handlar främst om examinationsuppgifter där tidsaspekten är avgörande för + bedömningen av studentens prestationer. Argumentet är att det inte ska vara + möjligt att köpa sig mer tid vid t.ex. en projektuppgift genom att inte gå + upp på ordinarie examination + +Vilket löses genom att göra en *korrekt* tidsmätning. + +Vi kan också påpeka att KTH är ett av de positiva lärosätena (sidan 34): + + Även KTH och Högskolan i Jönköping anser att det i vissa speciella fall bör + vara möjligt med olika betygsskalor. + +Om vi då återgår till en del av motiveringen i svaret till frågan, där skrivs +följande: + + Det ska framgå av kursplanen eller av betygskriterierna vad konsekvenserna + blir om uppgiften inte lämnats in i tid. Konsekvensen kan till exempel bli + underkänt eller lägre betyg på uppgiften. (Riktlinje om kursplan, + betygssystem och examination inom alla utbildningsnivåer.) + +Detta anser jag således vara väldigt förenklat och leder fel i det generella +fallet. Jag skulle säga att det är en begränsad tolkning som inte tar hänsyn +till studenternas rättigheter enligt högskoleförordningen och är inte heller +förenligt med målrelaterad bedömning. + diff --git a/adm/examiners-meeting-20230616.md b/adm/examiners-meeting-20230616.md new file mode 100644 index 00000000..0d1684be --- /dev/null +++ b/adm/examiners-meeting-20230616.md @@ -0,0 +1,68 @@ +# Vad är syftet med LAB1, LAB2, LAB3 + +LAB3 examinerar helheten. + +LAB2 kan examinera specifika problem som de inte nödvändigtvis kommer i kontakt +med under labbarna. Exempelvis referenser och scope. + +LAB2 är individuellt medan LAB1 är i grupp, så då kanske de deltar bättre under +LAB1 som förberedelse för LAB2, när de vet att det kommer ett prov. I detta +fall kanske vi bör ha en mer kontrollerad miljö, dvs skrivning med övervakning +i sal. + +Om man har tidigare prov tillgängliga så lär sig duktiga studenter att de +faktiskt inte kan kursens innehåll. + +Redundans i frågor: Olika frågor är bättre på vissa frågetyper, så variation är +bättre för varierade studenter. + +Kan vi få KTH att övervaka datorprovet åt oss? Då kan vi köra det oftare. Kan +vi använda Inspera? Tentarutin i Ubuntusalarna. Kan låsas till ett speciellt +utvecklat kursrum. Kolla vad vi kan göra med education-support@. Annars är +rutinen att det skapas ett tentaspecifikt canvasrum. + +Viktigast för Emma: legkontroll. + +Hur ofta? Kan ha gemensamma omprov. Men då blir det tentarum och inget +material. Två gånger per kursinstans och år. + +Hur länge ska bonuspoängen gälla? + +# Kursens lärandemål + +Efter godkänd kurs ska studenten kunna + +- konstruera program utan kodupprepningar +- dela upp ett större problem i hanterliga delar +- dela upp ett program +- tillämpa styrstrukturer +- utforma och presentera användarvänliga utdata +- skapa flexibla applikationer +- välja lämpliga identifierarnamn +- konstruera interaktiva program +- använda och konstruera sammansatta datatyper och klasser +- överföra data mellan fil och program +- granska andras program + +i syfte att senare + +- kunna använda programmering för att lösa problem +- kunna tillämpa problemlösningsmetodiken även inom andra områden än programmering +- kunna diskutera programutveckling med experter +- kunna bedöma program i storleksordningen på ca femhundra rader kod +- självständigt och i grupp kunna lösa problem genom att konstruera program på upp till femhundra rader i ett modernt programspråk. +- + +# Lärandemål som examineras med LAB2 + +- konstruera program utan kodupprepningar +- dela upp ett större problem i hanterliga delar ++ dela upp ett program ++ tillämpa styrstrukturer ++ utforma och presentera användarvänliga utdata +- skapa flexibla applikationer ++ välja lämpliga identifierarnamn ++ konstruera interaktiva program ++ använda och konstruera sammansatta datatyper och klasser ++ överföra data mellan fil och program +- granska andras program diff --git "a/adm/l\303\244rarlag-20230607.md" "b/adm/l\303\244rarlag-20230607.md" new file mode 100644 index 00000000..b3a576c4 --- /dev/null +++ "b/adm/l\303\244rarlag-20230607.md" @@ -0,0 +1,12 @@ +# Olika personer + +## Fredrik Kilander och Fadil Galjic i Kista + +Har flera kurser i inledande programmering i Kista. + +Det är deras kurser som Emma hjälpt till i. + + +# Vahid + +KTH forms: https://kth.se/form/admin diff --git a/adm/tid/amanuens.py b/adm/tid/amanuens.py index dbf9a4e8..c4787326 100644 --- a/adm/tid/amanuens.py +++ b/adm/tid/amanuens.py @@ -1,3 +1,4 @@ +import arrow import csv import nytid.schedules as sched import nytid.schedules.utils as utils @@ -14,13 +15,33 @@ def to_hours(td): return td.total_seconds()/60/60 +def shift_dates_forward(start_date, end_date): + """Takes dates and shifts them so that start_date is tomorrow.""" + now = arrow.now() + today = arrow.Arrow(now.year, now.month, now.day, + hour=start_date.hour, minute=start_date.minute, + second=start_date.second) + + if start_date > today: + return start_date, end_date + + diff = (today-start_date).days + return start_date.shift(days=diff+1), end_date.shift(days=diff+1) + + if len(sys.argv) < 2: print(f"{sys.argv[0]}: requires argument 'username'", file=sys.stderr) + print(f"{sys.argv[0]} []") sys.exit(1) else: user = sys.argv[1] +if len(sys.argv) > 2: + date = arrow.get(sys.argv[2]) +else: + date = None + prgi22 = utils.read_signup_sheet_from_url( utils.google_sheet_to_csv_url( "https://docs.google.com/spreadsheets/d/1GfwYBTJ2_D8TDap6HpWvoXuEP_lOMRTRnahCiXTk3hE/edit#gid=1060580342")) @@ -29,11 +50,17 @@ def to_hours(td): utils.google_sheet_to_csv_url( "https://docs.google.com/spreadsheets/d/18-afYjlI--e8hDwzSp9VcHjatc7SPvBFW0fH9JRrZ-4/edit#gid=1755336853")) -amanuensis = utils.compute_amanuensis_data(prgi22 + prgm22) +amanuensis = utils.compute_amanuensis_data(prgi22 + prgm22, + begin_date=date) data = amanuensis[user] -print(f"{user}: {data[2]:.2f} h, {100*utils.compute_percentage(*data):.1f}%: " - f"{data[0].format('YYYY-MM-DD')}--{data[1].format('YYYY-MM-DD')}") +#start, end = shift_dates_forward(data[0], data[1]) +start = data[0] +end = data[1] + +print(f"{user}: {data[2]:.2f} h, " + f"{round(100*utils.compute_percentage(*data))}%: " + f"{start.format('YYYY-MM-DD')}--{end.format('YYYY-MM-DD')}") prgx = utils.filter_events_by_TA(user, sorted(prgi22 + prgm22, key=operator.itemgetter(utils.SIGNUP_SHEET_HEADER.index("Start")))) diff --git a/adm/tid/bookedTAs.py b/adm/tid/booked.py similarity index 91% rename from adm/tid/bookedTAs.py rename to adm/tid/booked.py index edbe613b..901d95fb 100644 --- a/adm/tid/bookedTAs.py +++ b/adm/tid/booked.py @@ -56,10 +56,13 @@ def main(): booking_data += utils.read_signup_sheet_from_url(url) schedule = generate_schedule(events_booked_TAs(booking_data)) + now = arrow.get(2022, 8, 29) + if now < arrow.now(): + now = arrow.now() if len(sys.argv) > 1: try: - time_limit = arrow.get(2022, 8, 29).shift(weeks=+int(sys.argv[1])) + time_limit = now.shift(weeks=+int(sys.argv[1])) except ValueError as err: print(f"{sys.argv[0]}: {err}: " f"first argument must be the number of weeks to print", @@ -68,6 +71,14 @@ def main(): first = True for event in schedule.timeline: + try: + if event.end < now: + continue + elif event.begin > time_limit: + break + except NameError: + pass + if first: first = False current_week = event.begin.isocalendar()[1] @@ -75,12 +86,6 @@ def main(): current_week = event.begin.isocalendar()[1] print(end="\n\n") - try: - if event.begin > time_limit: - break - except NameError: - pass - print(format_event(event)) diff --git a/adm/tid/missingTAs.py b/adm/tid/missing.py similarity index 91% rename from adm/tid/missingTAs.py rename to adm/tid/missing.py index 5b875b72..a2d097ef 100644 --- a/adm/tid/missingTAs.py +++ b/adm/tid/missing.py @@ -61,10 +61,13 @@ def main(): booking_data += utils.read_signup_sheet_from_url(url) schedule = generate_schedule(events_missing_TAs(booking_data)) + now = arrow.get(2022, 8, 29) + if now < arrow.now(): + now = arrow.now() if len(sys.argv) > 1: try: - time_limit = arrow.get(2022, 8, 29).shift(weeks=+int(sys.argv[1])) + time_limit = now.shift(weeks=+int(sys.argv[1])) except ValueError as err: print(f"{sys.argv[0]}: {err}: " f"first argument must be the number of weeks to print", @@ -73,6 +76,14 @@ def main(): first = True for event in schedule.timeline: + try: + if event.end < now: + continue + elif event.begin > time_limit: + break + except NameError: + pass + if first: first = False current_week = event.begin.isocalendar()[1] @@ -80,12 +91,6 @@ def main(): current_week = event.begin.isocalendar()[1] print(end="\n\n") - try: - if event.begin > time_limit: - break - except NameError: - pass - print(format_event(event)) diff --git a/adm/tid/report b/adm/tid/report index b46edb01..c654017e 100755 --- a/adm/tid/report +++ b/adm/tid/report @@ -2,7 +2,7 @@ recipient="$1" -loffice --convert-to pdf *.xlsx +loffice --convert-to pdf *.xlsx *.numbers for f in *.pdf *.PDF; do xournal $f diff --git a/adm/tid/ug.py b/adm/tid/ug.py new file mode 100644 index 00000000..b55cc431 --- /dev/null +++ b/adm/tid/ug.py @@ -0,0 +1,40 @@ +import kthutils.ug +import os +from pprint import pprint +import nytid.schedules.utils as utils + +COURSES = { + "DD1310": + "https://cloud.timeedit.net/kth/web/public01/ri.ics?sid=7&p=0.w%2C12.n&objects=453080.10&e=220609&enol=t&ku=29&k=1B9F3AD696BCA5C434C68950EFD376DD", + "DD1317": + "https://cloud.timeedit.net/kth/web/public01/ri.ics?sid=7&p=0.w%2C12.n&objects=455995.10&e=220609&enol=t&ku=29&k=BA4400E3C003685549BC65AD9EAD3DC58E" + } + +prgi22 = utils.read_signup_sheet_from_url( + utils.google_sheet_to_csv_url( + "https://docs.google.com/spreadsheets/d/1GfwYBTJ2_D8TDap6HpWvoXuEP_lOMRTRnahCiXTk3hE/edit#gid=1060580342")) + +prgm22 = utils.read_signup_sheet_from_url( + utils.google_sheet_to_csv_url( + "https://docs.google.com/spreadsheets/d/18-afYjlI--e8hDwzSp9VcHjatc7SPvBFW0fH9JRrZ-4/edit#gid=1755336853")) + +ug = kthutils.ug.UGsession(os.environ["KTH_LOGIN"], os.environ["KTH_PASSWD"]) + +members = [] + +for user in utils.hours_per_TA(prgi22 + prgm22): + user_data = ug.find_user_by_username(user) + if len(user_data) > 1: + pprint(user_data) + continue + elif len(user_data) < 1: + print(f"ug: can't find {user}") + continue + members.append(user_data[0]["kthid"]) + +prgi = next(ug.find_group_by_name("edu.courses.DD.DD1317.20222.1.assistants")) +ug.set_group_members(members, prgi["kthid"]) + +prgm = next(ug.find_group_by_name("edu.courses.DD.DD1310.20222.3.assistants")) +ug.set_group_members(members, prgm["kthid"]) + diff --git a/makefiles b/makefiles index 7bce1d69..980ea1bb 160000 --- a/makefiles +++ b/makefiles @@ -1 +1 @@ -Subproject commit 7bce1d69401546bf858bc422647f2d2d55de2c2c +Subproject commit 980ea1bb5c264fee752b841ae53b463c5409c5be diff --git a/modules/Makefile b/modules/Makefile index 0be0002f..f6469dc5 100644 --- a/modules/Makefile +++ b/modules/Makefile @@ -1,15 +1,19 @@ SUBDIR+= overview +SUBDIR+= helloworld +SUBDIR+= computational-thinking SUBDIR+= variables -SUBDIR+= functions #SUBDIR+= debug SUBDIR+= conditionals +SUBDIR+= iterations +SUBDIR+= packages SUBDIR+= containers +#SUBDIR+= functions #SUBDIR+= exceptions -SUBDIR+= files SUBDIR+= classes -SUBDIR+= recap +SUBDIR+= files +#SUBDIR+= recap SUBDIR+= graphics -SUBDIR+= scipy +#SUBDIR+= scipy SUBDIR+= project INCLUDE_MAKEFILES=../makefiles diff --git a/modules/classes/lab/input_type.py b/modules/classes/lab/input_type.py index 52a136be..2fe9a90d 100644 --- a/modules/classes/lab/input_type.py +++ b/modules/classes/lab/input_type.py @@ -1,5 +1,6 @@ """Take input more easily.""" + def input_type(t, prompt=""): """Take input, convert to type t; repeat if error.""" while True: @@ -11,6 +12,7 @@ def input_type(t, prompt=""): else: print(f"Sorry, can't convert to {t}.") + def main(): """Test functionality of this module""" x = input_type(int, "x = ") @@ -22,5 +24,6 @@ def main(): print(f"z = {z}") print(f"Your name is {name}") + if __name__ == "__main__": main() diff --git a/modules/classes/lab/instruction.md b/modules/classes/lab/instruction.md index 91deb757..3795d74c 100644 --- a/modules/classes/lab/instruction.md +++ b/modules/classes/lab/instruction.md @@ -1,138 +1,97 @@ --- -title: Laboration: Klasser och objekt -authors +title: Laboration om Mer klasser och behållare +authors: + - Celina Soori - Daniel Bosk --- -# Laboration: Klasser och objekt +# Laboration: Mer klasser och behållare -Hittils har vi använt funktioner för att beräkna $g_n$ på olika sätt (konstant -$q$ och en lista med $q$-värden). Syftet med klasser (och objekt) är att de -bättre liknar objekt i verkligheten. Exempelvis är en talföljd väldigt lik en -lista, det är ju trots allt en (möjligtvis oändlig) lista med tal, men mindre -lik en funktion för att beräkna talen i följden. +I förra laborationen använde vi oss av en klass vars objekt vi sparade i en behållare i huvudprogrammet. +Nu ska vi istället använda oss av två klasser, därav den första +klassen har en behållare som ett attribut, där vi sparar objekt från +den andra klassen. -Fördelen med att representera objekt på ett bättre sätt är att det underlättar -för den som ska programmera. Det kan göra koden mer intuitiv, mer läsbar. Detta -minskar risken för fel (buggar). +Fördelen med att spara ner objekt på detta vis är att vi kan skapa en mer +strukturerad och användbar kod, vilket gör koden mer lättläst och flexibel. +## Innan du börjar koda + +Läs på om [uppslagsverk][uppslagsverk]. + +[uppslagsverk]: https://docs.python.org/3/tutorial/datastructures.html#dictionaries ## Uppgift -Nu ska vi skriva klasser som hanterar talföljder. Låt klasserna vara en del av -din modul för talföljder. De ska hantera den karakteristiska egenskapen för en -talföljd: det ska gå att få ut det $n$:te elementet (använd -[`__getitem__`][getitem]). - -[getitem]: https://docs.python.org/3/reference/datamodel.html#object.__getitem__ - -Med den egenskapen och om du använder `__getitem__` kan vi skriva kod som -följande: - -```python -import my_sequence_library as myseq -# Ladda hem modulen input_type från: -# https://github.com/dbosk/intropy/raw/master/modules/classes/lab/input_type.py -import input_type as it - -def run_tests(): - """Function containing tests for the my_sequence_library module""" - a1 = it.input_type(int, "a1 = ") - d = it.input_type(int, "d = ") - - # Skapa artimetiskt talföljdsobjekt - a = myseq.ArithmeticSequence(a1, d) - - # Skriv ut de första 20 elementen - for i in range(20): - print(f"a[{i}] = {a[i]}") - - # skapa geometriskt talföljdsobjekt - g1 = it.input_type(float, "g1 = ") - q = it.input_type(float, "q = ") - g = myseq.GeometricSequence(g1, q) - print(f"g[12] = {g[12]}") - - # detta ska generera ett IndexError, finns inget sista element i en - # oändlig lista - try: - print(f"g[-1] = {g[-1]}") - except IndexError: - print("Finns inget sista tal i en oändlig talföljd") - - # använd sequence.csv som exempelinmatning: - # https://github.com/dbosk/intropy/raw/master/modules/classes/lab/sequence.csv - filename = it.input_type(str, "filename = ") - gf = myseq.MultiplicativeSequenceFromFile(filename) - print(f"gf[12] = {gf[12]}") - - # sequence.csv har färre än 1000 element, så detta ska generera ett - # IndexError - try: - print(f"gf[1000] = {gf[1000]}") - except IndexError: - print("På tok för stort index.") - -if __name__ == "__main__": - run_tests() -``` +Nu ska vi skriva en klass "School" som har minst ett attribut __students__. -Ovan nämnda egenskap (indexering, `__getitem___`) är sann för alla talföljder, -vare sig de är aritmetiska, geometriska eller något annat. Då kan vi ha en -generell klass för talföljder och sedan specialiserade klasser för aritmetiska -och geometriska talföljder. Så vi skulle kunna byta ut `a = -myseq.ArithmeticSequence(a1=1, d=2)` mot `a = -myseq.MultiplicativeSequenceFromFile("file.txt")` (som läser in en sekvens från -fil, likt föregående laboration) och resten av koden i exemplet ovan kommer att -fortsätta att fungera. +Skapa ett objekt av typen School. Låt igen användaren skriva in information om +minst tre studenter och skapa objekt av typen Student. -**Inlämning**: Lämna in en modul (`my_sequence_library.py`) som fungerar med -testprogrammet ovan. Den måste då innehålla klasserna `ArithmeticSequence`, -`GeometricSequence` och `MultiplicativeSequenceFromFile`. +Spara objekten i School-objektets attribut __students__. -**Krav**: Du ska ha felhantering. Exempelvis hantera att talföljden (från fil) -inte har tillräckligt många element. Exempelvis om den innehållet data för 12 -månader, då finns inte `a[20]`. Testkoden ovan innehåller try-except-satser som -fångar de särfall (exceptions) som er kod förväntas att kasta (`raise`). +Fundera på vad som är den bästa typen av behållare för att spara objekten. +Vilka nackdelar och fördelar finns det med olika behållare? +Lägg nu till en metod i klassen School som låter användaren söka efter en +elev som går på skolan och som skriver ut om eleven finns och det funna +Student-objektet. Du får välja själv om du ska söka med hjälp av förnamn, efternamn +eller personnummer. -## Extrauppgift +### Exempelutskrift -Hantera [slice-notation][slice-notation], exempelvis: -``` -# Skriv ut summan av de första 20 elementen -print(f"sum(a) = {sum(a[:20])}") ``` +... +Vad heter studenten? Emma Emilsson +Vad är studentens personnummer? 010101000a +Personnumret får bara innehålla siffror, försök igen! +Vad är studentens personnummer? 0101010000 + +Studenten är tillagd! + +Vilken student vill du söka efter? Jan + +Den studenten läser på KTH: +Namn: Jan Jansson Personnr: 0404040010 -För raden `sum(a[:20])` krävs att din kod hanterar [sliceobjekt][slice-docs]. -Följande exempelkod är bra att experimentera med för att komma igång: -```python -class Test: - def __getitem__(self, key): - return key - -t = Test() -print(t[0]) -print(t[:10]) -print(t[4:7]) -slice_object = t[4:7] -print(slice_object.start) -print(slice_object.stop) -print(slice_object.step) -print(isinstance(t[4:8], slice)) -print(isinstance(t[4], slice)) ``` -[slice-notation]: https://docs.python.org/3/tutorial/introduction.html#strings -[slice-docs]: https://docs.python.org/3/library/functions.html#slice +### Krav + +* Programmet ska uppfylla alla krav nämnda i beskrivningen. +* All inmatning ska felhanteras med hjälp av lämplig hjälpfunktion. +* Din kod ska uppfylla kraven i rättningsmatrisen. + +### Kamraträttning +Denna laboration redovisas inte för en lärarassistent, utan kommer kamraträttas av en kurskamrat. När du lämnat in din kod på Canvas kommer du automatiskt bli tilldelad en annan persons kod, som du ska rätta utifrån den rättningsmatris som syns bredvid inlämningen. Ladda ner koden, provkör den på din dator och fyll sedan i rättningsmatrisen. Lämna gärna konstruktiva kommentarer för att hjälpa varandra att bli ännu bättre på att koda! -## Ytterligare extrauppgift +## Frivilliga extrauppgifter -Implementera [`__setitem__`][setitem] för `MultiplicativeSequenceFromFile` för -att sätta värden. När värdena sätts ska respektive $q$-värde beräknas från -föregående värde. Lägg till en metod `.save(filename)` som sparar alla -$q$-värden till en fil som kan läsas in med `MultiplicativeSequenceFromFile` -nästa körning. +### Hantera lärare -[setitem]: https://docs.python.org/3/reference/datamodel.html#object.__setitem__ +Lägg till en klass Person som klassen Student ärver ifrån, se [arv][arv]. +Skapa en till klass Teacher som också ärver från Person. Lägg till så att +klassen Skola har två attribut, en för studenter och en för lärare, alternativt +hitta på ett eget sätt att hålla isär elever och lärare i ditt program. +[arv]: https://docs.python.org/3/tutorial/classes.html#inheritance + +#### Exempelutskrift + +``` +... +Vad för roll har personen? Lärare +Vad heter personen? Albert Einstein +Vad är personens personnummer? 7903140050 + +Personen tillagd! + +Här är alla studenter på KTH: +Namn: Jan Jansson Personnr: 0404040010 +Namn: Per Persson Personnr: 0303030030 +Namn: Emma Emilsson Personnr: 0101010000 + +Här är alla lärare på KTH: +Namn: Albert Einsten Personnr: 7903140050 + +``` diff --git a/modules/classes/tutorial-advanced/.gitignore b/modules/classes/tutorial-advanced/.gitignore new file mode 100644 index 00000000..21feef11 --- /dev/null +++ b/modules/classes/tutorial-advanced/.gitignore @@ -0,0 +1 @@ +instruction.html diff --git a/modules/classes/tutorial-advanced/Makefile b/modules/classes/tutorial-advanced/Makefile new file mode 100644 index 00000000..c9d2ccd8 --- /dev/null +++ b/modules/classes/tutorial-advanced/Makefile @@ -0,0 +1,17 @@ +HTML_FILES= instruction.html + +PANDOCFLAGS= --filter pandoc-xnos + + +.PHONY: all +all: ${HTML_FILES} ${PDF_FILES} + +instruction.html: instruction.md + + +.PHONY: clean +clean: + ${RM} ${HTML_FILES} ${PDF_FILES} + + +include ../../../html.mk diff --git a/modules/classes/tutorial-advanced/address.py b/modules/classes/tutorial-advanced/address.py new file mode 100644 index 00000000..c2942846 --- /dev/null +++ b/modules/classes/tutorial-advanced/address.py @@ -0,0 +1,62 @@ +from dataclasses import dataclass +from typing import ClassVar +import input_type as it + + +@dataclass(frozen=True) +class Address: + """En address.""" + + DEFAULT_COUNTRY: ClassVar[str] = "Sweden" + """Om inget land specificeras under konstruktion av Address-objekt så blir + `DEFAULT_COUNTRY` det land som gäller. + """ + + street_name: str # gatunamnet, t.ex. "Sveavägen" + street_number: str # gatunumret, t.ex. "58" eller "2B" + postal_code: int # postnumret + town: str # orten + country: str = DEFAULT_COUNTRY # landets namn + + def __str__(self): + address_str = f"{self.street_name} {self.street_number}, " \ + f"{self.postal_code} {self.town}" + + if self.country != self.DEFAULT_COUNTRY: + address_str += " " + self.country + + return address_str + + +def input_address(prompt: str = "") -> Address: + """Låter användaren mata in data för en adress, + returnerar ett Address-objekt.""" + if prompt: + print(prompt) + + gata = input("Gatans namn: ") + nummer = input("Gatunummer: ") + postnummer = it.input_type(int, "Postnummer: ") + postort = input("Postort: ") + land = input(f"Land [blankt för {Address.DEFAULT_COUNTRY}]: ") + if not land: + land = Address.DEFAULT_COUNTRY + + return Address(gata, nummer, postnummer, postort, land) + + +def main(): + """Testprogram""" + daniels_kontor = Address("Lindstedtsvägen", "5", 11428, "Stockholm") + print(f"Daniel har sitt arbetsrum på adressen {daniels_kontor}.") + print(f"Gatan är {daniels_kontor.street_name}.") + + olles_kontor = Address("Lindstedtsvägen", "3", 11428, "Stockholm") + if daniels_kontor == olles_kontor: + print("Daniel och Olle har arbetsrum på samma adress.") + else: + print("Daniel och Olle har inte arbetsrum på samma adress.") + + +if __name__ == "__main__": + main() diff --git a/modules/classes/tutorial-advanced/bank.py b/modules/classes/tutorial-advanced/bank.py new file mode 100644 index 00000000..252fbad1 --- /dev/null +++ b/modules/classes/tutorial-advanced/bank.py @@ -0,0 +1,188 @@ +from citizen import Citizen +from address import Address, input_address +import input_type as it +from dataclasses import dataclass +from typing import List, Tuple + + +@dataclass(frozen=True) +class ClientProfile: + """Klient hos en bank.""" + citizen: Citizen # medborgaren som ska vara en klient + phone_number: int # medborgarens telefonnummer + + def __str__(self): + return f"{self.citizen} (telefon nummer: {self.phone_number})" + + +class Account: + """Bankkonto.""" + def __init__(self, account_id: int, password: str, + owner_profile: ClientProfile): + """`account_id` är ett unikt kontonummer hos en bank. + `password` är lösenordet. Krav: minst 8 symboler lång. + `owner_profile` är profilen till ägaren. + """ + self.__account_id = account_id + self.__owner_profile = owner_profile + self.__balance = 0.0 + self.__password = None # Obs: Här deklarerar vi bara att attributet + # `__password` finns, och vi låter set_password-metoden tilldela kontot + # sitt lösenord för att slippa kod-duplicering. + self.set_password(password) + + def __str__(self): + return str(self.__account_id) + + def __repr__(self): + return f"Account({self.__account_id}, '{self.__password}', " \ + f"{self.__balance})" + + @property + def account_id(self) -> int: + """Kontonummer.""" + return self.__account_id + + @property + def owner_profile(self) -> ClientProfile: + """Kontonummer.""" + return self.__owner_profile + + @property + def balance(self) -> float: + """Kontots saldo.""" + return self.__balance + + def insert_money(self, amount: float): + """Sätt in pengar.""" + self.__balance += amount + + def withdraw_money(self, amount: float): + """Tar ut en summa pengar från kontot, + kastar ett särfall ValueError vid för lite täckning på kontot""" + if self.__balance < amount: + raise ValueError(f"kontot saknar täckning, saldot {self.__balance} " + f"är mindre än uttaget {amount}.") + + self.__balance -= amount + + def set_password(self, password: str): + """Byt lösenord. Krav: minst 8 bokstäver.""" + if len(password) < 8: + raise ValueError("bankkontolösenordet är för kort.") + + self.__password = password + + def check_password(self, password: str) -> bool: + """Är lösenordet korrekt?""" + return self.__password == password + + +class Bank: + """En bank.""" + def __init__(self, name: str): + """`name` är namnet på banken.""" + self.__name = name + # Personnummer till respektive klients ClientProfile-objekt: + self.__clients = {} + # Kontonummer till respektive Account-objekt: + self.__accounts = {} + # Personnummer till respektive Account-objekt (värdet är en lista): + self.__client_accounts = {} + # Följande hjälper oss att hitta på unika ID nummer för nya konton: + self.__account_id_autoincrement = 1 + + def __str__(self): + return self.__name + + def __repr__(self): + return f"Bank({self.__name}, {len(self.__clients)} clients, " \ + f"{len(self.__accounts)} accounts)" + + @property + def name(self) -> str: + return self.__name + + def create_account(self, personal_id: int, password: str) -> Account: + """Skapar ett nytt konto åt klienten med personnumret `personal_id`, + returnerar det nya kontot. `password` blir kontots lösenord. + Se Account-klassen för krav på lösenordet.""" + owner_profile = self.__get_client_profile2(personal_id) + new_account_id = self.__account_id_autoincrement + account = Account(new_account_id, password, owner_profile) + self.__accounts[account.account_id] = account + self.__account_id_autoincrement += 1 + self.__client_accounts[personal_id].append(account) + return account + + def __get_client_profile2(self, personal_id: int) -> ClientProfile: + """Är personen en klient? Om ja, returnera klientens profil. + Om inte, släng ett ValueError.""" + try: + return self.get_client_profile(personal_id) + except KeyError: + raise ValueError(f"medborgare med personnummer {personal_id} " + f"är inte en klient.") + + def add_client(self, citizen: Citizen, phone_number: int): + """Lägger till en ny klient.""" + self.__clients[citizen.personal_id] = \ + ClientProfile(citizen, phone_number) + self.__client_accounts[citizen.personal_id] = [] + + def get_client_accounts(self, personal_id: int) -> List[Account]: + """Lista med alla konton som tillhör en klient.""" + self.__get_client_profile2(personal_id) + try: + return self.__client_accounts[personal_id].copy() + except KeyError: + return [] + + def get_client_profile(self, personal_id: int) -> ClientProfile: + """Returnerar profil till klient med personnumret `personal_id`, + om inte denne är en klient så kastas ett KeyError.""" + return self.__clients[personal_id] + + def get_account(self, account_id: int) -> Account: + """Returnerar ett konto med kontonumret `account_id`, om kontot inte + existerar så kastas ett KeyError.""" + return self.__accounts[account_id] + + +def input_client(prompt: str = "") -> Tuple[Citizen, int]: + """Låter användaren mata in uppgifter för en kund, + returnerar ett Client-objekt""" + if prompt: + print(prompt) + + full_name = input("Fullständigt namn: ") + personal_id = it.input_type(int, "Personnummer: ") + address = input_address() + phone_number = it.input_type(int, "Telefonnummer: ") + + return Citizen(full_name, personal_id, address, []), phone_number + + +def main(): + bank = Bank("LåtsasBanken") + + # Specificera medborgaren som ska bli en ny klient hos LåtsasBanken + vilmas_id = 9911037621 + vilmas_address = Address("Trollgatan", "1", 50641, "Borås") + vilma = Citizen("Vilma (totally legit) Andersson", vilmas_id, + vilmas_address, []) + + # Lägg till klient och skapa ett nya konton + bank.add_client(vilma, 5555555) + student_account = bank.create_account(vilmas_id, "pa$$word") + savings_account = bank.create_account(vilmas_id, "pa$$word2") + + student_account.insert_money(100.0) + student_account.withdraw_money(71.5) + savings_account.insert_money(71.5) + + print(bank.get_client_accounts(vilmas_id)) + + +if __name__ == "__main__": + main() diff --git a/modules/classes/tutorial-advanced/bank_program.py b/modules/classes/tutorial-advanced/bank_program.py new file mode 100644 index 00000000..6907f8e0 --- /dev/null +++ b/modules/classes/tutorial-advanced/bank_program.py @@ -0,0 +1,125 @@ +from bank import * +import input_type as it + + +def menu(bank: Bank) -> int: + """Skriver ut menyn, låter användaren välja ett alternativ. + Returnerar ett korrekt alternativ.""" + print(f"Välkommen till {bank}, hur kan vi hjälpa dig?") + print(""" +[1] Avsluta. +[2] Registrera dig som klient. +[3] Skapa ett konto. +[4] Se dina konton. +[5] Sätt in pengar. +[6] Ta ut pengar. +""") + choice = it.input_type(int, "Välj ett alternativ: ") + while choice < 1 or choice > 6: + print("Tyvärr är det inte ett giltigt alternativ, försök igen, " + "talet måste vara 1, 2, 3, 4, 5 eller 6.") + choice = it.input_type(int, "Välj ett alternativ: ") + + return choice + + +def register_client(bank: Bank): + """Menyvalet att registrera en ny klient.""" + try: + citizen, phone_number = input_client("Registrera dig som klient genom " + "att fylla i formuläret.") + bank.add_client(citizen, phone_number) + except KeyError: + print("Tyvärr verkar du redan vara registrerad som klient.") + except ValueError: + print("Namnet du angav var ogiltigt.") + + +def create_account(bank: Bank): + """Menyvalet att skapa ett konto.""" + personal_id = it.input_type(int, "Ange ditt personnummer: ") + password = input("Ange ett lösenord för kontot: ") + try: + bank.create_account(personal_id, password) + except KeyError: + print(f"Finns ingen klient med personnummer {personal_id}.") + except ValueError: + print("Lösenordet är för kort.") + + +def list_accounts(bank: Bank): + """Listar klientens konton.""" + personal_id = it.input_type(int, "Ange personnummer: ") + try: + accounts = bank.get_client_accounts(personal_id) + except ValueError: + print(f"Finns ingen klient med personnummer {personal_id}.") + return + + for account in accounts: + print(f"{account}: {account.balance} kr") + + +def get_account(bank: Bank) -> Account: + """Låt användaren mata in kontonummer och hämta konto.""" + account_id = it.input_type(int, "Ange kontonummer: ") + try: + account = bank.get_account(account_id) + except KeyError: + print(f"Tyvärr finns inte något konto {account_id}.") + account = None + + return account + + +def insert_money(account: Account): + """Låter användaren mata in summa att sätta in på konto.""" + amount = it.input_type(int, "Ange summa att sätta in: ") + account.insert_money(amount) + + +def withdraw_money(account: Account): + """Låter användaren mata in summa att ta ut från konto.""" + personal_id = it.input_type(int, "Ange ägarens personnummer: ") + password = input("Ange kontots lösenord: ") + if account.owner_profile.citizen.personal_id != personal_id or \ + not account.check_password(password): + print("Tyvärr autentiseringen misslyckades!") + return + + while True: + amount = it.input_type(int, "Ange summa att ta ut: ") + try: + account.withdraw_money(amount) + return + except ValueError as error: + print(error) + + +def main(): + """Huvudprogram""" + bank = Bank("Sveriges Riksbank") + + choice = menu(bank) + while choice != 1: + if choice == 2: + register_client(bank) + elif choice == 3: + create_account(bank) + elif choice == 4: + list_accounts(bank) + elif choice == 5 or choice == 6: + account = get_account(bank) + if not account: + continue + + if choice == 5: + insert_money(account) + else: + withdraw_money(account) + + choice = menu(bank) + + +if __name__ == "__main__": + main() diff --git a/modules/classes/tutorial-advanced/citizen.py b/modules/classes/tutorial-advanced/citizen.py new file mode 100644 index 00000000..1d7234b5 --- /dev/null +++ b/modules/classes/tutorial-advanced/citizen.py @@ -0,0 +1,52 @@ +from typing import Collection, Tuple +from person import Person +from address import Address + + +# Obs: Detta är ett exempel på arv där Citizen-klassen ärver egenskaper från +# Person-klassen. På så vis kan man skapa klasser för personer med mer +# "specialiserade" egenskaper (t.ex. att de är medborgare) utan att behöva +# skriva om alla metoder. +class Citizen(Person): + """En medborgare.""" + + def __init__(self, full_name: str, personal_id: int, address: Address, + parents: Collection[Person]): + """ + `full_name` är personens är medborgarens fullständiga namn. + Krav: minst ett mellanrum måste existera. + `personal_id` är personnumret. + `address` är medborgarens registrerade address. + `parents` medborgarens föräldrar (max 2 stycken). + """ + try: + first_name, last_name = full_name.split(maxsplit=1) + except ValueError: + raise ValueError("ett fullständigt namn måste bestå av åtminstone " + "ett mellanrum.") + + super(Citizen, self).__init__(first_name, last_name, address) + self.__personal_id = personal_id + + if len(parents) > 2: + raise ValueError("en medborgare kan inte ha fler än två föräldrar.") + + for parent in parents: + if not isinstance(parent, Person): + raise ValueError("`parents` får endast innehålla " + "Person-objekt.") + + # `parents` kan vara vilket itererbart objekt som helst + # (lista, tupel, etc.). Vi vill att `self.__parents` ska vara en tupel, + # och inget annat, så vi konstruerar en tupel från `parents`. + self.__parents = tuple(parents) + + @property + def personal_id(self) -> int: + """Personens personnummer.""" + return self.__personal_id + + @property + def parents(self) -> Collection[Person]: + """Returnerar en tupel med medborgarens föräldrar (Person-objekt).""" + return self.__parents diff --git a/modules/classes/tutorial/frac.py b/modules/classes/tutorial-advanced/frac.py similarity index 87% rename from modules/classes/tutorial/frac.py rename to modules/classes/tutorial-advanced/frac.py index ddf99d45..649d0ce5 100644 --- a/modules/classes/tutorial/frac.py +++ b/modules/classes/tutorial-advanced/frac.py @@ -1,8 +1,10 @@ """ Fractions library """ + class Fraction: """ Class for fractions """ - def __init__(self, nominator, denominator=1): + def __init__(self, nominator: int | str | "Fraction", + denominator: int | "Fraction" = 1): self.__nominator = 1 self.__denominator = 1 @@ -27,13 +29,13 @@ def __init__(self, nominator, denominator=1): raise TypeError(f"can't create fraction from {type(nominator)}") @property - def nominator(self): + def nominator(self) -> int: """nominator getter""" return self.__nominator @property - def denominator(self): - """demoninator getter""" + def denominator(self) -> int: + """denominator getter""" return self.__denominator def __str__(self): @@ -90,16 +92,16 @@ def main(): """Test program""" frac_a = Fraction(1, 2) frac_b = Fraction(2, 4) - if frac_a == frac_b: # frac_a.__eq__(frac_b) + if frac_a == frac_b: # frac_a.__eq__(frac_b) print(f"{frac_a} = {frac_b}") - elif frac_a > frac_b: # frac_a.__gt__(frac_b) --> not (a <= b) + elif frac_a > frac_b: # frac_a.__gt__(frac_b) --> not (a <= b) print(f"{frac_a} > {frac_b}") - elif frac_a < frac_b: # frac_a.__lt__(frac_b) + elif frac_a < frac_b: # frac_a.__lt__(frac_b) print(f"{frac_a} <= {frac_b}") fracs = sorted([Fraction(1, 2), Fraction(1, 3), Fraction(1, 4)]) - #fracs = [Fraction(1, 2), Fraction(1, 3), Fraction(1, 4)] - #fracs.sort() + # fracs = [Fraction(1, 2), Fraction(1, 3), Fraction(1, 4)] + # fracs.sort() for frac in fracs: print(frac) @@ -109,5 +111,6 @@ def main(): frac_test = Fraction("1/2") print(f"1/2 blir {frac_test}") + if __name__ == "__main__": main() diff --git a/modules/classes/tutorial-advanced/input_type.py b/modules/classes/tutorial-advanced/input_type.py new file mode 100644 index 00000000..6149af07 --- /dev/null +++ b/modules/classes/tutorial-advanced/input_type.py @@ -0,0 +1,29 @@ +"""Take input more easily.""" + + +def input_type(t: type, prompt: str = ""): + """Take input, convert to type t; repeat if error.""" + while True: + try: + return t(input(prompt)) + except ValueError: + if t == int: + print(f"Sorry, can't convert to integer.") + else: + print(f"Sorry, can't convert to {t}.") + + +def main(): + """Test functionality of this module""" + x = input_type(int, "x = ") + y = input_type(int, "y = ") + z = input_type(float, "z = ") + name = input_type(str, "Your name: ") + + print(f"{x} + {y} = {x+y}") + print(f"z = {z}") + print(f"Your name is {name}") + + +if __name__ == "__main__": + main() diff --git a/modules/classes/tutorial-advanced/instruction.md b/modules/classes/tutorial-advanced/instruction.md new file mode 100644 index 00000000..112ee8ce --- /dev/null +++ b/modules/classes/tutorial-advanced/instruction.md @@ -0,0 +1,92 @@ +--- +title: Övning om klasser och objekt +authors: + - Daniel Bosk + - Celina Soori + - Mazen Mardini +--- +# Fördjupande övning: klasser och objekt + +Målet med övningen är att du ska få en djupare förståelse för hur du ska + + - använda och konstruera sammansatta datatyper (klasser), + - tillämpa behållare för att lagra mängder med data, + - tillämpa olika former av upprepningar för att arbeta med data, + - dela upp problem i mindre problem, + - minimera kodupprepning, + - leta i Pythons dokumentation. + + +## Önskemål från gruppen + +Var det något särskilt från veckans föreläsning och/eller OLI-material som gruppen vill gå in djupare på? + +Är det någon som vill visa upp något särskilt från förra veckans laboration som kan ge inspiration till gruppen? + +### Finn fem fel + + +[Gissningsspelet](https://github.com/dbosk/intropy/blob/master/modules/containers/tutorial/guess.py) låter användaren gissa. + +Läs igenom koden och få ett hum om vad den är tänkt att göra. Testa att köra koden. + +Hitta nu tillsammans minst fem fel/utvecklingsområden i koden (tänk på vad ni lärt er under veckan). + +Förbättra nu koden efter det ni hittat. Blev koden mer lättläst, användbar och/eller användarvänlig? Varför? + +[Lösningsförslag](https://github.com/dbosk/intropy/blob/master/modules/containers/tutorial/guess-good.py) + +### Bankkontot + +Vi ska skriva ett enkelt program som hanterar konton åt en bank. Vi behöver en +sammansatt datatyp (klass) som kan representera ett bankkonto: + + - Det ska lagra ägarens uppgifter. Ägaren är en person. (Hm, kanske vi har en + klass lämplig för att spara en persons data? Hint: se folkbokföringen + ovan.) + - Det ska lagra nuvarande saldo. + - Det ska gå att sätta in pengar. + - Det ska gå att ta ut pengar, men bara om det finns tillräckligt med pengar + på kontot. Inga negativa saldon! + +Lösningsförslag: + + - [En modul med klasser för en bank, bank.py][bank.py] + - [Ett program med gränssnitt för en bank, bank_program.py][bank_program.py] + - [En modul med en personklass, person.py][bank_program.py] + - [En modul med en medborgarklass, citizen.py][citizen.py] + - [En modul med en adressklass, address.py][address.py] + - [En modul för inmatning av specifika typer, input_type.py][input_type.py] + +[bank.py]: https://github.com/dbosk/intropy/blob/master/modules/classes/tutorial-advanced/bank.py +[bank_program.py]: https://github.com/dbosk/intropy/blob/master/modules/classes/tutorial-advanced/bank_program.py +[address.py]: https://github.com/dbosk/intropy/blob/master/modules/classes/tutorial-advanced/address.py +[citizen.py]: https://github.com/dbosk/intropy/blob/master/modules/classes/tutorial-advanced/citizen.py +[person.py]: https://github.com/dbosk/intropy/blob/master/modules/classes/tutorial-advanced/person.py +[input_type.py]: https://github.com/dbosk/intropy/blob/master/modules/classes/tutorial-advanced/input_type.py + + +### En bråkig klass + +Vi vill ha en klass för att räkna med rationella tal, eller bråk. Vi ska kunna: + + - skapa bråk, exempelvis `a = Bråk(1, 3)` och `b = Bråk(2, 6)`; + - jämföra bråk, exempelvis `a == b` eller `a < b`; + - skriva ut bråk på läsbar form, exempelvis `print(f"{a} och {b}")` ger + utskriften `1/3 och 2/6`. + - addera, subtrahera, multiplicera och dividera bråk. + - typkonvertera bråket till ett flyttal (`float`). + - förkorta bråk, exempelvis så att `b` (som är 2/6) kan förkortas till 1/3. + +Detta kräver en del specialmetoder. Se [dokumentationen för Pythons +specialmetoder för jämförelse][doc-cmp] och [dokumentationen för Pythons +specialmetoder för att emulera numeriska typer][doc-numtypemethods]. + +[doc-cmp]: https://docs.python.org/3/reference/datamodel.html#object.__lt__ +[doc-numtypemethods]: https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types + +Lösningsförslag: + + - [Lösningsförslag: en modul med en klass för bråktal, frac.py][frac.py] + +[frac.py]: https://github.com/dbosk/intropy/blob/master/modules/classes/tutorial/frac.py diff --git a/modules/classes/tutorial-advanced/person.py b/modules/classes/tutorial-advanced/person.py new file mode 100644 index 00000000..68200a02 --- /dev/null +++ b/modules/classes/tutorial-advanced/person.py @@ -0,0 +1,112 @@ +from address import Address + + +class Person: + """En person.""" + + def __init__(self, first_name: str, last_name: str, address: Address): + """`first_name` är förnamnet (sträng). + `last_name` är efternamnet (sträng). + `address` är adressen (Address-objekt). + """ + self.__first_name = first_name + self.__last_name = last_name + self.__address = address + + # Obs: __str__-metoden används för att ge en användarvänlig + # sträng-representation av objektet. + def __str__(self): + """Personens fullständiga namn.""" + return self.full_name + + # Obs: __repr__-metoden används för att ge en sträng-representation + # av objektet som är hjälpsam + # för programmeraren. + def __repr__(self): + """En sträng som innehåller alla attribut.""" + return f"Person({self.__first_name}, {self.__last_name}, " \ + f"{repr(self.__address)})" + + # Obs: @property gör att vi inte behöver parenteserna: + # `kund.namn` istället för `kund.namn()` + @property + def first_name(self) -> str: + """Personens förnamn.""" + return self.__first_name.capitalize() + + @property + def last_name(self) -> str: + """Personens efternamn.""" + return self.__last_name.capitalize() + + @property + def full_name(self) -> str: + """Personens fullständiga namn.""" + return self.first_name + " " + self.last_name + + @property + def address(self) -> Address: + """Personens adress.""" + return self.__address + + # Obs: "*" betyder att alla efterkommande parametrar måste explicit anges i + # ett anrop om du väljer att tilldela dem värden. Till exempel är + # "person.change_name('Olle', 'Ohlsson')" inte tillåtet, men + # "person.change_name(first_name='Olle', last_name='Ohlsson')" är det. + def change_name(self, *, first_name: str | None = None, + last_name: str | None = None): + """Byt personens för- och/eller efternamn. + + Om parametern `first_name` eller `last_name` är None så byts det + inte ut. + + Exempel: + >> person.change_name() # Gör ingenting + >> person.change_name(last_name="Stonkman") # Byter efternamnet till + "Stonkman" + """ + if first_name: + self.__first_name = first_name + + if last_name: + self.__last_name = last_name + + def __lt__(self, other): + """Gör så att operatorn < jämför personer baserat på deras namn.""" + return self.full_name < other.full_name + + +def main(): + """ Test program """ + + # Skapa ett Person-objekt + person = Person("Anne-Marie", "Ingeström", Address("Odengatan", "1", + 11424, "Stockholm")) + print(f"{person} bor på adressen {person.address}.") + + # Byt namn + person.change_name(first_name="Margareta", last_name="Engström") + print(f"{person} bor på adressen {person.address}") + + # Skapa ett annat Person-objekt + person2 = Person("Ada", "Bedasdotter", Address("Uttervägen", "12", + 98137, "Kiruna")) + + # Jämför objekten (använder __lt__-metoden implicit) + if person < person2: + print(f"{person} sorteras före {person2}.") + else: + print(f"{person2} sorteras före {person}.") + + people = [person, person2] + + # När man skriver ut en lista så används __repr__-metoden för alla element + print(people) + + # Vi kan sortera listan eftersom < operatorn är definierad för Person-objekt + people.sort() + print(people) + + +if __name__ == "__main__": + main() diff --git a/modules/classes/tutorial/address.py b/modules/classes/tutorial/address.py new file mode 100644 index 00000000..d5ae2960 --- /dev/null +++ b/modules/classes/tutorial/address.py @@ -0,0 +1,92 @@ +import input_type as it + + +class Address: + """En address.""" + + DEFAULT_COUNTRY = "Sweden" + """Om inget land specificeras under konstruktion av Address-objekt så blir + `DEFAULT_COUNTRY` det land som gäller. + """ + + def __init__(self, street_name, street_number, postal_code, town, + country=DEFAULT_COUNTRY): + """`street_name` är gatunamnet, t.ex. "Sveavägen" (sträng). + `street_number` är gatunumret, t.ex. "58" eller "2B" (sträng). + `postal_code` är postnumret (sträng). + `town` är orten (sträng). + `country` är landets namn (sträng). + """ + self.__street_name = street_name + self.__street_number = street_number + self.__postal_code = postal_code + self.__town = town + self.__country = country + + def __str__(self): + address_str = f"{self.street_name} {self.street_number}, " \ + f"{self.postal_code} {self.town}" + + if self.__country != self.DEFAULT_COUNTRY: + address_str += " " + self.country + + return address_str + + @property + def street_name(self): + """Gatunamnet.""" + return self.__street_name + + @property + def street_number(self): + """Gatunumret.""" + return self.__street_number + + @property + def postal_code(self): + """Postnumret.""" + return self.__postal_code + + @property + def town(self): + """Orten.""" + return self.__town + + @property + def country(self): + """Landets namn.""" + return self.__country + + +def input_address(prompt=""): + """Låter användaren mata in data för en adress, + returnerar ett Address-objekt.""" + if prompt: + print(prompt) + + gata = input("Gatans namn: ") + nummer = input("Gatunummer: ") + postnummer = it.input_type(int, "Postnummer: ") + postort = input("Postort: ") + land = input(f"Land [blankt för {Address.DEFAULT_COUNTRY}]: ") + if not land: + land = Address.DEFAULT_COUNTRY + + return Address(gata, nummer, postnummer, postort, land) + + +def main(): + """Testprogram""" + daniels_kontor = Address("Lindstedtsvägen", "5", "11428", "Stockholm") + print(f"Daniel har sitt arbetsrum på adressen {daniels_kontor}.") + print(f"Gatan är {daniels_kontor.street_name}.") + + olles_kontor = Address("Lindstedtsvägen", "3", "11428", "Stockholm") + if daniels_kontor == olles_kontor: + print("Daniel och Olle har arbetsrum på samma adress.") + else: + print("Daniel och Olle har inte arbetsrum på samma adress.") + + +if __name__ == "__main__": + main() diff --git a/modules/classes/tutorial/adress.py b/modules/classes/tutorial/adress.py deleted file mode 100644 index 7fe4bc6e..00000000 --- a/modules/classes/tutorial/adress.py +++ /dev/null @@ -1,70 +0,0 @@ -"""Modul med en klass för att hantera adresser""" - -class Adress: - """Klass för att hantera adresser""" - def __init__(self, gata, nummer, postnummer, postort, - land="Sverige"): - """Returnerar ett adressobjekt""" - self.__gata = gata - self.__nummer = nummer - self.__postnummer = postnummer - self.__postort = postort - self.__land = land - - def __str__(self): - """Returnerar sträng för utskrift""" - adress = f"{self.__gata} {self.__nummer}, " + \ - f"{self.__postnummer} {self.__postort}" - - if self.__land != "Sverige": - adress += f", {self.__land}" - - return adress - - def gatan(self): - """Returnerar gatan i adressen""" - return self.__gata - - def orten(self): - """Returnerar numret i adressen""" - return self.__postort - - def __eq__(self, other): - """Jämför två adresser, returnerar True om de är identiska""" - return self.__gata == other.__gata and \ - self.__nummer == other.__nummer and \ - self.__postnummer == other.__postnummer and \ - self.__postort == other.__postort and \ - self.__land == other.__land - -def input_adress(prompt=""): - """Låter användaren mata in data för en adress, - returnerar ett Adress-objekt""" - if prompt: - print(prompt) - - gata = input("Gatans namn: ") - nummer = input("Gatunummer: ") - postnummer = input("Postnummer: ") - postort = input("Postort: ") - land = input("Land [blankt för Sverige]: ") - if not land: - land = "Sverige" - - return Adress(gata, nummer, postnummer, postort, land) - - -def main(): - """Testprogram""" - daniels_kontor = Adress("Lindstedtsvägen", "5", "11428", "Stockholm") - print(f"Daniel har sitt arbtesrum på adressen {daniels_kontor}.") - print(f"Gatan är {daniels_kontor.gatan()}.") - - olles_kontor = Adress("Lindstedtsvägen", "3", "11428", "Stockholm") - if daniels_kontor == olles_kontor: - print("Daniel och Olle har arbetsrum på samma adress.") - else: - print("Daniel och Olle har inte arbetsrum på samma adress.") - -if __name__ == "__main__": - main() diff --git a/modules/classes/tutorial/bank.py b/modules/classes/tutorial/bank.py index 98208a41..fed1cd05 100644 --- a/modules/classes/tutorial/bank.py +++ b/modules/classes/tutorial/bank.py @@ -1,183 +1,198 @@ -"""En modul för bankrelaterade klasser""" +from citizen import Citizen +from address import Address, input_address +import input_type as it -import adress -class Kund: - """En klass för kunder""" - - def __init__(self, namn, personnummer, adress, telefon): - """Skapar en bankkund: namn (sträng), personnummer (sträng), adress - (Adress-objekt), telefon (sträng)""" - self.__namn = namn - self.__personnummer = personnummer - self.__adress = adress - self.__telefon = telefon - self.__konton = [] - - # @property gör att vi inte behöver parenteserna: - # `kund.namn` istället för `kund.namn()` - @property - def namn(self): - """ Returnerar namnet""" - return self.__namn +class ClientProfile: + """Klient hos en bank.""" + def __init__(self, citizen, phone_number): + self.__citizen = citizen + self.__phone_number = phone_number def __str__(self): - """Returnerar en strängrepresentation lämpligt för utskrift""" - return self.namn + return f"{self.citizen} (telefon nummer: {self.phone_number})" + + def __repr__(self): + return f"ClientProfile({repr(self.citizen)}, {self.phone_number})" @property - def personnummer(self): - """ Returnera personnummer """ - return self.__personnummer + def citizen(self): + """Klienten som profilen avser.""" + return self.__citizen @property - def adress(self): - """ Returnera adress """ - return self.__adress + def phone_number(self): + """Klientens telefonnummer.""" + return self.__phone_number + + +class Account: + """Bankkonto.""" + def __init__(self, account_id, password, owner_profile): + """`account_id` är ett unikt kontonummer hos en bank (heltal). + `password` är lösenordet (sträng)..Krav: minst 8 symboler lång. + `owner_profile` är profilen till ägaren (ClientProfile). + """ + self.__account_id = account_id + self.__owner_profile = owner_profile + self.__balance = 0.0 + self.__password = None # Obs: Här deklarerar vi bara att attributet + # `__password` finns, och vi låter set_password-metoden tilldela kontot + # sitt lösenord för att slippa kod-duplicering. + self.set_password(password) + + def __str__(self): + return str(self.__account_id) def __repr__(self): - """Returns unique representation""" - return f"({self.namn}, {self.personnummer}" + return f"Account({self.__account_id}, '{self.__password}', " \ + f"{self.__balance})" @property - def telefon(self): - """Returnerar telefonnumret""" - return self.__telefon + def account_id(self): + """Kontonummer.""" + return self.__account_id - def lägg_till_konto(self, konto): - """Lägger till konto till kundens konton""" - self.__konton.append(konto) + @property + def owner_profile(self): + """Kontonummer.""" + return self.__owner_profile @property - def konton(self): - """Returnerar en lista med kundens konton""" - return self.__konton.copy() + def balance(self): + """Kontots saldo.""" + return self.__balance -def input_kund(prompt=""): - """Låter användaren mata in uppgifter för en kund, - returnerar ett Kund-objekt""" - if prompt: - print(prompt) + def insert_money(self, amount): + """Sätt in pengar.""" + self.__balance += amount - namn = input("Fullständigt namn: ") - personnummer = input("Personnummer: ") - adressen = adress.input_adress() - telefon = input("Telefonnummer: ") + def withdraw_money(self, amount): + """Tar ut en summa pengar från kontot, + kastar ett särfall ValueError vid för lite täckning på kontot""" + if self.__balance < amount: + raise ValueError(f"kontot saknar täckning, saldot {self.__balance} " + f"är mindre än uttaget {amount}.") - return Kund(namn, personnummer, adressen, telefon) + self.__balance -= amount -class Konto: - """Ett bankkonto""" + def set_password(self, password): + """Byt lösenord. Krav: minst 8 bokstäver.""" + if len(password) < 8: + raise ValueError("bankkontolösenordet är för kort.") - def __init__(self, ägare, konto_id, saldo=0): - """Skapar ett bankkonto: - ägare är en Kund, - konto_id är en textsträng, - saldo är ett tal (int eller float, default 0)""" - self.__owner = ägare - self.__account_id = konto_id - self.__amount = saldo - self.__lösneord = "" + self.__password = password - @property - def ägare(self): - """Returnerar ägaren""" - return self.__owner + def check_password(self, password): + """Är lösenordet korrekt?""" + return self.__password == password - @property - def kontonr(self): - """Returnerar kontonumret""" - return self.__account_id + +class Bank: + """En bank.""" + def __init__(self, name): + """`name` är namnet på banken.""" + self.__name = name + # Personnummer till respektive klients ClientProfile-objekt: + self.__clients = {} + # Kontonummer till respektive Account-objekt: + self.__accounts = {} + # Personnummer till respektive Account-objekt (värdet är en lista): + self.__client_accounts = {} + # Följande hjälper oss att hitta på unika ID nummer för nya konton: + self.__account_id_autoincrement = 1 def __str__(self): - return str(self.kontonr) + return self.__name - def sätt_in(self, summa): - """Sätter in en summa pengar på kontot""" - self.__amount += summa + def __repr__(self): + return f"Bank({self.__name}, {len(self.__clients)} clients, " \ + f"{len(self.__accounts)} accounts)" @property - def saldo(self): - """Returnerar kontots saldo""" - return self.__amount - - def ta_ut(self, summa): - """Tar ut en summa pengar från kontot, - kastar ett särfall ValueError vid för lite täckning på kontot""" - if self.__amount - summa < 0: - raise ValueError(f"kontot saknar täckning, " - f"saldot {self.__amount} är mindre än " - f"uttaget {summa}") - - self.__amount -= summa - - def sätt_lösenord(self, lösenord): - """Sätter ett lösenord för kontot""" - self.__lösenord = lösenord - - def korrekt_lösenord(self, lösenord): - """Returnerar True om lösenordet matchar""" - return self.__lösenord == lösenord - -class Bank: - """Klass för en bank""" + def name(self): + return self.__name + + def create_account(self, personal_id, password): + """Skapar ett nytt konto åt klienten med personnumret `personal_id`, + returnerar det nya kontot. `password` blir kontots lösenord. + Se Account-klassen för krav på lösenordet.""" + owner_profile = self.__get_client_profile2(personal_id) + new_account_id = self.__account_id_autoincrement + account = Account(new_account_id, password, owner_profile) + self.__accounts[account.account_id] = account + self.__account_id_autoincrement += 1 + self.__client_accounts[personal_id].append(account) + return account + + def __get_client_profile2(self, personal_id): + """Är personen en klient? Om ja, returnera klientens profil. + Om inte, släng ett ValueError.""" + try: + return self.get_client_profile(personal_id) + except KeyError: + raise ValueError(f"medborgare med personnummer {personal_id} " + f"är inte en klient.") + + def add_client(self, citizen, phone_number): + """Lägger till en ny klient.""" + self.__clients[citizen.personal_id] = \ + ClientProfile(citizen, phone_number) + self.__client_accounts[citizen.personal_id] = [] + + def get_client_accounts(self, personal_id): + """Lista med alla konton som tillhör en klient.""" + self.__get_client_profile2(personal_id) + try: + return self.__client_accounts[personal_id].copy() + except KeyError: + return [] + + def get_client_profile(self, personal_id): + """Returnerar profil till klient med personnumret `personal_id`, + om inte denne är en klient så kastas ett KeyError.""" + return self.__clients[personal_id] + + def get_account(self, account_id): + """Returnerar ett konto med kontonumret `account_id`, om kontot inte + existerar så kastas ett KeyError.""" + return self.__accounts[account_id] + + +def input_client(prompt=""): + """Låter användaren mata in uppgifter för en kund, + returnerar ett Client-objekt""" + if prompt: + print(prompt) - def __init__(self, namn): - """Skapa en bank med namnet namn""" - self.__namn = namn - self.__kunder = {} - self.__konton = {} - self.__nuvarande_kontonr = 0 + full_name = input("Fullständigt namn: ") + personal_id = it.input_type(int, "Personnummer: ") + address = input_address() + phone_number = it.input_type(int, "Telefonnummer: ") - def __str__(self): - """Returnerar en strängformaterat representation""" - return self.__namn + return Citizen(full_name, personal_id, address, []), phone_number - def registrera_kund(self, kund): - """Registrera kunden kund (Kund-objekt) som kund i banken. - kund får inte vara registrerad, då kastas ett KeyError.""" - if kund.personnummer in self.__kunder: - raise KeyError(f"{kund} är redan registrerad som kund.") - self.__kunder[kund.personnummer] = kund +def main(): + bank = Bank("LåtsasBanken") - def hämta_kund(self, personnummer): - """Returnerar kund med personnummer personnummer""" - return self.__kunder[personnummer] + # Specificera medborgaren som ska bli en ny klient hos LåtsasBanken + vilmas_id = 9911037621 + vilmas_address = Address("Trollgatan", "1", 50641, "Borås") + vilma = Citizen("Vilma (totally legit) Andersson", vilmas_id, + vilmas_address, []) - def skapa_konto(self, personnummer): - """Skapa ett nytt konto åt kunden med personnumret personnummer, - returnerar det nya kontot""" - kund = self.hämta_kund(personnummer) - konto = Konto(kund, self.__nuvarande_kontonr+1) - self.__konton[konto.kontonr] = konto - self.__nuvarande_kontonr += 1 - kund.lägg_till_konto(konto) - return konto + # Lägg till klient och skapa ett nya konton + bank.add_client(vilma, 5555555) + student_account = bank.create_account(vilmas_id, "pa$$word") + savings_account = bank.create_account(vilmas_id, "pa$$word2") - def hämta_konto(self, kontonr): - """Returnerar Konto-objektet med kontonumret kontonr, - kastar KeyError om kontonumret inte finns""" - return self.__konton[int(kontonr)] + student_account.insert_money(100.0) + student_account.withdraw_money(71.5) + savings_account.insert_money(71.5) + print(bank.get_client_accounts(vilmas_id)) -def main(): - """Testprogram""" - kund = Kund("Ada Adamsdotter", "1999-01-01-xxxx", - adress.Adress("Stora vägen", "1", "12345", "Orten"), - "070-1234567") - konto = Konto(kund, "123-456-789") - - print(f"{konto.ägare} har {konto.saldo} kr på {konto}") - konto.sätt_in(500) - print(f"{konto.ägare} har {konto.saldo} kr på {konto}") - konto.ta_ut(200) - print(f"{konto.ägare} har {konto.saldo} kr på {konto}") - try: - konto.ta_ut(500) - except ValueError as err: - print(err) - print(f"{konto.ägare} har {konto.saldo} kr på {konto}") if __name__ == "__main__": main() diff --git a/modules/classes/tutorial/bank_arv.py b/modules/classes/tutorial/bank_arv.py deleted file mode 100644 index 400454d8..00000000 --- a/modules/classes/tutorial/bank_arv.py +++ /dev/null @@ -1,161 +0,0 @@ -"""En modul för bankrelaterade klasser""" - -import adress -import person - -class Kund(person.Person): - """En klass för kunder""" - - def __init__(self, namn, personnummer, adress, telefon): - """Skapar en bankkund: namn (sträng), personnummer (sträng), adress - (Address-objekt), telefon (sträng)""" - namnen = namn.split(" ") - super().__init__(" ".join(namnen[:-1]), namnen[-1], personnummer, - adress) - self.__telefon = telefon - self.__konton = [] - - # @property gör att vi inte behöver parenteserna: - # `kund.telefon` istället för `kund.telefon()` - @property - def telefon(self): - """Returnerar telefonnumret""" - return self.__telefon - - def lägg_till_konto(self, konto): - """Lägger till konto till kundens konton""" - self.__konton.append(konto) - - @property - def konton(self): - """Returnerar en lista med kundens konton""" - return self.__konton.copy() - -def input_kund(prompt=""): - """Låter användaren mata in uppgifter för en kund, - returnerar ett Kund-objekt""" - if prompt: - print(prompt) - - namn = input("Fullständigt namn: ") - personnummer = input("Personnummer: ") - adressen = adress.input_adress() - telefon = input("Telefonnummer: ") - - return Kund(namn, personnummer, adressen, telefon) - -class Konto: - """Ett bankkonto""" - - def __init__(self, ägare, konto_id, saldo=0): - """Skapar ett bankkonto: - ägare är en Kund, - konto_id är en textsträng, - saldo är ett tal (int eller float, default 0)""" - self.__owner = ägare - self.__account_id = konto_id - self.__amount = saldo - self.__lösneord = "" - - @property - def ägare(self): - """Returnerar ägaren""" - return self.__owner - - @property - def kontonr(self): - """Returnerar kontonumret""" - return self.__account_id - - def __str__(self): - return str(self.kontonr) - - def sätt_in(self, summa): - """Sätter in en summa pengar på kontot""" - self.__amount += summa - - @property - def saldo(self): - """Returnerar kontots saldo""" - return self.__amount - - def ta_ut(self, summa): - """Tar ut en summa pengar från kontot, - kastar ett särfall ValueError vid för lite täckning på kontot""" - if self.__amount - summa < 0: - raise ValueError(f"kontot saknar täckning, " - f"saldot {self.__amount} är mindre än " - f"uttaget {summa}") - - self.__amount -= summa - - def sätt_lösenord(self, lösenord): - """Sätter ett lösenord för kontot""" - self.__lösenord = lösenord - - def korrekt_lösenord(self, lösenord): - """Returnerar True om lösenordet matchar""" - return self.__lösenord == lösenord - -class Bank: - """Klass för en bank""" - - def __init__(self, namn): - """Skapa en bank med namnet namn""" - self.__namn = namn - self.__kunder = {} - self.__konton = {} - self.__nuvarande_kontonr = 0 - - def __str__(self): - """Returnerar en strängformaterat representation""" - return self.__namn - - def registrera_kund(self, kund): - """Registrera kunden kund (Kund-objekt) som kund i banken. - kund får inte vara registrerad, då kastas ett KeyError.""" - if kund.get_personnummer() in self.__kunder: - raise KeyError(f"{kund} är redan registrerad som kund.") - - self.__kunder[kund.get_personnummer()] = kund - - def hämta_kund(self, personnummer): - """Returnerar kund med personnummer personnummer""" - return self.__kunder[personnummer] - - def skapa_konto(self, personnummer): - """Skapa ett nytt konto åt kunden med personnumret personnummer, - returnerar det nya kontot""" - kund = self.hämta_kund(personnummer) - konto = Konto(kund, self.__nuvarande_kontonr+1) - self.__konton[konto.kontonr] = konto - self.__nuvarande_kontonr += 1 - kund.lägg_till_konto(konto) - return konto - - def hämta_konto(self, kontonr): - """Returnerar Konto-objektet med kontonumret kontonr, - kastar KeyError om kontonumret inte finns""" - return self.__konton[int(kontonr)] - - -def main(): - """Testprogram""" - kund = Kund("Ada Adamsdotter", "1999-01-01-xxxx", - adress.Adress("Stora vägen", "1", "12345", "Orten"), - "070-1234567") - konto = Konto(kund, "123-456-789") - - print(f"{konto.ägare} har {konto.saldo} kr på {konto}") - konto.sätt_in(500) - print(f"{konto.ägare} har {konto.saldo} kr på {konto}") - konto.ta_ut(200) - print(f"{konto.ägare} har {konto.saldo} kr på {konto}") - try: - konto.ta_ut(500) - except ValueError as err: - print(err) - print(f"{konto.ägare} har {konto.saldo} kr på {konto}") - -if __name__ == "__main__": - main() diff --git a/modules/classes/tutorial/bank_program.py b/modules/classes/tutorial/bank_program.py new file mode 100644 index 00000000..91f3760c --- /dev/null +++ b/modules/classes/tutorial/bank_program.py @@ -0,0 +1,125 @@ +from bank import * +import input_type as it + + +def menu(bank): + """Skriver ut menyn, låter användaren välja ett alternativ. + Returnerar ett korrekt alternativ.""" + print(f"Välkommen till {bank}, hur kan vi hjälpa dig?") + print(""" +[1] Avsluta. +[2] Registrera dig som klient. +[3] Skapa ett konto. +[4] Se dina konton. +[5] Sätt in pengar. +[6] Ta ut pengar. +""") + choice = it.input_type(int, "Välj ett alternativ: ") + while choice < 1 or choice > 6: + print("Tyvärr är det inte ett giltigt alternativ, försök igen, " + "talet måste vara 1, 2, 3, 4, 5 eller 6.") + choice = it.input_type(int, "Välj ett alternativ: ") + + return choice + + +def register_client(bank): + """Menyvalet att registrera en ny klient.""" + try: + citizen, phone_number = input_client("Registrera dig som klient genom " + "att fylla i formuläret.") + bank.add_client(citizen, phone_number) + except KeyError: + print("Tyvärr verkar du redan vara registrerad som klient.") + except ValueError: + print("Namnet du angav var ogiltigt.") + + +def create_account(bank): + """Menyvalet att skapa ett konto.""" + personal_id = it.input_type(int, "Ange ditt personnummer: ") + password = input("Ange ett lösenord för kontot: ") + try: + bank.create_account(personal_id, password) + except KeyError: + print(f"Finns ingen klient med personnummer {personal_id}.") + except ValueError: + print("Lösenordet är för kort.") + + +def list_accounts(bank): + """Listar klientens konton.""" + personal_id = it.input_type(int, "Ange personnummer: ") + try: + accounts = bank.get_client_accounts(personal_id) + except ValueError: + print(f"Finns ingen klient med personnummer {personal_id}.") + return + + for account in accounts: + print(f"{account}: {account.balance} kr") + + +def get_account(bank): + """Låt användaren mata in kontonummer och hämta konto.""" + account_id = it.input_type(int, "Ange kontonummer: ") + try: + account = bank.get_account(account_id) + except KeyError: + print(f"Tyvärr finns inte något konto {account_id}.") + account = None + + return account + + +def insert_money(account): + """Låter användaren mata in summa att sätta in på konto.""" + amount = it.input_type(int, "Ange summa att sätta in: ") + account.insert_money(amount) + + +def withdraw_money(account): + """Låter användaren mata in summa att ta ut från konto.""" + personal_id = it.input_type(int, "Ange ägarens personnummer: ") + password = input("Ange kontots lösenord: ") + if account.owner_profile.citizen.personal_id != personal_id or \ + not account.check_password(password): + print("Tyvärr autentiseringen misslyckades!") + return + + while True: + amount = it.input_type(int, "Ange summa att ta ut: ") + try: + account.withdraw_money(amount) + return + except ValueError as error: + print(error) + + +def main(): + """Huvudprogram""" + bank = Bank("Sveriges Riksbank") + + choice = menu(bank) + while choice != 1: + if choice == 2: + register_client(bank) + elif choice == 3: + create_account(bank) + elif choice == 4: + list_accounts(bank) + elif choice == 5 or choice == 6: + account = get_account(bank) + if not account: + continue + + if choice == 5: + insert_money(account) + else: + withdraw_money(account) + + choice = menu(bank) + + +if __name__ == "__main__": + main() diff --git a/modules/classes/tutorial/banken.py b/modules/classes/tutorial/banken.py deleted file mode 100644 index 708c0e8d..00000000 --- a/modules/classes/tutorial/banken.py +++ /dev/null @@ -1,113 +0,0 @@ -"""Ett program som utför bankliga uppgifter""" - -import bank -import input_type as it - -def meny(banken="banken"): - """Skriver ut menyn, låter användaren välja ett alternativ. - Returnerar ett korrekt alternativ.""" - print(f"Välkommen till {banken}, hur kan vi hjälpa dig?") - print(""" -[1] Avsluta. -[2] Registrera dig som kund. -[3] Skapa ett konto. -[4] Se dina konton. -[5] Sätt in pengar. -[6] Ta ut pengar. -""") - val = it.input_type(int, "Välj ett alternativ: ") - while val < 1 or val > 6: - print("Tyvärr är det inte ett giltigt alternaiv, försök igen, " - "talet måste vara 1, 2, 3, 4, 5 eller 6.") - val = it.input_type(int, "Välj ett alternativ: ") - - return val - -def registrera_kund(banken): - """Menyvalet att registrera en ny kund""" - kund = bank.input_kund("Registrera dig som kund genom att " - "fylla i formuläret.") - try: - banken.registrera_kund(kund) - except KeyError: - print("Tyvärr verkar du redan vara registrerad som kund.") - -def skapa_konto(banken): - """Menyvalet att skapa ett konto""" - personnummer = input("Ange ditt personnummer: ") - try: - konto = banken.skapa_konto(personnummer) - except KeyError: - print(f"Finns ingen kund med personnummer {personnummer}.") - return - - lösenord = input("Ange ett lösenord för kontot: ") - konto.sätt_lösenord(lösenord) - -def lista_konton(banken): - """Listar kundens konton""" - personnummer = input("Ange personnummer: ") - kund = banken.hämta_kund(personnummer) - for konto in kund.konton: - print(f"{konto}: {konto.saldo} kr") - -def hämta_konto(banken): - """Låt användaren mata in kontonummer och hämta konto""" - kontonr = input("Ange kontonummer: ") - try: - konto = banken.hämta_konto(kontonr) - except KeyError: - print(f"Tyvärr finns inte något konto {kontonr}.") - konto = None - - return konto - -def sätt_in(konto): - """Låter användaren mata in summa att sätta in på konto""" - summa = it.input_type(int, "Ange summa att sätta in: ") - konto.sätt_in(summa) - -def ta_ut(konto): - """Låter användaren mata in summa att ta ut från konto""" - personnummer = input("Ange ägarens personnummer: ") - lösenord = input("Ange kontots lösenord: ") - if konto.ägare.personnummer != personnummer or \ - not konto.korrekt_lösenord(lösenord): - print("Tyvärr autentiseringen misslyckades!") - return - - while True: - summa = it.input_type(int, "Ange summa att ta ut: ") - try: - konto.ta_ut(summa) - return - except ValueError as err: - print(err) - - -def main(): - """Huvudprogram""" - banken = bank.Bank("Sveriges Riksbank") - - menyval = meny(banken) - while menyval != 1: - if menyval == 2: - registrera_kund(banken) - elif menyval == 3: - skapa_konto(banken) - elif menyval == 4: - lista_konton(banken) - elif menyval == 5 or menyval == 6: - konto = hämta_konto(banken) - if not konto: - continue - - if menyval == 5: - sätt_in(konto) - else: - ta_ut(konto) - - menyval = meny(banken) - -if __name__ == "__main__": - main() diff --git a/modules/classes/tutorial/banken_arv.py b/modules/classes/tutorial/banken_arv.py deleted file mode 100644 index 07473180..00000000 --- a/modules/classes/tutorial/banken_arv.py +++ /dev/null @@ -1,113 +0,0 @@ -"""Ett program som utför bankliga uppgifter""" - -import bank_arv as bank -import input_type as it - -def meny(banken="banken"): - """Skriver ut menyn, låter användaren välja ett alternativ. - Returnerar ett korrekt alternativ.""" - print(f"Välkommen till {banken}, hur kan vi hjälpa dig?") - print(""" -[1] Avsluta. -[2] Registrera dig som kund. -[3] Skapa ett konto. -[4] Se dina konton. -[5] Sätt in pengar. -[6] Ta ut pengar. -""") - val = it.input_type(int, "Välj ett alternativ: ") - while val < 1 or val > 6: - print("Tyvärr är det inte ett giltigt alternaiv, försök igen, " - "talet måste vara 1, 2, 3, 4, 5 eller 6.") - val = it.input_type(int, "Välj ett alternativ: ") - - return val - -def registrera_kund(banken): - """Menyvalet att registrera en ny kund""" - kund = bank.input_kund("Registrera dig som kund genom att " - "fylla i formuläret.") - try: - banken.registrera_kund(kund) - except KeyError: - print("Tyvärr verkar du redan vara registrerad som kund.") - -def skapa_konto(banken): - """Menyvalet att skapa ett konto""" - personnummer = input("Ange ditt personnummer: ") - try: - konto = banken.skapa_konto(personnummer) - except KeyError: - print(f"Finns ingen kund med personnummer {personnummer}.") - return - - lösenord = input("Ange ett lösenord för kontot: ") - konto.sätt_lösenord(lösenord) - -def lista_konton(banken): - """Listar kundens konton""" - personnummer = input("Ange personnummer: ") - kund = banken.hämta_kund(personnummer) - for konto in kund.konton: - print(f"{konto}: {konto.saldo} kr") - -def hämta_konto(banken): - """Låt användaren mata in kontonummer och hämta konto""" - kontonr = input("Ange kontonummer: ") - try: - konto = banken.hämta_konto(kontonr) - except KeyError: - print(f"Tyvärr finns inte något konto {kontonr}.") - konto = None - - return konto - -def sätt_in(konto): - """Låter användaren mata in summa att sätta in på konto""" - summa = it.input_type(int, "Ange summa att sätta in: ") - konto.sätt_in(summa) - -def ta_ut(konto): - """Låter användaren mata in summa att ta ut från konto""" - personnummer = input("Ange ägarens personnummer: ") - lösenord = input("Ange kontots lösenord: ") - if konto.ägare.get_personnummer() != personnummer or \ - not konto.korrekt_lösenord(lösenord): - print("Tyvärr autentiseringen misslyckades!") - return - - while True: - summa = it.input_type(int, "Ange summa att ta ut: ") - try: - konto.ta_ut(summa) - return - except ValueError as err: - print(err) - - -def main(): - """Huvudprogram""" - banken = bank.Bank("Sveriges Riksbank") - - menyval = meny(banken) - while menyval != 1: - if menyval == 2: - registrera_kund(banken) - elif menyval == 3: - skapa_konto(banken) - elif menyval == 4: - lista_konton(banken) - elif menyval == 5 or menyval == 6: - konto = hämta_konto(banken) - if not konto: - continue - - if menyval == 5: - sätt_in(konto) - else: - ta_ut(konto) - - menyval = meny() - -if __name__ == "__main__": - main() diff --git a/modules/classes/tutorial/citizen.py b/modules/classes/tutorial/citizen.py new file mode 100644 index 00000000..b0f32902 --- /dev/null +++ b/modules/classes/tutorial/citizen.py @@ -0,0 +1,51 @@ +from person import Person + + +# Obs: Detta är ett exempel på arv där Citizen-klassen ärver egenskaper från +# Person-klassen. På så vis kan man skapa klasser för personer med mer +# "specialiserade" egenskaper (t.ex. att de är medborgare) utan att behöva +# skriva om alla metoder. +class Citizen(Person): + """En medborgare.""" + + def __init__(self, full_name, personal_id, address, parents): + """ + `full_name` är personens är medborgarens fullständiga namn (sträng). + Krav: minst ett mellanrum måste existera. + `personal_id` är personnumret (heltal). + `address` är medborgarens registrerade address (Address-objekt). + `parents` ett itererbart objekt (en lista, tupel, etc.) med medborgarens + föräldrar (max 2 stycken). + Föräldrarna får vara Person-objekt. + """ + try: + first_name, last_name = full_name.split(maxsplit=1) + except ValueError: + raise ValueError("ett fullständigt namn måste bestå av åtminstone " + "ett mellanrum.") + + super(Citizen, self).__init__(first_name, last_name, address) + self.__personal_id = personal_id + + if len(parents) > 2: + raise ValueError("en medborgare kan inte ha fler än två föräldrar.") + + for parent in parents: + if not isinstance(parent, Person): + raise ValueError("`parents` får endast innehålla " + "Person-objekt.") + + # `parents` kan vara vilket itererbart objekt som helst + # (lista, tupel, etc.). Vi vill att `self.__parents` ska vara en tupel, + # och inget annat, så vi konstruerar en tupel från `parents`. + self.__parents = tuple(parents) + + @property + def personal_id(self): + """Personens personnummer.""" + return self.__personal_id + + @property + def parents(self): + """Returnerar en tupel med medborgarens föräldrar (Person-objekt).""" + return self.__parents diff --git a/modules/classes/tutorial/input_type.py b/modules/classes/tutorial/input_type.py index 52a136be..2fe9a90d 100644 --- a/modules/classes/tutorial/input_type.py +++ b/modules/classes/tutorial/input_type.py @@ -1,5 +1,6 @@ """Take input more easily.""" + def input_type(t, prompt=""): """Take input, convert to type t; repeat if error.""" while True: @@ -11,6 +12,7 @@ def input_type(t, prompt=""): else: print(f"Sorry, can't convert to {t}.") + def main(): """Test functionality of this module""" x = input_type(int, "x = ") @@ -22,5 +24,6 @@ def main(): print(f"z = {z}") print(f"Your name is {name}") + if __name__ == "__main__": main() diff --git a/modules/classes/tutorial/instruction.md b/modules/classes/tutorial/instruction.md index f33bf532..06d5fcc4 100644 --- a/modules/classes/tutorial/instruction.md +++ b/modules/classes/tutorial/instruction.md @@ -2,10 +2,12 @@ title: Övning om klasser och objekt authors: - Daniel Bosk + - Celina Soori + - Mazen Mardini --- # Övning: klasser och objekt -Målet med övningen är att du ska blir bättre på att +Målet med övningen är att du ska bli bättre på att - använda och konstruera sammansatta datatyper (klasser), - tillämpa behållare för att lagra mängder med data, @@ -14,56 +16,53 @@ Målet med övningen är att du ska blir bättre på att - minimera kodupprepning, - leta i Pythons dokumentation. +## Genomgång av veckans svårigheter -## Laborationen +Vi går igenom det vi upptäckt i OLI är extra svårt den här veckan. -Hur har olika grupper löst samma labb? Oftast väldigt olika. Vi går igenom -några lösningar. Hur löser man extrauppgiften? +Zoomlänk: +## Önskemål från gruppen -## Inköpslistan +Var det något särskilt från veckans föreläsning och/eller OLI-material som gruppen vill gå igenom igen? -Skriv ett program som hanterar en inköpslista. Du ska kunna ha flera olika -inköpslistor (exempelvis en för mat, en för andra saker), men det räcker med -att experimentera med en. +Gick förra veckans laboration bra? Finns det något ni skulle vilja gå igenom från laborationen? -Det ska gå att lägga till saker, lista dem, bocka av enskilda saker och ta bort -alla avbockade saker. +## Övningsuppgifter -Lösningsförslag: +### Finn fem fel - - [En modul som illustrerar en enkel inköpslista, shopping.py][shopping.py] +Programmet [En multiplikationstabell](https://github.com/dbosk/intropy/blob/master/modules/containers/tutorial/multtable.py) skriver ut en multiplikationstabell. -[shopping.py]: https://github.com/dbosk/intropy/blob/master/modules/classes/tutorial/shopping.py +Läs igenom koden och få ett hum om vad den är tänkt att göra. Testa att köra koden. + +Hitta nu tillsammans minst fem fel/utvecklingsområden i koden (tänk på vad ni lärt er under veckan). +Förbättra nu koden efter det ni hittat. Blev koden mer lättläst, användbar och/eller användarvänlig? Varför? -## Folkbokföringen +([Lösningsförslag]([multtable-good.py](https://github.com/dbosk/intropy/blob/master/modules/containers/tutorial/multtable-good.py) -Under föreläsningen skrev vi en [modul med en klass för -personer][person_old.py]. Vi ska nu bygga vidare på den och skriva en enkel -version av Skatteverkets folkbokföringsdatabas. +### Inköpslistan -[person_old.py]: https://github.com/dbosk/intropy/blob/master/modules/classes/slides/examples/person.py +Skriv ett program som hanterar en inköpslista. Du ska kunna ha flera olika +inköpslistor (exempelvis en för mat, en för andra saker), men det räcker med +att experimentera med en. -Folkbokföringen håller koll på följande om varje person: +Det ska gå att lägga till saker, lista dem, bocka av enskilda saker och ta bort +alla avbockade saker. - - personens identitet (namn, personnummer och de olika delarna av dessa), - - personens föräldrar och barn, - - personens bostadsadress (delarna av den adressen) och alla historiska - bostadsadresser. +Testa att spara inköpslistorna i en lista, så att du får listor i listor. +Försök iterera genom listan med inköpslistor och alla varor i inköpslistorna. +Hur gör du detta enklast? Lösningsförslag: - - [En modul med en klass för personer, person.py][person.py], - - [en modul med en klass för adresser, adress.py][adress.py], - - [en modul med anpassningar för Skatteverket och testprogram, skatteverket.py][skatteverket.py] + - [En modul som illustrerar en enkel inköpslista, shopping.py][shopping.py] -[person.py]: https://github.com/dbosk/intropy/blob/master/modules/classes/tutorial/person.py -[adress.py]: https://github.com/dbosk/intropy/blob/master/modules/classes/tutorial/adress.py -[skatteverket.py]: https://github.com/dbosk/intropy/blob/master/modules/classes/tutorial/skatteverket.py +[shopping.py]: https://github.com/dbosk/intropy/blob/master/modules/classes/tutorial/shopping.py -## Bankkontot +### Bankkontot Vi ska skriva ett enkelt program som hanterar konton åt en bank. Vi behöver en sammansatt datatyp (klass) som kan representera ett bankkonto: @@ -79,44 +78,16 @@ sammansatt datatyp (klass) som kan representera ett bankkonto: Lösningsförslag: - [En modul med klasser för en bank, bank.py][bank.py] - - [En modul med klasser för en bank (använder arv), bank_arv.py][bank_arv.py] - - [Ett program med gränssnitt för en bank, banken.py][banken.py] - - [Ett program med gränssnitt för en bank (arv), banken_arv.py][banken_arv.py] + - [Ett program med gränssnitt för en bank, bank_program.py][bank_program.py] + - [En modul med en personklass, person.py][bank_program.py] + - [En modul med en medborgarklass, citizen.py][citizen.py] + - [En modul med en adressklass, address.py][address.py] - [En modul för inmatning av specifika typer, input_type.py][input_type.py] [bank.py]: https://github.com/dbosk/intropy/blob/master/modules/classes/tutorial/bank.py -[bank_arv.py]: https://github.com/dbosk/intropy/blob/master/modules/classes/tutorial/bank_arv.py -[banken.py]: https://github.com/dbosk/intropy/blob/master/modules/classes/tutorial/banken.py -[banken_arv.py]: https://github.com/dbosk/intropy/blob/master/modules/classes/tutorial/banken_arv.py +[bank_program.py]: https://github.com/dbosk/intropy/blob/master/modules/classes/tutorial/bank_program.py +[address.py]: https://github.com/dbosk/intropy/blob/master/modules/classes/tutorial/address.py +[citizen.py]: https://github.com/dbosk/intropy/blob/master/modules/classes/tutorial/citizen.py +[person.py]: https://github.com/dbosk/intropy/blob/master/modules/classes/tutorial/person.py [input_type.py]: https://github.com/dbosk/intropy/blob/master/modules/classes/tutorial/input_type.py - -## En bråkig klass - -Vi vill ha en klass för att räkna med rationella tal, eller bråk. Vi ska kunna: - - - skapa bråk, exempelvis `a = Bråk(1, 3)` och `b = Bråk(2, 6)`; - - jämföra bråk, exempelvis `a == b` eller `a < b`; - - skriva ut bråk på läsbar form, exempelvis `print(f"{a} och {b}")` ger - utskriften `1/3 och 2/6`. - - addera, subtrahera, multiplicera och dividera bråk. - - typkonvertera bråket till ett flyttal (`float`). - - förkorta bråk, exempelvis så att `b` (som är 2/6) kan förkortas till 1/3. - -Detta kräver en del specialmetoder. Se [dokumentationen för Pythons -specialmetoder för jämförelse][doc-cmp] och [dokumentationen för Pythons -specialmetoder för att emulera numeriska typer][doc-numtypemethods]. - -[doc-cmp]: https://docs.python.org/3/reference/datamodel.html#object.__lt__ -[doc-numtypemethods]: https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types - -Lösningsförslag: - - - [Lösningsförslag: en modul med en klass för bråktal, frac.py][frac.py] - -[frac.py]: https://github.com/dbosk/intropy/blob/master/modules/classes/tutorial/frac.py - - -## Önskemål från gruppen - -Vad vill gruppen gå igenom igen från veckan som var? diff --git a/modules/classes/tutorial/person.py b/modules/classes/tutorial/person.py index 6e5ae301..507499c9 100644 --- a/modules/classes/tutorial/person.py +++ b/modules/classes/tutorial/person.py @@ -1,86 +1,111 @@ -""" Class for a person """ +from address import Address + class Person: - """ Class for a person """ - def __init__(self, first_name, last_name, personnummer, address): - """first_name: string with first name. - last_name: string with last name. - personnummer: string with personnummer, - address: string or Adress object with address.""" + """En person.""" + + def __init__(self, first_name, last_name, address): + """`first_name` är förnamnet (sträng). + `last_name` är efternamnet (sträng). + `address` är adressen (Address-objekt). + """ self.__first_name = first_name self.__last_name = last_name - self.__personnummer = personnummer self.__address = address - def get_name(self): - """ Returns the full name as a concatenation """ - return self.__first_name + " " + self.__last_name - + # Obs: __str__-metoden används för att ge en användarvänlig + # sträng-representation av objektet. def __str__(self): - """Returnerar en strängrepresentation lämpligt för utskrift""" - return self.get_name() - - def get_first_name(self): - """ Returns the first name """ - return self.__first_name - - def get_last_name(self): - """ Returns the last name """ - return self.__last_name - - def change_name(self, name): - """ Takes a concatenated name, sets last and first names """ - names = name.split() - # Shorthand for the last element in the list - self.__last_name = names[-1] - # names[:-1] all elements except the last - self.__first_name = " ".join(names[:-1]) - - def get_personnummer(self): - """ Return personnummer """ - return self.__personnummer - - def get_address(self): - """ Return address """ + """Personens fullständiga namn.""" + return self.full_name + + # Obs: __repr__-metoden används för att ge en sträng-representation + # av objektet som är hjälpsam + # för programmeraren. + def __repr__(self): + """En sträng som innehåller alla attribut.""" + return f"Person({self.__first_name}, {self.__last_name}, " \ + f"{repr(self.__address)})" + + # Obs: @property gör att vi inte behöver parenteserna: + # `kund.namn` istället för `kund.namn()` + @property + def first_name(self): + """Personens förnamn.""" + return self.__first_name.capitalize() + + @property + def last_name(self): + """Personens efternamn.""" + return self.__last_name.capitalize() + + @property + def full_name(self): + """Personens fullständiga namn.""" + return self.first_name + " " + self.last_name + + @property + def address(self): + """Personens adress.""" return self.__address - def __lt__(self, other): - """Returns True if self comes before other in alphabetical order""" - if self.get_last_name() == other.get_last_name(): - return self.get_first_name() < other.get_first_name() + # Obs: "*" betyder att alla efterkommande parametrar måste explicit anges i + # ett anrop om du väljer att tilldela dem värden. Till exempel är + # "person.change_name('Olle', 'Ohlsson')" inte tillåtet, men + # "person.change_name(first_name='Olle', last_name='Ohlsson')" är det. + def change_name(self, *, first_name=None, last_name=None): + """Byt personens för- och/eller efternamn. - return self.get_last_name() < other.get_last_name() + Om parametern `first_name` eller `last_name` är None så byts det + inte ut. - def __repr__(self): - """Returns unique representation""" - return f"({self.get_name()}, {self.get_personnummer()}" + Exempel: + >> person.change_name() # Gör ingenting + >> person.change_name(last_name="Stonkman") # Byter efternamnet till + "Stonkman" + """ + if first_name: + self.__first_name = first_name + + if last_name: + self.__last_name = last_name + + def __lt__(self, other): + """Gör så att operatorn < jämför personer baserat på deras namn.""" + return self.full_name < other.full_name def main(): """ Test program """ - person = Person("Anne-Marie", "Ingeström", "1907-08-28", - "Vimmerby", "okänt") - print(f"{person.get_name()} har telefonnummer {person.get_phone()} " - f"och bor på adressen {person.get_address()}") - print(f"{person} har telefonnummer {person.get_phone()} " - f"och bor på adressen {person.get_address()}") - - person.change_name("Margareta Engström") - print(f"{person} bor på adressen {person.get_address()}") - print(person.get_first_name()) - print(person.get_last_name()) - - person2 = Person("Ada", "Bedasdotter", "1990-01-01", - "Kiruna", "070-1234567") + + # Skapa ett Person-objekt + person = Person("Anne-Marie", "Ingeström", Address("Odengatan", "1", + 11424, "Stockholm")) + print(f"{person} bor på adressen {person.address}.") + + # Byt namn + person.change_name(first_name="Margareta", last_name="Engström") + print(f"{person} bor på adressen {person.address}") + + # Skapa ett annat Person-objekt + person2 = Person("Ada", "Bedasdotter", Address("Uttervägen", "12", + 98137, "Kiruna")) + + # Jämför objekten (använder __lt__-metoden implicit) if person < person2: print(f"{person} sorteras före {person2}.") else: print(f"{person2} sorteras före {person}.") - lista = [person, person2] - print(lista) - lista.sort() - print(lista) + people = [person, person2] + + # När man skriver ut en lista så används __repr__-metoden för alla element + print(people) + + # Vi kan sortera listan eftersom < operatorn är definierad för Person-objekt + people.sort() + print(people) + if __name__ == "__main__": main() diff --git a/modules/classes/tutorial/shopping.py b/modules/classes/tutorial/shopping.py index 5b824a80..16137477 100644 --- a/modules/classes/tutorial/shopping.py +++ b/modules/classes/tutorial/shopping.py @@ -1,59 +1,58 @@ """En modul lämpad för hantering av shoppinglistor""" -class Vara: + +class Item: """En klass för varor i en shoppinglista""" - def __init__(self, namn, antal=1): + def __init__(self, name, amount=1): """Skapar ett inlägg i en shoppinglista: - namn (sträng), - antal (int, default 1)""" - self.__namn = namn - if type(antal) in [int, float]: - self.__antal = antal + `name` (sträng), + `amount` (heltal, default 1)""" + self.__name = name + if type(amount) in [int, float]: + self.__amount = amount else: - self.__antal = int(antal) - self.__avbockad = False + self.__amount = int(amount) + self.__checked = False @property - def namn(self): + def name(self): """Returnerar namnet""" - return self.__namn + return self.__name @property - def antal(self): + def amount(self): """Returnerar antalet""" - return self.__antal + return self.__amount @property - def avbockad(self): + def checked(self): """Returnerar True om varan är avbockad, False annars""" - return self.__avbockad + return self.__checked def __str__(self): """Returnerar en representation lämplig för utskrift""" - return f"[{'x' if self.avbockad else ' '}] {self.antal} st {self.namn}" + return f"[{'x' if self.checked else ' '}] {self.amount} st {self.name}" - def bocka_av(self): + def check(self): """Bockar av""" - self.__avbockad = True + self.__checked = True def main(): """Testprogram""" - lista = [] - lista.append(Vara("mjölk", 5)) - lista.append(Vara("tomater", 3)) - lista.append(Vara("yoghurt", 1)) + shopping_items = [Item("mjölk", 5), Item("tomater", 3), Item("yoghurt", 1)] print("Shoppinglista") - for vara in lista: - print(vara) + for item in shopping_items: + print(item) - lista[1].bocka_av() + shopping_items[1].check() print("Shoppinglista") - for vara in lista: - print(vara) + for item in shopping_items: + print(item) + if __name__ == "__main__": main() diff --git a/modules/classes/tutorial/skatteverket.py b/modules/classes/tutorial/skatteverket.py deleted file mode 100644 index d51e65e7..00000000 --- a/modules/classes/tutorial/skatteverket.py +++ /dev/null @@ -1,79 +0,0 @@ -""" Reperesenting Skatteverket's pupulation register """ - -import person -# vi kan byta namn på Adress till Address då personklassen är skriven på -# engelska -from adress import Adress as Address - -# vi kan ha "samma namn" på dem, fast egentligen är det inte samma namn: -# den ena heter Person och den andra person.Person. -class Person(person.Person): - """ Represents a real/physical person """ - def __init__(self, person_id, full_name, parents, address): - names = full_name.split() - # vi behöver separera för- och efternamn åt person.Person - super().__init__(" ".join(names[:-1]), names[-1], person_id, address) - self.__parents = parents - self.__address = address - self.__old_addresses = [] - - def __str__(self): - """Returns a string representation of the person""" - return f"{self.get_name()} ({self.get_personnummer()})" - - def get_parents(self): - """ Returns the parents """ - # vi returnerar en kopia, annars kan någon uppdatera föräldrarna - # genom att modifiera listan som returneras. - return self.__parents.copy() - - def change_address(self, new_address): - """ Changes the address (registers a move) """ - self.__old_addresses.append(self.__address) - self.__address = new_address - - def get_address_history(self): - """Returns the list of all addresses""" - # returnera kopia för att historiken inte ska kunna förvanskas - return self.__old_addresses.copy() - - -def main(): - """ Skatteverket test program """ - folkbokföring = {} - - alice = Person("1950-01-01-1234", "Alice Adamsdotter", None, - Address("Vägen", "1", "12345", "Orten")) - - folkbokföring["1950-01-01-1234"] = alice - - bob = Person("1950-01-01-1244", "Bob Evasson", None, - Address("Vägen", "1", "12345", "Orten")) - - folkbokföring["1950-01-01-1244"] = bob - - cecilia = Person("1970-01-01-1234", "Cecilia Adamsdotter-Evasson", - [alice, bob], - Address("Vägen", "1", "12345", "Orten")) - - folkbokföring["1970-01-01-1234"] = cecilia - - print(f"{cecilia} bor på {cecilia.get_address()}") - - cecilia.change_address(Address("Vägen", "2", "12345", "Orten")) - print(f"{cecilia} bor på {cecilia.get_address()}") - print(f"{cecilia} har tidigare bott på adresserna:") - for address in cecilia.get_address_history(): - print(address) - - parents = cecilia.get_parents() - print(f"{cecilia}s föräldrar heter {parents[0]} och {parents[1]}.") - - print(f"{alice} och {bob} bor fortfarande på {alice.get_address()}") - - print("Folkbokföringen") - for person in sorted(folkbokföring.values()): - print(person) - -if __name__ == "__main__": - main() diff --git a/modules/variables/slides-more/.gitignore b/modules/computational-thinking/slides/.gitignore similarity index 100% rename from modules/variables/slides-more/.gitignore rename to modules/computational-thinking/slides/.gitignore diff --git a/modules/variables/slides-more/Makefile b/modules/computational-thinking/slides/Makefile similarity index 100% rename from modules/variables/slides-more/Makefile rename to modules/computational-thinking/slides/Makefile diff --git a/modules/computational-thinking/slides/README.md b/modules/computational-thinking/slides/README.md new file mode 100644 index 00000000..392c1ed5 --- /dev/null +++ b/modules/computational-thinking/slides/README.md @@ -0,0 +1,5 @@ +- [YouTube: Algoritmiskt tänkande][yt] +- [FeedbackFruits: Algoritmiskt tänkande][fbf] + +[yt]: https://www.youtube.com/watch?v=BCj702g9klc +[fbf]: https://eu.feedbackfruits.com/courses/activity-course/6eda1d62-b142-42c2-b8fc-def0b90f89d1 diff --git a/modules/conditionals/slides/abstract.tex b/modules/computational-thinking/slides/abstract.tex similarity index 100% rename from modules/conditionals/slides/abstract.tex rename to modules/computational-thinking/slides/abstract.tex diff --git a/modules/computational-thinking/slides/contents.tex b/modules/computational-thinking/slides/contents.tex new file mode 100644 index 00000000..65e8b110 --- /dev/null +++ b/modules/computational-thinking/slides/contents.tex @@ -0,0 +1,256 @@ +\title{% + Algoritmiskt tänkande +} +\author{Daniel Bosk} +\institute{% + KTH EECS +} + +\mode
{\maketitle} +\mode{% + \begin{frame} + \maketitle + \end{frame} +} + +\mode* + +\begin{abstract} + \input{abstract.tex} +\end{abstract} + + +\section{Algoritmer} + +% diska +% sortera tvätt innan tvätt +% hänga tvätt +% vika tvätt + +\begin{frame} + \begin{example}[Att göra pannkakssmet] + \begin{enumerate} + \item Knäck tre ägg i en bunke. + \item Vispa ordentligt. + \item Häll i \SI{3}{\deci\litre} mjölk. + \item Vispa ordentligt. + \item \label{mjöl} Häll i \SI{1}{\deci\litre} mjöl. + \item \label{vispa-mjöl} Vispa ordentligt. + \item Repetera \ref{mjöl} och \ref{vispa-mjöl} två gånger till. + \item Häll i \SI{1/2}{tsk} salt. + \item Häll i \SI{2}{msk} smält smör. + \item Vispa ordentligt. + \end{enumerate} + \end{example} +\end{frame} + +\begin{frame}[fragile] + \begin{definition}[Algoritm] + \begin{itemize} + \item Algoritm, algorism: ursprungligen förvanskning av namnet på den + persisk-arabiska matematikern al-Khwarizmi\footnote{% + \emph{Nationalencyklopedin}, + algoritm. + \url{http://www-ne-se.focus.lib.kth.se/uppslagsverk/encyklopedi/lång/algoritm} + (hämtad 2022-09-04). + } + \item Definition: \enquote{inom matematik och databehandling en + systematisk procedur som i ett ändligt antal steg anger hur man utför + en beräkning eller löser ett givet problem}. + \end{itemize} + \end{definition} +\end{frame} + +\begin{frame} + \begin{exercise}[Sortera tvätt] + \begin{itemize} + \item Beskriv din algoritm för att sortera tvätt innan den åker in i + tvättmaskinen. + \end{itemize} + \end{exercise} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[Sortera tvätt] + \begin{enumerate} + \item \label{ta-från-tvättkorg} Ta \alert<3>{en textil} ur tvättkorgen. + \item Om \alert<3>{textilen} är vit, lägg i vit 60; annars + \item Om \alert<3>{textilen} är mörk och underkläder, lägg i mörk 60; + annars + \item Om \alert<3>{textilen} är mörk, lägg i mörk 40; annars + \item Om \alert<3>{textilen} är ljus och underkläder, lägg i ljus 60; + annars + \item Om \alert<3>{textilen} är ljus, lägg i ljus 40; annars + \item Lägg \alert<3>{textilen} i hantera senare-högen. + \item Repetera från \ref{ta-från-tvättkorg}. + \end{enumerate} + \end{example} + + \begin{onlyenv}<2> + \begin{exercise} + \begin{itemize} + \item Vad varierar i exemplet med tvättsortering? + \end{itemize} + \end{exercise} + \end{onlyenv} +\end{frame} + +\subsection{Variabler} + +\begin{frame} + \begin{exercise} + \begin{itemize} + \item Vad varierar i exemplet med pannkakssmet? + \end{itemize} + \end{exercise} + + \begin{example}[Att göra pannkakssmet] + \begin{enumerate} + \item Knäck tre ägg i en bunke. + \item Vispa ordentligt. + \item Häll i \SI{3}{\deci\litre} mjölk. + \item Vispa ordentligt. + \item \label{mjöl} Häll i \SI{1}{\deci\litre} mjöl. + \item \label{vispa-mjöl} Vispa ordentligt. + \item Repetera \ref{mjöl} och \ref{vispa-mjöl} två gånger till. + \item Häll i \SI{1/2}{tsk} salt. + \item Häll i \SI{2}{msk} smält smör. + \item Vispa ordentligt. + \end{enumerate} + \end{example} +\end{frame} + +\begin{frame} + \begin{example}[Att göra pannkakssmet för \(n\) personer] + \begin{enumerate} + \item Knäck \(\frac{3n}{4}\) ägg i en bunke. + \item Vispa ordentligt. + \item Häll i \SI{\frac{3n}{4}}{\deci\litre} mjölk. + \item Vispa ordentligt. + \item För totalt \SI{\frac{3n}{4}}{\deci\litre} mjöl: + \begin{enumerate} + \item Häll i \SI{1}{\deci\litre} mjöl. + \item Vispa ordentligt. + \end{enumerate} + \item Häll i \SI{\frac{3n}{2\cdot 4}}{tsk} salt. + \item Häll i \SI{\frac{2n}{4}}{msk} smält smör. + \item Vispa ordentligt. + \end{enumerate} + \end{example} +\end{frame} + +\begin{frame}[fragile] + \begin{definition}[Variabel] + \begin{itemize} + \item Något som hänvisar till något som kan variera kallar vi för + \emph{variabel}. + \end{itemize} + \end{definition} + + \pause + + \begin{example}[Variabler] + \begin{itemize} + \item Textilen + \item Antal personer, \(n\). + \end{itemize} + \end{example} +\end{frame} + +\subsection{(Del)algoritmer, eller funktioner} + +\begin{frame} + \begin{example}[Att steka pannkakor\only<2>{ \alert{för fyra personer}}] + \begin{enumerate} + \item \alert<2>{Gör pannkakssmet för fyra personer.} + \item För varje portion, medan det finns pannkakssmet kvar: + \begin{enumerate} + \item Häll \SI{1}{\deci\litre} smet i en het stekpanna. + \item Vänta \SI{2}{\minute}. + \item Vänd pannkakan. + \item Vänta \SI{2}{\minute}. + \item Servera pannkakan. + \end{enumerate} + \end{enumerate} + \end{example} + + \begin{onlyenv}<1> + \begin{exercise} + \begin{itemize} + \item Det resterande, som inte är en variabel, vad är det? + \end{itemize} + \end{exercise} + \end{onlyenv} + + \begin{onlyenv}<2> + \begin{definition}[Funktion] + \begin{itemize} + \item En funktion är en fixerad procedur. + \item Den tar variabler som inmatning och returnerar någon + utmatning. + \end{itemize} + \end{definition} + \end{onlyenv} +\end{frame} + +\section{Uppdelning i delalgoritmer (funktioner)} + +\begin{frame}[fragile] + \begin{exercise} + \begin{itemize} + \item Vilka funktioner kan ni hitta i funktionen? + \end{itemize} + \end{exercise} + + \begin{example}[Att göra pannkakssmet för \(n\) personer] + \begin{enumerate} + \item \alert<2>{Knäck} \(\frac{3n}{4}\) ägg i en bunke. + \item \alert<2>{Vispa} ordentligt. + \item \alert<2>{Häll} i \SI{\frac{3n}{4}}{\deci\litre} mjölk. + \item \alert<2>{Vispa} ordentligt. + \item För totalt \SI{\frac{3n}{4}}{\deci\litre} mjöl: + \begin{enumerate} + \item \alert<2>{Häll} i \SI{1}{\deci\litre} mjöl. + \item \alert<2>{Vispa} ordentligt. + \end{enumerate} + \item \alert<2>{Häll} i \SI{\frac{3n}{2\cdot 4}}{tsk} salt. + \item \alert<2>{Häll} i \SI{\frac{2n}{4}}{msk} smält smör. + \item \alert<2>{Vispa} ordentligt. + \end{enumerate} + \end{example} +\end{frame} + +\begin{frame} + \begin{remark} + \begin{itemize} + \item Funktioner motsvarar verb i dagligt språk! + \end{itemize} + \end{remark} +\end{frame} + +\begin{frame} + \begin{exercise} + \begin{itemize} + \item Vilka funktioner och variabler använder du i din algoritm för + handdisk i köket? + \end{itemize} + \end{exercise} +\end{frame} + +\begin{frame} + \begin{example}[Algoritm för handdisk] + \begin{enumerate} + \item \alert{Lägg} \emph{all disk} i diskhon med diskvattnet i. + \item \label{glas} \alert{Ta} \emph{ett glas}, \alert{diska} \emph{det}, + \alert{lägg} \emph{det} i diskhon för diskad disk. + \item Repetera \ref{glas} tills att \emph{glasen} är slut. + \item \label{bestick} \alert{Ta} \emph{ett bestick}, \alert{diska} + \emph{det}, \alert{lägg} \emph{det} i diskhon för diskad disk. + \item Repetera \ref{bestick} tills att besticken är slut. + \item \label{tallrik} \alert{Ta} \emph{en tallrik}, \alert{diska} + \emph{den}, \alert{lägg} \emph{den} i diskhon för diskad disk. + \item Repetera \ref{tallrik} tills att tallrikarna är slut. + \end{enumerate} + \end{example} +\end{frame} + diff --git a/modules/variables/slides-more/examples/area.py b/modules/computational-thinking/slides/examples/area.py similarity index 100% rename from modules/variables/slides-more/examples/area.py rename to modules/computational-thinking/slides/examples/area.py diff --git a/modules/conditionals/slides/notes.tex b/modules/computational-thinking/slides/notes.tex similarity index 100% rename from modules/conditionals/slides/notes.tex rename to modules/computational-thinking/slides/notes.tex diff --git a/modules/computational-thinking/slides/preamble.tex b/modules/computational-thinking/slides/preamble.tex new file mode 100644 index 00000000..b561d934 --- /dev/null +++ b/modules/computational-thinking/slides/preamble.tex @@ -0,0 +1,39 @@ +\usepackage[utf8]{inputenc} +\usepackage[T1]{fontenc} +\usepackage[british,swedish]{babel} +\usepackage{booktabs} + +\usepackage[natbib,style=alphabetic,maxbibnames=99]{biblatex} +\addbibresource{slides.bib} + +\usepackage[all]{foreign} +\renewcommand{\foreignfullfont}{} +\renewcommand{\foreignabbrfont}{} + +\usepackage{newclude} +\usepackage{import} + +\usepackage[strict]{csquotes} +\usepackage[single]{acro} + +\usepackage{subcaption} + +\usepackage[noend]{algpseudocode} +\usepackage{xparse} + +\let\email\texttt + +\usepackage[outputdir=ltxobj]{minted} +\setminted{autogobble,fontsize=\footnotesize} + +\usepackage{amsmath} +\usepackage{amssymb} +\usepackage{mathtools} +\usepackage{amsthm} +\usepackage{thmtools} +\usepackage[unq]{unique} +\DeclareMathOperator{\powerset}{\mathcal{P}} + +\usepackage[binary-units,parse-numbers=false]{siunitx} + +\usepackage[capitalize]{cleveref} diff --git a/modules/variables/slides-more/slides.tex b/modules/computational-thinking/slides/slides.tex similarity index 97% rename from modules/variables/slides-more/slides.tex rename to modules/computational-thinking/slides/slides.tex index d7beb5f0..692a8dd9 100644 --- a/modules/variables/slides-more/slides.tex +++ b/modules/computational-thinking/slides/slides.tex @@ -102,7 +102,7 @@ % %%% REFERENCES %%% -\begin{frame}[allowframebreaks] - \printbibliography -\end{frame} +%\begin{frame}[allowframebreaks] +% \printbibliography +%\end{frame} \end{document} diff --git a/modules/conditionals/Makefile b/modules/conditionals/Makefile index c93e77af..63ae30a2 100644 --- a/modules/conditionals/Makefile +++ b/modules/conditionals/Makefile @@ -1,4 +1,5 @@ -SUBDIR+= slides +SUBDIR+= slides-input +SUBDIR+= slides-conditionals SUBDIR_GOALS= all clean distclean HTML_FILES= lecture.html exercise.html tutorial.html diff --git a/modules/conditionals/anim.py b/modules/conditionals/anim.py new file mode 100644 index 00000000..620133ec --- /dev/null +++ b/modules/conditionals/anim.py @@ -0,0 +1,174 @@ +""" +Ett bibliotek för att animera i terminalen + +Av: Daniel Bosk, Emelie Wästlund + +ANSI-escape för att flytta markören: + + https://tldp.org/HOWTO/Bash-Prompt-HOWTO/x361.html + +Cow av Shanaka Dias: https://www.asciiart.eu/animals/cows +""" + +import math +import os +import platform +import time +import shutil + +WIDTH, HEIGHT = shutil.get_terminal_size((80, 20)) + +def init_canvas(width=WIDTH, height=HEIGHT): + """Initierar ritområdet""" + canvas = "\n"*height + render(canvas) + erase(canvas) + +def frame(canvas, seconds): + """Kör en frame med canvas i seconds sekunder""" + render(canvas) + time.sleep(seconds) + erase(canvas) + +def render(canvas): + """Skriver ut canvas på skärmen""" + print(canvas) + +def erase(canvas): + """Suddar allt, tar bort det som gjorts av render""" + for _ in canvas.splitlines(): + # ANSI-escapes för att flytta markören i terminalen + print("\033[K", end="") # ta bort allt på raden + print("\033[1A", end="") # flytta en rad upp + + print("\033[K", end="") # ta bort allt på sista raden också + +def erase_windows(_): + """Suddar allt""" + os.system("cls") + +if platform.system() == "Windows": + erase = erase_windows + +def position(sprite, x, y, x_max=WIDTH, y_max=HEIGHT): + """Returnerar en canvas där sprite är på position x och y""" + sprite = sprite.strip("\n") + + max_width = max(map(len, sprite.splitlines())) + + if x < 0: + sprite = cut_left(sprite, -x) + if x > WIDTH - max_width: + sprite = cut_right(sprite, max_width-(x_max-x)) + + if x > 0: + sprite = fill_left(sprite, x) + + if y < 0: + sprite = cut_top(sprite, -y) + elif y > 0: + sprite = "\n"*y + sprite + + if (height := len(sprite.splitlines())) > y_max: + sprite = cut_bottom(sprite, height-y_max) + + return sprite + +def cut_left(sprite, n): + """Klipp bort n tecken på vänster sida""" + spritelines = sprite.splitlines() + + for row in range(len(spritelines)): + try: + spritelines[row] = spritelines[row][n:] + except IndexError: + pass + + return "\n".join(spritelines) + +def cut_right(sprite, n): + """Klipp bort n tecken på höger sida""" + spritelines = sprite.splitlines() + max_width = max(map(len, spritelines)) + + for row in range(len(spritelines)): + row_width = len(spritelines[row]) + to_cut = row_width - (max_width - n) + if to_cut > 0: + spritelines[row] = spritelines[row][:-to_cut] + + return "\n".join(spritelines) + +def fill_left(sprite, n): + """Fyller på med n blanktecken till vänter om sprite""" + spritelines = sprite.splitlines() + + for row in range(len(spritelines)): + spritelines[row] = " "*n + spritelines[row] + + return "\n".join(spritelines) + +def cut_top(sprite, n): + """Klipp bort de n översta raderna""" + try: + return "\n".join(sprite.splitlines()[n:]) + except IndexError: + pass + + return sprite + +def cut_bottom(sprite, n): + """Klipper bort de n nedersta raderna""" + spritelines = sprite.splitlines() + + try: + return "\n".join(spritelines[:len(spritelines)-n]) + except IndexError: + pass + + return sprite + +def sprite_size(sprite): + """Returnerar (bredd, höjd) för sprite""" + spritelines = sprite.splitlines() + + max_width = max(map(len, spritelines)) + max_height = len(spritelines) + + return (max_width, max_height) + +def toggle_cursor(mode): + """Ändrar visningen av markör; på om mode=True, av om mode=False""" + if mode: + print("\033[?25h", end="") # slå på markör + else: + print("\033[?25l", end="") # slå av markör + +def test(): + """Denna funktion testar animationsfunktionerna""" + COW_SPRITE = """ + __n__n__ + .------`-\00/-' + / ## ## (oo) +/ \## __ ./ + |//YY \|/ + ||| ||| +""" + + toggle_cursor(False) + init_canvas() + + frame(position(COW_SPRITE, 0, 0), 0.5) + for n in range(10): + frame(position(COW_SPRITE, -n, 0), 0.1) + for n in range(10): + frame(position(COW_SPRITE, -10+n, 0), 0.1) + for n in range(WIDTH): + frame(position(COW_SPRITE, n, math.ceil(n*HEIGHT/WIDTH)), 0.1) + + render(position(COW_SPRITE, WIDTH, math.floor(HEIGHT))) + toggle_cursor(True) + + +if __name__ == "__main__": + test() diff --git a/modules/conditionals/exercise.md b/modules/conditionals/exercise.md deleted file mode 100644 index 49d536cb..00000000 --- a/modules/conditionals/exercise.md +++ /dev/null @@ -1,11 +0,0 @@ -Övningen sker i respektive övningsgrupp. Se [ditt schema][schedule-personal] -eller [kursens övningsschema][schedule] och gå till den sal som din grupp är -hänvisad till. - -Den digitala övningsgruppen har sin övning i [zoomrummet 666 222 743 -94][zoom-room]. - -[zoom-room]: https://kth-se.zoom.us/j/66622274394 -[schedule-personal]: https://www.kth.se/social/home/personal-menu/schema/ -[schedule]: https://cloud.timeedit.net/kth/web/public01/ri1Y4X90Q5wZ6YQvQ609g9o5yyY78Z60Z7Q5Z05Q962xQYy6.html#contentlinks - diff --git a/modules/conditionals/lab/instruction.md b/modules/conditionals/lab/instruction.md index 2dc5a741..7f141723 100644 --- a/modules/conditionals/lab/instruction.md +++ b/modules/conditionals/lab/instruction.md @@ -1,14 +1,37 @@ -# Laboration: Inmatning och styrstrukturer +--- +title: Laboration om Klasser och objekt +authors: + - Daniel Bosk + - Celina Soori +--- +# Laboration: Inmatning, felhantering och styrstrukturer I denna laboration ska vi utöka programmet vi skrev i föregående laboration. I föregående laboration skrev vi två funktioner, en som beräknar en aritmetisk -summa och en som beräknar en geometrisk summa. +summa och en som beräknar en geometrisk summa, vilka har använt sig av +variabler definierade i programmet. Nu ska istället användaren få mata in dessa +värden. +För att se till att programmet inte kraschar om användaren matar in fel värden +kommer vi lägga till felhantering i koden som skriver ut ett fint meddelande +till användaren. + +## Innan du börjar koda + +Läs på om [styrstrukturer][styrstrukturer], [felhantering][felhantering] och hur [inmatning][inmatning] sker i Python. +Kom även ihåg att använda [pylint][pylint] när du kodar. + +[styrstrukturer]: https://docs.python.org/3/reference/compound_stmts.html# +[felhantering]: https://docs.python.org/3/tutorial/errors.html +[inmatning]: https://docs.python.org/3/library/functions.html#input +[pylint]: https://pypi.org/project/pylint/ ## Uppgift -Låt användaren mata in värdena för $a_1, d, g_1, q$ och $n$. Efter att summorna -är beräknade, använd lämplig styrstruktur för att skriva ut enligt följande: +Låt användaren mata in värdena för $a_1, d, g_1, q$ och $n$. Om användaren +skriver in fel typ ska programmet avslutas med ett felmeddelande. Efter att +summorna är beräknade, använd lämplig styrstruktur för att skriva ut +enligt följande: - "Den aritmetiska summan är störst" om den aritmetiska summan är (strikt) större än den geometriska, @@ -16,32 +39,74 @@ Låt användaren mata in värdena för $a_1, d, g_1, q$ och $n$. Efter att summo eller - "Summorna är lika" om de är lika. -Exempelvis: +### Exempelutskrift + +Användaren kör programmet: ``` Data för den aritmetiska summan: -a_1: 1 -d: 2 +Skriv in startvärdet (a1): a + +Det där var inte ett flyttal. Starta om programmmet och försök igen. +``` + +Användaren kör programmet igen: +``` +Data för den aritmetiska summan: +Skriv in startvärdet (a1): 1 +Skriv in differensen (d): 2 + Data för den geometriska summan: -g_1: 1.01 -q: 1.10 +Skriv in startvärdet (g1): 1.01 +Skriv in kvoten (q): 1.10 + Antal termer i summorna: -n: 10 +Skriv in antal element i följden (n): 10.1 + +Det där var inte ett heltal. Starta om programmet och försök igen. +``` + +Användaren kör programmet ytterligare en gång: +``` +Data för den aritmetiska summan: +Skriv in startvärdet (a1): 1 +Skriv in differensen (d): 2 + +Data för den geometriska summan: +Skriv in startvärdet (g1): 1.01 +Skriv in kvoten (q): 1.10 + +Antal termer i summorna: +Skriv in antal element i följden (n): 10 Den aritmetiska summan är störst. ``` +### Krav + +* Den aritmetiska och geometriska summan ska använda sig av samma $n$. +* All inmatning ska felhanteras. +* Ditt program ska kunna hantera alla testfall som visas i exempelutskriften. +* Din kod ska uppfylla kraven i rättningsmatrisen. + +### Kamraträttning + +Denna laboration redovisas inte för en lärarassistent, utan kommer kamraträttas av en kurskamrat. När du lämnat in din kod på Canvas kommer du automatiskt bli tilldelad en annan persons kod, som du ska rätta utifrån den rättningsmatris som syns bredvid inlämningen. Ladda ner koden, provkör den på din dator och fyll sedan i rättningsmatrisen. Lämna gärna konstruktiva kommentarer för att hjälpa varandra att bli ännu bättre på att koda! -## Extrauppgift +## Frivillig extrauppgift Låt programmet först fråga användaren om en summa är aritmetisk eller geometrisk. På så vis kan användaren jämföra en aritmetisk summa med en geometrisk eller två aritmetiska summor. + +### Exempelutskrift ``` Är den första summan [a]rtimetisk eller [g]eometrisk? a -a_1: 1.02 -d: 0.1 +Skriv in startvärdet (a1): 1.02 +Skriv in differensen (d): 0.1 + Är den andra summan [a]ritmetisk eller [g]eometrisk? g -g_1: 1.02 -q: 1.1 -Hur många termer, n? 10 +Skriv in startvärdet (g1): 1.02 +Skriv in kvoten (q): 1.1 + +Hur många termer (n)? 10 Den andra summan är störst. ``` diff --git a/modules/conditionals/slides/.gitignore b/modules/conditionals/slides-conditionals/.gitignore similarity index 100% rename from modules/conditionals/slides/.gitignore rename to modules/conditionals/slides-conditionals/.gitignore diff --git a/modules/conditionals/slides/Makefile b/modules/conditionals/slides-conditionals/Makefile similarity index 91% rename from modules/conditionals/slides/Makefile rename to modules/conditionals/slides-conditionals/Makefile index f18c19e6..9a1a3696 100644 --- a/modules/conditionals/slides/Makefile +++ b/modules/conditionals/slides-conditionals/Makefile @@ -1,3 +1,5 @@ +LATEXFLAGS+= -shell-escape + .PHONY: all all: notes.pdf slides.pdf diff --git a/modules/conditionals/slides-conditionals/README.md b/modules/conditionals/slides-conditionals/README.md new file mode 100644 index 00000000..bfe42f33 --- /dev/null +++ b/modules/conditionals/slides-conditionals/README.md @@ -0,0 +1,5 @@ +- [YouTube: Villkor och styrstrukturer][yt] +- [FeedbackFruits: Villkor och styrstrukturer][fbf] + +[yt]: https://youtu.be/DQdYirC9qYE +[fbf]: https://eu.feedbackfruits.com/courses/activity-course/2274f848-feb7-46b1-a62f-d64ed59509fd diff --git a/modules/functions/slides-more/abstract.tex b/modules/conditionals/slides-conditionals/abstract.tex similarity index 100% rename from modules/functions/slides-more/abstract.tex rename to modules/conditionals/slides-conditionals/abstract.tex diff --git a/modules/conditionals/slides-conditionals/contents.tex b/modules/conditionals/slides-conditionals/contents.tex new file mode 100644 index 00000000..b36519a8 --- /dev/null +++ b/modules/conditionals/slides-conditionals/contents.tex @@ -0,0 +1,281 @@ +\title{% + Villkor och styrstrukturer +} +\author{Daniel Bosk} +\institute{% + KTH EECS +} + +\mode
{\maketitle} +\mode{% + \begin{frame} + \maketitle + \end{frame} +} + +\mode* + +\begin{abstract} + \input{abstract.tex} +\end{abstract} + + +\section{Ett program} + +\begin{frame}[fragile] + \Large\texttt{bed.py} +\end{frame} + + +\section{Datatyper och operationer} + +\subsection{Numeriska typer} + +\begin{frame}[fragile] + \begin{block}{Operationer numeriska typer} + \begin{itemize} + \item \mintinline{python}|a + b| ger addition + \item \mintinline{python}|a - b| ger subtraktion + \item \mintinline{python}|a * b| ger multiplikation + \item \mintinline{python}|a / b| ger division (heltal till flyttal) + \item \mintinline{python}|a // b| ger heltalsdivision (heltal till heltal) + \item \mintinline{python}|a % b| ger resten vid heltalsdivision + \item \mintinline{python}|a ** b| ger \(a^b\) + \end{itemize} + \end{block} +\end{frame} + +\subsection{Strängar} + +\begin{frame}[fragile] + \begin{block}{Operationer strängar} + \begin{itemize} + \item \mintinline{python}|a + b| ger sammanslagning + \item \mintinline{python}|a * b| ger upprepning om \mintinline{python}|a| + är en sträng och \mintinline{python}|b| är ett heltal. + \item \mintinline{python}|a[b]| ger en tecknet på position + \mintinline{python}|b|. + \item \mintinline{python}|a[b:c]| ger en delsträng om + \mintinline{python}|b| och \mintinline{python}|c| är heltal. + \end{itemize} + \end{block} + + \pause + + \begin{block}{Metoder strängar} + \begin{itemize} + \item \texttt{.capitalize()} + \item \texttt{.center(width, fillchar)} + \item \texttt{.find(substring, start, end)} + \item \texttt{.strip()} + \item \texttt{.upper()}, \texttt{.lower()}, \texttt{.casefold()} + \end{itemize} + \end{block} +\end{frame} + +\subsection{Den booleska typen} + +\begin{frame} + \begin{center} + \mintinline[fontsize=\Large]{python}|True or False| + \end{center} +\end{frame} + +\begin{frame} + \begin{table} + \begin{tabular}{rll} + \mintinline{python}|or| & \mintinline{python}|True| & \mintinline{python}|False| \\ + \mintinline{python}|True| & \mintinline{python}|True| & \mintinline{python}|True| \\ + \mintinline{python}|False| & \mintinline{python}|True| & \mintinline{python}|False| + \end{tabular} + \caption{Sanningstabell för \mintinline{python}|or|.} + \end{table} + + \pause + + \begin{table} + \begin{tabular}{rll} + \mintinline{python}|and| & \mintinline{python}|True| & \mintinline{python}|False| \\ + \mintinline{python}|True| & \mintinline{python}|True| & \mintinline{python}|False| \\ + \mintinline{python}|False| & \mintinline{python}|False| & \mintinline{python}|False| + \end{tabular} + \caption{Sanningstabell för \mintinline{python}|and|.} + \end{table} +\end{frame} + + +\begin{frame}[fragile] + \begin{block}{Jämförelseoperationer ger booleskt resultat} + \begin{itemize} + \item \mintinline{python}|a < b| sant om \(a\) är mindre än \(b\) + \item \mintinline{python}|a <= b| sant som ovan eller om \(a\) lika med \(b\) + (\(\leq\)) + \item \mintinline{python}|a > b| sant om \(a\) större än \(b\) + \item \mintinline{python}|a >= b| sant som ovan eller om \(a\) är lika med \(b\) + (\(\geq\)) + \item \mintinline{python}|a == b| sant om \(a\) och \(b\) är lika + \end{itemize} + \end{block} + + \pause + + \begin{remark}[Vanligt misstag] + \begin{itemize} + \item \mintinline{python}|a = b| är tilldelning + \item \mintinline{python}|a == b| är jämförelse + \end{itemize} + \end{remark} +\end{frame} + + +\section{Villkor och styrstrukturer} + +\subsection{Styrstrukturer} + +\begin{frame}[fragile] + \begin{minted}[fontsize=\Large]{python} +if villkor: + print(True) +else: + print(False) + \end{minted} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[\texttt{birthyear.py}] + \inputminted[linenos]{python}{examples/birthyear.py} + \end{example} +\end{frame} + +\begin{frame}[fragile] + \begin{minted}[fontsize=\large]{python} +if villkor1: + print("villkor1 == True") +elif villkor2: + print("villkor2 == True") +. +. +. +elif villkorN: + print("villkorN == True") +else: + print(False) + \end{minted} +\end{frame} + +\begin{frame}[fragile] + \begin{example} + \begin{minted}{python} +år = int(input("När föddes du?")) + +if år < 2000: + print("Du är i hyfsad form ändå.") +elif år < 1995: + print("Du är gammal och grå!") +else: + print("Du är ung och fräsch! Än så länge!") + \end{minted} + \end{example} + + \pause + + \begin{question} + \begin{itemize} + \item Funkar inte som tänkt, varför? + \end{itemize} + \end{question} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[\texttt{birthyear.py}] + \inputminted[linenos]{python}{examples/birthyear-elif.py} + \end{example} +\end{frame} + +\section{Vårt program igen} + +\begin{frame}[fragile] + \inputminted[linenos,firstline=18]{python}{examples/bed-noerr.py} +\end{frame} + +\mode{\endinput} + +\section{Villkor och slingor} + +\subsection{Slingor} + +\begin{frame}[fragile] + \begin{center} + \begin{minted}[fontsize=\Large]{python} +while villkor: + print(True) +print(False) + \end{minted} + \end{center} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[Räkna ner] + \begin{minted}{python} +n = 10 +while n > 0: + print(f"n = {n}") + n -= 1 +print("Done") + \end{minted} + \end{example} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[Gissa talet] + \begin{minted}{python} +guess = int(input("Guess what number I'm thinking of:")) +while guess != 2: + guess = int(input("Wrong, guess again:")) +print("Finally, that's correct!") + \end{minted} + \end{example} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[Mer gissande] + \begin{minted}{python} +guess = int(input("Guess one of my favourite numbers:")) +while guess != 2 and guess != 3 and guess != 5: + guess = int(input("Wrong, guess again:")) +print(f"That's correct, {guess} is one of my favourites.") + \end{minted} + \end{example} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[Ännu mer gissande] + \begin{minted}{python} +guess = int(input("Guess one of my favourite numbers:")) +while True: + if guess == 2: + break + elif guess == 3: + break + elif guess == 5: + break + else: + guess = int(input("Wrong, guess again:")) +print(f"That's correct, {guess} is one of my favourites.") + \end{minted} + \end{example} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[Nog med gissande] + \begin{minted}{python} +guess = int(input("Guess one of my favourite numbers:")) +while True: + if guess == 2 or guess == 3 or guess == 5: + break + else: + guess = int(input("Wrong, guess again:")) +print(f"That's correct, {guess} is one of my favourites.") + \end{minted} + \end{example} +\end{frame} diff --git a/modules/conditionals/slides/examples-cinek/age.py b/modules/conditionals/slides-conditionals/examples-cinek/age.py similarity index 100% rename from modules/conditionals/slides/examples-cinek/age.py rename to modules/conditionals/slides-conditionals/examples-cinek/age.py diff --git a/modules/conditionals/slides/examples-cinek/birthyear.py b/modules/conditionals/slides-conditionals/examples-cinek/birthyear.py similarity index 100% rename from modules/conditionals/slides/examples-cinek/birthyear.py rename to modules/conditionals/slides-conditionals/examples-cinek/birthyear.py diff --git "a/modules/conditionals/slides/examples-cinek/j\303\244mf\303\266relse.py" "b/modules/conditionals/slides-conditionals/examples-cinek/j\303\244mf\303\266relse.py" similarity index 100% rename from "modules/conditionals/slides/examples-cinek/j\303\244mf\303\266relse.py" rename to "modules/conditionals/slides-conditionals/examples-cinek/j\303\244mf\303\266relse.py" diff --git a/modules/conditionals/slides/examples-cinek/vakna.py b/modules/conditionals/slides-conditionals/examples-cinek/vakna.py similarity index 100% rename from modules/conditionals/slides/examples-cinek/vakna.py rename to modules/conditionals/slides-conditionals/examples-cinek/vakna.py diff --git a/modules/conditionals/slides/examples/age.py b/modules/conditionals/slides-conditionals/examples/age.py similarity index 100% rename from modules/conditionals/slides/examples/age.py rename to modules/conditionals/slides-conditionals/examples/age.py diff --git a/modules/conditionals/slides-conditionals/examples/bed-noerr.py b/modules/conditionals/slides-conditionals/examples/bed-noerr.py new file mode 100644 index 00000000..ef5a783d --- /dev/null +++ b/modules/conditionals/slides-conditionals/examples/bed-noerr.py @@ -0,0 +1,44 @@ +import sys + +def hardness(): + """Fråga om vikt och returnera en rekommendation.""" + weight = float(input("Hur mycket väger du (kg)? ")) + + if weight < 50: + return "mjuk" + elif weight < 80: + return "mellan" + elif weight < 120: + return "hård" + else: + return "special" + +def main(): + """Huvudprogrammet""" + length = int(input("Hur lång är du? ")) + + mattress = "mjuk" + + if length < 10: + print("Ange längden i cm.") + sys.exit() + elif length < 130: + print("Du kan använda en barnsäng.") + elif length < 200: + print("Du kan använda en vanlig vuxensäng, 200 cm.") + mattress = hardness() + elif length < 220: + print("Du kan använda vår längre vuxensäng, 220 cm.") + mattress = hardness() + else: + print("Tyvärr har vi inga sängar i lager för dig, " + "du måste specialbeställa en.") + sys.exit() + + if mattress == "special": + print("Vi har ingen lämplig madrass för dig, " + "men det går att specialbeställa.") + else: + print(f"Du trivs nog bäst på en {mattress} madrass.") + +main() diff --git a/modules/conditionals/slides-conditionals/examples/bed-pep8.py b/modules/conditionals/slides-conditionals/examples/bed-pep8.py new file mode 100644 index 00000000..e5036d5d --- /dev/null +++ b/modules/conditionals/slides-conditionals/examples/bed-pep8.py @@ -0,0 +1,55 @@ +"""Ett program för att beräkna sängegenskaper""" +import sys + +def hardness(): + """Fråga om vikt och returnera en rekommendation.""" + try: + weight = float(input("Hur mycket väger du (kg)? ")) + except ValueError as err: + print(f"Din vikt måste anges med siffror: {err}") + sys.exit() + + mattress = "special" + + if weight < 50: + mattress = "mjuk" + elif weight < 80: + mattress = "mellan" + elif weight < 120: + mattress = "hård" + + return mattress + +def main(): + """Huvudprogrammet""" + try: + length = int(input("Hur lång är du? ")) + except ValueError as err: + print(f"Du måste ange din längd i hela centimeter med siffror: {err}") + sys.exit() + + mattress = "mjuk" + + if length < 10: + print("Ange längden i cm.") + sys.exit() + elif length < 130: + print("Du kan använda en barnsäng.") + elif length < 200: + print("Du kan använda en vanlig vuxensäng, 200 cm.") + mattress = hardness() + elif length < 220: + print("Du kan använda vår längre vuxensäng, 220 cm.") + mattress = hardness() + else: + print("Tyvärr har vi inga sängar i lager för dig, " + "du måste specialbeställa en.") + sys.exit() + + if mattress == "special": + print("Vi har ingen lämplig madrass för dig, " + "men det går att specialbeställa.") + else: + print(f"Du trivs nog bäst på en {mattress} madrass.") + +main() diff --git a/modules/conditionals/slides-conditionals/examples/bed.py b/modules/conditionals/slides-conditionals/examples/bed.py new file mode 100644 index 00000000..ff7700fd --- /dev/null +++ b/modules/conditionals/slides-conditionals/examples/bed.py @@ -0,0 +1,52 @@ +import sys + +def hardness(): + """Fråga om vikt och returnera en rekommendation.""" + try: + weight = float(input("Hur mycket väger du (kg)? ")) + except ValueError as err: + print(f"Din vikt måste anges med siffror: {err}") + sys.exit() + + if weight < 50: + return "mjuk" + elif weight < 80: + return "mellan" + elif weight < 120: + return "hård" + else: + return "special" + +def main(): + """Huvudprogrammet""" + try: + length = int(input("Hur lång är du? ")) + except ValueError as err: + print(f"Du måste ange din längd i hela centimeter med siffror: {err}") + sys.exit() + + mattress = "mjuk" + + if length < 10: + print("Ange längden i cm.") + sys.exit() + elif length < 130: + print("Du kan använda en barnsäng.") + elif length < 200: + print("Du kan använda en vanlig vuxensäng, 200 cm.") + mattress = hardness() + elif length < 220: + print("Du kan använda vår längre vuxensäng, 220 cm.") + mattress = hardness() + else: + print("Tyvärr har vi inga sängar i lager för dig, " + "du måste specialbeställa en.") + sys.exit() + + if mattress == "special": + print("Vi har ingen lämplig madrass för dig, " + "men det går att specialbeställa.") + else: + print(f"Du trivs nog bäst på en {mattress} madrass.") + +main() diff --git a/modules/conditionals/slides/examples/birth.py b/modules/conditionals/slides-conditionals/examples/birth.py similarity index 100% rename from modules/conditionals/slides/examples/birth.py rename to modules/conditionals/slides-conditionals/examples/birth.py diff --git a/modules/conditionals/slides/examples/birthyear.py b/modules/conditionals/slides-conditionals/examples/birthyear-elif.py similarity index 100% rename from modules/conditionals/slides/examples/birthyear.py rename to modules/conditionals/slides-conditionals/examples/birthyear-elif.py diff --git a/modules/conditionals/slides-conditionals/examples/birthyear.py b/modules/conditionals/slides-conditionals/examples/birthyear.py new file mode 100644 index 00000000..60a3fe20 --- /dev/null +++ b/modules/conditionals/slides-conditionals/examples/birthyear.py @@ -0,0 +1,8 @@ +"""Program som tar ålder som inmatning""" + +år = int(input("När föddes du? ")) + +if år < 1995: + print("Du är gammal och grå!") +else: + print("Du är ung och fräsch! Än så länge!") diff --git a/modules/conditionals/slides/examples/countdown.py b/modules/conditionals/slides-conditionals/examples/countdown.py similarity index 100% rename from modules/conditionals/slides/examples/countdown.py rename to modules/conditionals/slides-conditionals/examples/countdown.py diff --git a/modules/conditionals/slides/examples/genus.py b/modules/conditionals/slides-conditionals/examples/genus.py similarity index 100% rename from modules/conditionals/slides/examples/genus.py rename to modules/conditionals/slides-conditionals/examples/genus.py diff --git a/modules/conditionals/slides/examples/guess-annorlunda.py b/modules/conditionals/slides-conditionals/examples/guess-annorlunda.py similarity index 100% rename from modules/conditionals/slides/examples/guess-annorlunda.py rename to modules/conditionals/slides-conditionals/examples/guess-annorlunda.py diff --git a/modules/conditionals/slides/examples/guess.py b/modules/conditionals/slides-conditionals/examples/guess.py similarity index 100% rename from modules/conditionals/slides/examples/guess.py rename to modules/conditionals/slides-conditionals/examples/guess.py diff --git a/modules/conditionals/slides/examples/if.py b/modules/conditionals/slides-conditionals/examples/if.py similarity index 100% rename from modules/conditionals/slides/examples/if.py rename to modules/conditionals/slides-conditionals/examples/if.py diff --git a/modules/conditionals/slides/examples/rnd.py b/modules/conditionals/slides-conditionals/examples/rnd.py similarity index 100% rename from modules/conditionals/slides/examples/rnd.py rename to modules/conditionals/slides-conditionals/examples/rnd.py diff --git a/modules/conditionals/slides/examples/test.py b/modules/conditionals/slides-conditionals/examples/test.py similarity index 100% rename from modules/conditionals/slides/examples/test.py rename to modules/conditionals/slides-conditionals/examples/test.py diff --git a/modules/variables/slides-more/notes.tex b/modules/conditionals/slides-conditionals/notes.tex similarity index 100% rename from modules/variables/slides-more/notes.tex rename to modules/conditionals/slides-conditionals/notes.tex diff --git a/modules/variables/slides-more/preamble.tex b/modules/conditionals/slides-conditionals/preamble.tex similarity index 100% rename from modules/variables/slides-more/preamble.tex rename to modules/conditionals/slides-conditionals/preamble.tex index 9a092c5b..ee813387 100644 --- a/modules/variables/slides-more/preamble.tex +++ b/modules/conditionals/slides-conditionals/preamble.tex @@ -3,6 +3,9 @@ \usepackage[british,swedish]{babel} \usepackage{booktabs} +\usepackage[natbib,style=alphabetic,maxbibnames=99]{biblatex} +\addbibresource{slides.bib} + \usepackage[all]{foreign} \renewcommand{\foreignfullfont}{} \renewcommand{\foreignabbrfont}{} @@ -13,9 +16,6 @@ \usepackage[strict]{csquotes} \usepackage[single]{acro} -\usepackage[natbib,style=alphabetic,maxbibnames=99]{biblatex} -\addbibresource{slides.bib} - \usepackage{subcaption} \usepackage[noend]{algpseudocode} diff --git a/modules/conditionals/slides-conditionals/slides.tex b/modules/conditionals/slides-conditionals/slides.tex new file mode 100644 index 00000000..692a8dd9 --- /dev/null +++ b/modules/conditionals/slides-conditionals/slides.tex @@ -0,0 +1,108 @@ +\documentclass[ignoreframetext]{beamer} +\input{preamble.tex} + +\usetheme{Berlin} +\setbeamertemplate{footline}%{miniframes theme} +{% + \begin{beamercolorbox}[colsep=1.5pt]{upper separation line foot} + \end{beamercolorbox} + \begin{beamercolorbox}[ht=2.5ex,dp=1.125ex,% + leftskip=.3cm,rightskip=.3cm plus1fil]{author in head/foot}% + \leavevmode{\usebeamerfont{author in head/foot}\insertshortauthor}% + \hfill% + {\usebeamerfont{institute in head/foot}\usebeamercolor[fg]{institute in head/foot}\insertshortinstitute}% + \end{beamercolorbox}% + \begin{beamercolorbox}[ht=2.5ex,dp=1.125ex,% + leftskip=.3cm,rightskip=.3cm plus1fil]{title in head/foot}% + {\usebeamerfont{title in head/foot}\insertshorttitle} \hfill \insertframenumber% + \end{beamercolorbox}% + \begin{beamercolorbox}[colsep=1.5pt]{lower separation line foot} + \end{beamercolorbox} +} +\setbeamercovered{transparent} +\setbeamertemplate{bibliography item}[text] + +\AtBeginSection[]{% + \begin{frame} + \tableofcontents[currentsection] + \end{frame} +} + +\ProvideDocumentEnvironment{assumption}{o}{% + \IfValueTF{#1}{% + \begin{block}{Assumption: #1} + }{% + \begin{block}{Assumption} + } +}{% + \end{block} +} + +\ProvideDocumentEnvironment{protocol}{o}{% + \IfValueTF{#1}{% + \begin{block}{Protocol: #1} + }{% + \begin{block}{Protocol} + } +}{% + \end{block} +} + +\ProvideDocumentEnvironment{remark}{o}{% + \IfValueTF{#1}{% + \begin{alertblock}{Note: #1} + }{% + \begin{alertblock}{Note} + } +}{% + \end{alertblock} +} + +\ProvideDocumentEnvironment{idea}{o}{% + \IfValueTF{#1}{% + \begin{block}{Idea: #1} + }{% + \begin{block}{Idea} + } +}{% + \end{block} +} + +\ProvideDocumentEnvironment{question}{o}{% + \setbeamercolor{block body}{bg=orange!15,fg=black} + \setbeamercolor{block title}{bg=orange,fg=white} + \setbeamercolor{local structure}{fg=orange} + \IfValueTF{#1}{% + \begin{block}{Question: #1} + }{% + \begin{block}{Question} + } +}{% + \end{block} +} + +\ProvideDocumentEnvironment{exercise}{o}{% + \setbeamercolor{block body}{bg=yellow!10,fg=black} + \setbeamercolor{block title}{bg=yellow,fg=black} + \setbeamercolor{local structure}{fg=yellow} + \IfValueTF{#1}{% + \begin{block}{Exercise: #1} + }{% + \begin{block}{Exercise} + } +}{% + \end{block} +} + + +\begin{document} +\mode +\input{contents.tex} +\mode* +% +%%% REFERENCES %%% + +%\begin{frame}[allowframebreaks] +% \printbibliography +%\end{frame} +\end{document} diff --git a/modules/conditionals/slides-input/.gitignore b/modules/conditionals/slides-input/.gitignore new file mode 100644 index 00000000..6d2abc47 --- /dev/null +++ b/modules/conditionals/slides-input/.gitignore @@ -0,0 +1,4 @@ +notes.pdf +slides.pdf +notes-more.pdf +slides-more.pdf diff --git a/modules/conditionals/slides-input/Makefile b/modules/conditionals/slides-input/Makefile new file mode 100644 index 00000000..9a1a3696 --- /dev/null +++ b/modules/conditionals/slides-input/Makefile @@ -0,0 +1,22 @@ +LATEXFLAGS+= -shell-escape + +.PHONY: all +all: notes.pdf slides.pdf + +SRC+= preamble.tex +SRC+= abstract.tex contents.tex + +notes.pdf: notes.tex +notes.pdf: ${SRC} + +slides.pdf: slides.tex +slides.pdf: ${SRC} + + +.PHONY: clean +clean: + ${RM} notes.pdf slides.pdf + + +INCLUDE_MAKEFILES=../../../makefiles +include ${INCLUDE_MAKEFILES}/tex.mk diff --git a/modules/conditionals/slides-input/README.md b/modules/conditionals/slides-input/README.md new file mode 100644 index 00000000..aa424411 --- /dev/null +++ b/modules/conditionals/slides-input/README.md @@ -0,0 +1,5 @@ +- [YouTube: Inmatning och felhantering][yt] +- [FeedbackFruits: Inmatning och felhantering][fbf] + +[yt]: https://youtu.be/EOLHQ-eJTyU +[fbf]: https://eu.feedbackfruits.com/courses/activity-course/91c73814-3a91-4b23-b95a-283663cc2c44 diff --git a/modules/functions/slides/abstract.tex b/modules/conditionals/slides-input/abstract.tex similarity index 100% rename from modules/functions/slides/abstract.tex rename to modules/conditionals/slides-input/abstract.tex diff --git a/modules/conditionals/slides-input/contents.tex b/modules/conditionals/slides-input/contents.tex new file mode 100644 index 00000000..c4719486 --- /dev/null +++ b/modules/conditionals/slides-input/contents.tex @@ -0,0 +1,288 @@ +\title{% + Inmatning och felhantering +} +\author{Daniel Bosk} +\institute{% + KTH EECS +} + +\mode
{\maketitle} +\mode{% + \begin{frame} + \maketitle + \end{frame} +} + +\mode* + +\begin{abstract} + \input{abstract.tex} +\end{abstract} + + +\section{Ett program} + +\begin{frame}[fragile] + \inputminted[linenos,firstline=12,lastline=12]{python}{examples/age-funcs.py} + \inputminted[linenos,firstline=16,lastline=16]{python}{examples/age-funcs.py} + \inputminted[linenos,firstline=20,lastline=20]{python}{examples/age-funcs.py} + \vspace{0.5em} + \inputminted[linenos,firstline=36]{python}{examples/age-funcs.py} +\end{frame} + +\begin{frame}[fragile] + \begin{block}{Gammal} + \inputminted[linenos,firstline=36,highlightlines={36,37,39}]{python}{examples/age-funcs.py} + \end{block} + \begin{block}{Ny} + \inputminted[linenos,firstline=37,highlightlines={37,39,40}]{python}{examples/age-funcs-input.py} + \end{block} +\end{frame} + +%\begin{frame}[fragile] +% \dots +% \inputminted[linenos,firstline=20,lastline=25,highlightlines=22]{python}{examples/age-funcs-input.py} +% \dots +% \inputminted[linenos,firstline=37,highlightlines=39]{python}{examples/age-funcs-input.py} +%\end{frame} + +\section{Inmatning} + +\subsection{Inmatning av text} + +\begin{frame} + \begin{center} + \mintinline[fontsize=\Large]{python}|variable = input("Optional prompt:")| + \end{center} +\end{frame} + +\begin{frame}[fragile] + \includegraphics[height=\textheight]{figs/docs-builtins.png} +\end{frame} + +\begin{frame}[fragile] + \begin{example} + \begin{minted}{python} +age = input("How old are you? ") +print(f"Aha, so you're {age} years.") + \end{minted} + \end{example} + + \pause + + \begin{example} + \begin{minted}{python} +print("How old are you?", end=" ") +age = input() +print(f"Ah, you're only {age} years old.") + \end{minted} + \end{example} +\end{frame} + +\subsection{Inmatning av andra typer} + +\begin{frame} + \begin{remark}[\mintinline{python}|input()|] + \begin{itemize} + \item Returnerar en sträng. + \item Måste typkonvertera om man vill ha annat. + \end{itemize} + \end{remark} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[Funkar inte] + \begin{minted}{python} +age = input("How old are you?") +print(f"Ah, then I'm older, I'm {age+1}!") + \end{minted} + \end{example} + + \pause + + \begin{example}[Funkar] + \begin{minted}[highlightlines=2]{python} +age = input("How old are you?") +print(f"Oh, then I'm older, I'm {int(age)+1}!") + \end{minted} + \end{example} + + \begin{example}[Funkar] + \begin{minted}[highlightlines=1]{python} +age = int(input("How old are you?")) +print(f"Oh, then I'm older, I'm {age+1}!") + \end{minted} + \end{example} +\end{frame} + +\section{Datatyper och operationer} + +\begin{frame} + \begin{remark}[Inbyggda datatyper] + \begin{itemize} + \item \mintinline{python}|str(x)| gör om \mintinline{python}|x| till textsträng + \item \mintinline{python}|int(x)| gör om till heltal + \item \mintinline{python}|float(x)| gör om till flyttal + \item \mintinline{python}|complex(re, im)| gör om till komplext tal + \end{itemize} + \end{remark} +\end{frame} + +\subsection{Numeriska typer} + +\begin{frame}[fragile] + \begin{block}{Operationer numeriska typer} + \begin{itemize} + \item \mintinline{python}|a + b| ger addition + \item \mintinline{python}|a - b| ger subtraktion + \item \mintinline{python}|a * b| ger multiplikation + \item \mintinline{python}|a / b| ger division (heltal till flyttal) + \item \mintinline{python}|a // b| ger heltalsdivision (heltal till heltal) + \item \mintinline{python}|a % b| ger resten vid heltalsdivision + \item \mintinline{python}|a ** b| ger \(a^b\) + \end{itemize} + \end{block} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[\texttt{mod.py}] + \inputminted[linenos]{python}{examples/mod.py} + \end{example} +\end{frame} + +\subsection{Strängar} + +\begin{frame}[fragile] + \begin{block}{Operationer strängar} + \begin{itemize} + \item \mintinline{python}|a + b| ger sammanslagning + \item \mintinline{python}|a * b| ger upprepning om \mintinline{python}|a| + är en sträng och \mintinline{python}|b| är ett heltal. + \item \mintinline{python}|a[b]| ger en tecknet på position + \mintinline{python}|b|. + \item \mintinline{python}|a[b:c]| ger en delsträng om + \mintinline{python}|b| och \mintinline{python}|c| är heltal. + \end{itemize} + \end{block} +\end{frame} + +\begin{frame} + \begin{example}[\texttt{strop.py}] + \inputminted[linenos]{python}{examples/strop.py} + \end{example} +\end{frame} + +\begin{frame} + \begin{block}{Metoder strängar} + \begin{itemize} + \item \texttt{.capitalize()} + \item \texttt{.center(width, fillchar)} + \item \texttt{.find(substring, start, end)} + \item \texttt{.strip()} + \item \texttt{.upper()}, \texttt{.lower()}, \texttt{.casefold()} + \end{itemize} + \end{block} +\end{frame} + +\begin{frame} + \begin{example}[\texttt{strmeth.py}] + \inputminted[linenos]{python}{examples/strmeth.py} + \end{example} +\end{frame} + +\subsection{Vårt program} + +\begin{frame}[fragile] + \inputminted[linenos,firstline=12,lastline=14,highlightlines=14]{python}{examples/age-funcs-input.py} + \dots + \inputminted[linenos,firstline=20,lastline=25]{python}{examples/age-funcs-input.py} + \dots + \inputminted[linenos,firstline=37,highlightlines=39]{python}{examples/age-funcs-input.py} +\end{frame} + + +\section{Fel och felhantering} + +\subsection{Särfall} + +\begin{frame}[fragile] + \begin{example} + \begin{minted}{text} +>>> int("a") +Traceback (most recent call last): + File "", line 1, in +ValueError: invalid literal for int() with base 10: 'a' +>>> + \end{minted} + \end{example} +\end{frame} + +\begin{frame}[fragile] + \begin{example} + \begin{minted}{text} +>>> 5/0 +Traceback (most recent call last): + File "", line 1, in +ZeroDivisionError: division by zero +>>> + \end{minted} + \end{example} +\end{frame} + +\begin{frame}[fragile] + \begin{example} + \begin{minted}{text} +>>> prynt(3) +Traceback (most recent call last): + File "", line 1, in +NameError: name 'prynt' is not defined +>>> + \end{minted} + \end{example} +\end{frame} + +\subsection{Felhantering: att fånga särfall} + +\begin{frame} + \includegraphics[width=\columnwidth]{figs/docs-except.png} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[Fånga särfall: valuerr.py] + \inputminted{python}{examples/valuerr.py} + \end{example} + + \pause + + \begin{example} + \begin{minted}{text} +$ python3 valuerr.py +We caught this: invalid literal for int() with base 10: 'a' + \end{minted} + \end{example} +\end{frame} + +\begin{frame}[fragile] + \begin{minted}{python} +try: + # kod som kan orsaka fel +except Exception as err: + print(f"Ett okänt fel inträffade: {err}") + \end{minted} + \begin{remark} + \begin{itemize} + \item \mintinline{python}{except Exception as err} fångar \emph{allt}! + \end{itemize} + \end{remark} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[manyerr.py] + \inputminted{python}{examples/manyerr.py} + \end{example} +\end{frame} + +\begin{frame}[fragile] + \inputminted[linenos,firstline=37,highlightlines={38,41,42}]{python}{examples/age-funcs-input.py} +\end{frame} + diff --git a/modules/conditionals/slides-input/examples-cinek/age.py b/modules/conditionals/slides-input/examples-cinek/age.py new file mode 100644 index 00000000..4fe4a34a --- /dev/null +++ b/modules/conditionals/slides-input/examples-cinek/age.py @@ -0,0 +1,5 @@ +"""Exempelprogram som visar åldersexemplet med inmatning""" + +print("How old are you?", end=" ") +age = int(input()) +print(f"Aha, I'm {age+1} years, so I'm older.") diff --git a/modules/conditionals/slides-input/examples-cinek/birthyear.py b/modules/conditionals/slides-input/examples-cinek/birthyear.py new file mode 100644 index 00000000..2c8f3283 --- /dev/null +++ b/modules/conditionals/slides-input/examples-cinek/birthyear.py @@ -0,0 +1,9 @@ +"""Exempelprogram som frågar efter ålder""" + +födelseår = int(input("Vilket år är du född?")) +if födelseår < 1995: + print("Ojsan hoppsan, här var det riktigt gammalt!") +elif födelseår < 2000: + print("Oj, du börjar bli gammal!") +else: + print("Grattis, du är fortfarande ung och fräsch!") diff --git "a/modules/conditionals/slides-input/examples-cinek/j\303\244mf\303\266relse.py" "b/modules/conditionals/slides-input/examples-cinek/j\303\244mf\303\266relse.py" new file mode 100644 index 00000000..bf15023e --- /dev/null +++ "b/modules/conditionals/slides-input/examples-cinek/j\303\244mf\303\266relse.py" @@ -0,0 +1,18 @@ +"""Ett program som jämför returvärden från funktionsanrop""" + +def kvadrat(x): + """Returnerar x i kvadrat""" + return x*x + +sträng1 = input("Säg något: ") +sträng2 = input("Säg något annat: ") + +if sträng1 != sträng2: + print("Grattis, du följde instruktionen!") + print(f"Första gången sa du '{sträng1}', andra gången sa du '{sträng2}'.") + +x = float(input("Skriv ett flyttal: ")) +x2 = kvadrat(x) +print(f"{x} i kvadrat blir {x2}.") +if x2 == round(x2): + print(f"{x2} saknar decimalföljd.") diff --git a/modules/conditionals/slides-input/examples-cinek/vakna.py b/modules/conditionals/slides-input/examples-cinek/vakna.py new file mode 100644 index 00000000..98a4e0da --- /dev/null +++ b/modules/conditionals/slides-input/examples-cinek/vakna.py @@ -0,0 +1,33 @@ +"""Program som räknar ut hur länge du varit vaken""" + +def skillnad(nu, vaknade): + """Tar nuvarande tid, tiden för vaknandet och returnerar skillnaden i timmar""" + return nu - vaknade + +def hhmm_till_flyttal(hh, mm): + """Tar hh och mm och returnerar som flyttal""" + return int(hh) + int(mm)/60 + +def flyttal_till_hhmm(timmar): + """Tar timmar i flyttalsform, returnerar hh och mm""" + hh = int(timmar) + mm = round((timmar - hh)*60) + return str(hh), str(mm) + +def main(): + klockan_nu = input("Hur mycket är klockan just nu? (Ange hh:mm) ") + klockan_vaknade = input("Hur mycket var klockan när du vaknade? ") + + hh_nu, mm_nu = klockan_nu.split(":") + hh_vaknade, mm_vaknade = klockan_vaknade.split(":") + + flyttal_vaken = skillnad( + hhmm_till_flyttal(hh_nu, mm_nu), + hhmm_till_flyttal(hh_vaknade, mm_vaknade)) + + timmar_vaken, minuter_vaken = flyttal_till_hhmm(flyttal_vaken) + + print(f"Du har varit vaken i {timmar_vaken} timmar och {minuter_vaken} minuter.") + +if __name__ == "__main__": + main() diff --git a/modules/conditionals/slides-input/examples/age-funcs-input.py b/modules/conditionals/slides-input/examples/age-funcs-input.py new file mode 100644 index 00000000..edf16ace --- /dev/null +++ b/modules/conditionals/slides-input/examples/age-funcs-input.py @@ -0,0 +1,42 @@ +""" +Ett program om ålder. Illustrerar: + + - kommentarer, + - utskrifter, + - variabler, + - datatyper + - variabelnamn och konstanter +""" +THIS_YEAR = 2022 + +def age(birthyear, this_year): + """Beräknar ålder utifrån två år.""" + return this_year - birthyear + +def birthyear_age(age): + """Retunerar födelseår för att vara age år gammal.""" + return THIS_YEAR - age + +def age_game(name, birthyear): + """Skriver ut lite skoj om ålder""" + #print(f"Hej, {name}") + + # beräkna ålder + the_age = age(birthyear, THIS_YEAR) + + print(f"Du är {the_age} gammal.") + print("Nu ska du får bli 25 år igen.") + + # beräkna nytt födelseår + birthyear = birthyear_age(25) + + print(f"Du är {age(birthyear, THIS_YEAR)} år gammal, " + f"det är {the_age-age(birthyear, THIS_YEAR)} år yngre.") + + +name = input("Vad heter du? ") +try: + birthyear = int(input(f"Hej, {name}, vilket år är du född? ")) + age_game(name, birthyear) +except ValueError as err: + print(f"Årtalet måste skrivas med siffror: {err}") diff --git a/modules/conditionals/slides-input/examples/age-funcs.py b/modules/conditionals/slides-input/examples/age-funcs.py new file mode 100644 index 00000000..58842ec1 --- /dev/null +++ b/modules/conditionals/slides-input/examples/age-funcs.py @@ -0,0 +1,40 @@ +""" +Ett program om ålder. Illustrerar: + + - kommentarer, + - utskrifter, + - variabler, + - datatyper + - variabelnamn och konstanter +""" +THIS_YEAR = 2022 + +def age(birthyear, this_year): + """Beräknar ålder utifrån två år.""" + return this_year - birthyear + +def birthyear_age(age): + """Retunerar födelseår för att vara age år gammal.""" + return THIS_YEAR - age + +def age_game(name, birthyear): + """Skriver ut lite skoj om ålder""" + print(f"Hej, {name}") + + # beräkna ålder + the_age = age(birthyear, THIS_YEAR) + + print(f"Du är {the_age} gammal.") + print("Nu ska du får bli 25 år igen.") + + # beräkna nytt födelseår + birthyear = birthyear_age(25) + + print(f"Du är {age(birthyear, THIS_YEAR)} år gammal, " + f"det är {the_age-age(birthyear, THIS_YEAR)} år yngre.") + +name = "Daniel" +birthyear = 1985 + +age_game(name, birthyear) +age_game("Urban", 1950) diff --git a/modules/conditionals/slides-input/examples/age.py b/modules/conditionals/slides-input/examples/age.py new file mode 100644 index 00000000..bfaddf1f --- /dev/null +++ b/modules/conditionals/slides-input/examples/age.py @@ -0,0 +1,2 @@ +age = int(input("Hur gammal är du?")) +print(f"Då är jag ett år äldre, jag är {age+1} år.") diff --git a/modules/conditionals/slides-input/examples/manyerr.py b/modules/conditionals/slides-input/examples/manyerr.py new file mode 100644 index 00000000..cfd8e17d --- /dev/null +++ b/modules/conditionals/slides-input/examples/manyerr.py @@ -0,0 +1,16 @@ +"""Program som illustrerar hur man fångar flera typer av fel""" + +try: + x = int(input("Nominator x = ")) + y = int(input("Denominator y = ")) + print(f"{x} / {y} = {x/y}") + +except ZeroDivisionError: + print("Sorry, the denominator must be non-zero.") + +except ValueError: + print("Sorry, you must enter numbers.") + +except Exception as err: + print(f"Sorry, an unexpected error occurred: {err}") + diff --git a/modules/conditionals/slides-input/examples/mod.py b/modules/conditionals/slides-input/examples/mod.py new file mode 100644 index 00000000..2bf1516e --- /dev/null +++ b/modules/conditionals/slides-input/examples/mod.py @@ -0,0 +1,11 @@ +def integer_division(a, b): + """Skriver ut info om a heltalsdividerat med b""" + print(f"{a} = {a // b} * {b} + {a % b}") + print(f"{a} // {b} == {a // b}") + print(f"{a} % {b} == {a % b}") + +integer_division(10, 4) +print() +integer_division(10, 3) +print() +integer_division(9, 3) diff --git a/modules/conditionals/slides-input/examples/nameerr.py b/modules/conditionals/slides-input/examples/nameerr.py new file mode 100644 index 00000000..04871f4d --- /dev/null +++ b/modules/conditionals/slides-input/examples/nameerr.py @@ -0,0 +1,5 @@ +try: + prynt("3") +except Exception as err: + print(f"We caught this: {err}") + diff --git a/modules/conditionals/slides-input/examples/strmeth.py b/modules/conditionals/slides-input/examples/strmeth.py new file mode 100644 index 00000000..6c94ff23 --- /dev/null +++ b/modules/conditionals/slides-input/examples/strmeth.py @@ -0,0 +1,14 @@ +def str_methods(string1, string2): + """Visar sträng-experiment med string""" + print(f"string1 = '{string1}'") + print(f"string2 = '{string2}'") + print(f"string1.capitalize() = '{string1.capitalize()}'") + print(f"string1.upper() = '{string1.upper()}'") + print(f"string1.center(20, '=') = '{string1.center(20, '=')}'") + print(f"string2.strip() = '{string2.strip()}'") + print(f"string1.find(string2) = '{string1.find(string2)}'") + print(f"string1.find(string2.strip()) = '{string1.find(string2.strip())}'") + +str_methods("hej på dig", " hej ") +print() +str_methods("hej på dig", " på ") diff --git a/modules/conditionals/slides-input/examples/strop.py b/modules/conditionals/slides-input/examples/strop.py new file mode 100644 index 00000000..5ab25941 --- /dev/null +++ b/modules/conditionals/slides-input/examples/strop.py @@ -0,0 +1,13 @@ +def str_operators(string1, string2, number): + """Visar sträng-experiment med string""" + print(f"string1 = '{string1}'") + print(f"string2 = '{string2}'") + print(f"string1 + string2 = '{string1+string2}'") + print(f"string1 * {number} = '{string1*number}'") + print(f"string1[{number}] = '{string1[number]}'") + print(f"string2[{number}] = '{string2[number]}'") + print(f"string1[{number}:{number+3}] = '{string1[number:number+3]}'") + print(f"string2[{number}:{number+3}] = '{string2[number:number+3]}'") + +str_operators("hej på dig", "hello there", 3) +str_operators("hejsan", "svejsan", 2) diff --git a/modules/conditionals/slides-input/examples/valuerr.py b/modules/conditionals/slides-input/examples/valuerr.py new file mode 100644 index 00000000..897ac0fa --- /dev/null +++ b/modules/conditionals/slides-input/examples/valuerr.py @@ -0,0 +1,7 @@ +"""Program som visar hur särfall funkar""" + +try: + int("a") +except ValueError as err: + print(f"We caught this: {err}") + diff --git a/modules/conditionals/slides-input/examples/zerodiv.py b/modules/conditionals/slides-input/examples/zerodiv.py new file mode 100644 index 00000000..b6f78997 --- /dev/null +++ b/modules/conditionals/slides-input/examples/zerodiv.py @@ -0,0 +1,5 @@ +try: + 5/0 +except Exception as err: + print(f"We caught this: {err}") + diff --git a/modules/conditionals/slides-input/figs/docs-builtins.png b/modules/conditionals/slides-input/figs/docs-builtins.png new file mode 100644 index 00000000..0cb7e338 Binary files /dev/null and b/modules/conditionals/slides-input/figs/docs-builtins.png differ diff --git a/modules/conditionals/slides-input/figs/docs-except.png b/modules/conditionals/slides-input/figs/docs-except.png new file mode 100644 index 00000000..3e90fac5 Binary files /dev/null and b/modules/conditionals/slides-input/figs/docs-except.png differ diff --git a/modules/conditionals/slides-input/figs/docs-str.png b/modules/conditionals/slides-input/figs/docs-str.png new file mode 100644 index 00000000..085e39ca Binary files /dev/null and b/modules/conditionals/slides-input/figs/docs-str.png differ diff --git a/modules/conditionals/slides-input/notes.tex b/modules/conditionals/slides-input/notes.tex new file mode 100644 index 00000000..b6f9a884 --- /dev/null +++ b/modules/conditionals/slides-input/notes.tex @@ -0,0 +1,30 @@ +\documentclass{article} + +\usepackage[hyphens]{url} +\usepackage[hidelinks]{hyperref} + +\input{preamble.tex} + +\usepackage[noamsthm,notheorems]{beamerarticle} +\setjobnamebeamerversion{slides} + +%\usepackage{authblk} +%\let\institute\affil + +\declaretheorem[numbered=unless unique,style=theorem]{theorem} +\declaretheorem[numbered=unless unique,style=definition]{definition} +\declaretheorem[numbered=unless unique,style=definition]{assumption} +\declaretheorem[numbered=unless unique,style=definition]{protocol} +\declaretheorem[numbered=unless unique,style=example]{example} +%\declaretheorem[style=definition,numbered=unless unique, +% name=Example,refname={example,examples}]{example} +\declaretheorem[numbered=unless unique,style=remark]{remark} +\declaretheorem[numbered=unless unique,style=remark]{idea} +\declaretheorem[numbered=unless unique,style=exercise]{exercise} +\declaretheorem[numbered=unless unique,style=exercise]{question} +\declaretheorem[numbered=unless unique,style=solution]{solution} + +\begin{document} +\input{contents.tex} +\printbibliography +\end{document} diff --git a/modules/conditionals/slides/preamble.tex b/modules/conditionals/slides-input/preamble.tex similarity index 85% rename from modules/conditionals/slides/preamble.tex rename to modules/conditionals/slides-input/preamble.tex index f6c64faf..ee813387 100644 --- a/modules/conditionals/slides/preamble.tex +++ b/modules/conditionals/slides-input/preamble.tex @@ -3,6 +3,9 @@ \usepackage[british,swedish]{babel} \usepackage{booktabs} +\usepackage[natbib,style=alphabetic,maxbibnames=99]{biblatex} +\addbibresource{slides.bib} + \usepackage[all]{foreign} \renewcommand{\foreignfullfont}{} \renewcommand{\foreignabbrfont}{} @@ -13,9 +16,6 @@ \usepackage[strict]{csquotes} \usepackage[single]{acro} -\usepackage[natbib,style=alphabetic,maxbibnames=99]{biblatex} -\addbibresource{slides.bib} - \usepackage{subcaption} \usepackage[noend]{algpseudocode} @@ -23,13 +23,8 @@ \let\email\texttt -\usepackage{listings} -\lstset{% - basicstyle=\footnotesize, - numbers=left, - language=python, - showstringspaces=false -} +\usepackage[outputdir=ltxobj]{minted} +\setminted{autogobble,fontsize=\footnotesize} \usepackage{amsmath} \usepackage{amssymb} diff --git a/modules/conditionals/slides-input/slides.tex b/modules/conditionals/slides-input/slides.tex new file mode 100644 index 00000000..692a8dd9 --- /dev/null +++ b/modules/conditionals/slides-input/slides.tex @@ -0,0 +1,108 @@ +\documentclass[ignoreframetext]{beamer} +\input{preamble.tex} + +\usetheme{Berlin} +\setbeamertemplate{footline}%{miniframes theme} +{% + \begin{beamercolorbox}[colsep=1.5pt]{upper separation line foot} + \end{beamercolorbox} + \begin{beamercolorbox}[ht=2.5ex,dp=1.125ex,% + leftskip=.3cm,rightskip=.3cm plus1fil]{author in head/foot}% + \leavevmode{\usebeamerfont{author in head/foot}\insertshortauthor}% + \hfill% + {\usebeamerfont{institute in head/foot}\usebeamercolor[fg]{institute in head/foot}\insertshortinstitute}% + \end{beamercolorbox}% + \begin{beamercolorbox}[ht=2.5ex,dp=1.125ex,% + leftskip=.3cm,rightskip=.3cm plus1fil]{title in head/foot}% + {\usebeamerfont{title in head/foot}\insertshorttitle} \hfill \insertframenumber% + \end{beamercolorbox}% + \begin{beamercolorbox}[colsep=1.5pt]{lower separation line foot} + \end{beamercolorbox} +} +\setbeamercovered{transparent} +\setbeamertemplate{bibliography item}[text] + +\AtBeginSection[]{% + \begin{frame} + \tableofcontents[currentsection] + \end{frame} +} + +\ProvideDocumentEnvironment{assumption}{o}{% + \IfValueTF{#1}{% + \begin{block}{Assumption: #1} + }{% + \begin{block}{Assumption} + } +}{% + \end{block} +} + +\ProvideDocumentEnvironment{protocol}{o}{% + \IfValueTF{#1}{% + \begin{block}{Protocol: #1} + }{% + \begin{block}{Protocol} + } +}{% + \end{block} +} + +\ProvideDocumentEnvironment{remark}{o}{% + \IfValueTF{#1}{% + \begin{alertblock}{Note: #1} + }{% + \begin{alertblock}{Note} + } +}{% + \end{alertblock} +} + +\ProvideDocumentEnvironment{idea}{o}{% + \IfValueTF{#1}{% + \begin{block}{Idea: #1} + }{% + \begin{block}{Idea} + } +}{% + \end{block} +} + +\ProvideDocumentEnvironment{question}{o}{% + \setbeamercolor{block body}{bg=orange!15,fg=black} + \setbeamercolor{block title}{bg=orange,fg=white} + \setbeamercolor{local structure}{fg=orange} + \IfValueTF{#1}{% + \begin{block}{Question: #1} + }{% + \begin{block}{Question} + } +}{% + \end{block} +} + +\ProvideDocumentEnvironment{exercise}{o}{% + \setbeamercolor{block body}{bg=yellow!10,fg=black} + \setbeamercolor{block title}{bg=yellow,fg=black} + \setbeamercolor{local structure}{fg=yellow} + \IfValueTF{#1}{% + \begin{block}{Exercise: #1} + }{% + \begin{block}{Exercise} + } +}{% + \end{block} +} + + +\begin{document} +\mode +\input{contents.tex} +\mode* +% +%%% REFERENCES %%% + +%\begin{frame}[allowframebreaks] +% \printbibliography +%\end{frame} +\end{document} diff --git a/modules/conditionals/slides/contents.tex b/modules/conditionals/slides/contents.tex deleted file mode 100644 index 9d08ec03..00000000 --- a/modules/conditionals/slides/contents.tex +++ /dev/null @@ -1,313 +0,0 @@ -\title{% - Inmatning och styrstrukturer -} -\author{Daniel Bosk} -\institute{% - KTH EECS -} - -\mode
{\maketitle} -\mode{% - \begin{frame} - \maketitle - \end{frame} -} - -\mode* - -\begin{abstract} - \input{abstract.tex} -\end{abstract} - - -\section{Inmatning} - -\subsection{Inmatning av text} - -\begin{frame} - \begin{center} - \lstinline[basicstyle=\Large]{variable = input("Optional prompt:")} - \end{center} -\end{frame} - -\begin{frame}[fragile] - \begin{example} - \begin{lstlisting} -age = input("How old are you?") -print(f"Aha, so you're {age} years.") - \end{lstlisting} - \end{example} - - \pause - - \begin{example} - \begin{lstlisting} -print("How old are you?") -age = input() -print(f"Ah, you're only {age} years old.") - \end{lstlisting} - \end{example} -\end{frame} - -\subsection{Inmatning av andra typer} - -\begin{frame} - \begin{remark}[\lstinline{input()}] - \begin{itemize} - \item Returnerar en sträng. - \item Måste typkonvertera om man vill ha annat. - \end{itemize} - \end{remark} -\end{frame} - -\begin{frame}[fragile] - \begin{example}[Funkar inte] - \begin{lstlisting} -age = input("How old are you?") -print(f"Ah, then I'm older, I'm {age+1}!") - \end{lstlisting} - \end{example} - - \pause - - \begin{example}[Funkar] - \begin{lstlisting} -age = int(input("How old are you?")) -print(f"Oh, then I'm older, I'm {age+1}!") - \end{lstlisting} - \end{example} -\end{frame} - -\subsection{Datatyper} - -\begin{frame} - \begin{remark}[Inbyggda datatyper] - \begin{itemize} - \item \lstinline{str(x)} gör om \lstinline{x} till textsträng - \item \lstinline{int(x)} gör om till heltal - \item \lstinline{float(x)} gör om till flyttal - \item \lstinline{complex(re, im)} gör om till komplext tal - \end{itemize} - \end{remark} -\end{frame} - - -\section{Datatyper och operationer} - -\subsection{Den booleska typen} - -\begin{frame} - \begin{center} - \lstinline[basicstyle=\Large]{True or False} - \end{center} -\end{frame} - -\begin{frame} - \begin{table} - \begin{tabular}{rll} - \lstinline$or$ & \lstinline$True$ & \lstinline$False$ \\ - \lstinline$True$ & \lstinline$True$ & \lstinline$True$ \\ - \lstinline$False$ & \lstinline$True$ & \lstinline$False$ - \end{tabular} - \caption{Sanningstabell för \lstinline{or}.} - \end{table} - - \pause - - \begin{table} - \begin{tabular}{rll} - \lstinline$and$ & \lstinline$True$ & \lstinline$False$ \\ - \lstinline$True$ & \lstinline$True$ & \lstinline$False$ \\ - \lstinline$False$ & \lstinline$False$ & \lstinline$False$ - \end{tabular} - \caption{Sanningstabell för \lstinline{and}.} - \end{table} -\end{frame} - - -\subsection{Numeriska typer} - -\begin{frame}[fragile] - \begin{block}{Operationer numeriska typer} - \begin{itemize} - \item \lstinline{a + b} ger addition - \item \lstinline{a - b} ger subtraktion - \item \lstinline{a * b} ger multiplikation - \item \lstinline{a / b} ger division (heltal till flyttal) - \item \lstinline{a // b} ger heltalsdivision (heltal till heltal) - \item \lstinline{a % b} ger resten vid heltalsdivision - \item \lstinline{a ** b} ger \(a^b\) - \end{itemize} - \end{block} -\end{frame} - -\begin{frame}[fragile] - \begin{block}{Jämförelseoperationer ger booleskt resultat} - \begin{itemize} - \item \lstinline{a < b} sant om \(a\) är mindre än \(b\) - \item \lstinline{a <= b} sant som ovan eller om \(a\) lika med \(b\) - (\(\leq\)) - \item \lstinline{a > b} sant om \(a\) större än \(b\) - \item \lstinline{a >= b} sant som ovan eller om \(a\) är lika med \(b\) - (\(\geq\)) - \item \lstinline{a == b} sant om \(a\) och \(b\) är lika - \end{itemize} - \end{block} - - \pause - - \begin{remark}[Vanligt misstag] - \begin{itemize} - \item \lstinline{a = b} är tilldelning - \item \lstinline{a == b} är jämförelse - \end{itemize} - \end{remark} -\end{frame} - - -\section{Villkor och styrstrukturer} - -\subsection{Styrstrukturer} - -\begin{frame}[fragile] - \begin{lstlisting}[basicstyle=\Large,numbers=none] -if villkor: - print(True) -else: - print(False) - \end{lstlisting} -\end{frame} - -\begin{frame}[fragile] - \begin{example} - \begin{lstlisting} -birthyear = int(input("What year were you born?")) -if birthyear < 2000: - print("You're old!") -else: - print("Congrats, you're a millenial!") - \end{lstlisting} - \end{example} -\end{frame} - -\begin{frame}[fragile] - \begin{lstlisting}[basicstyle=\large,numbers=none] -if villkor1: - print("villkor1 == True") -elif villkor2: - print("villkor2 == True") -. -. -. -elif villkorN: - print("villkorN == True") -else: - print(False) - \end{lstlisting} -\end{frame} - -\begin{frame}[fragile] - \begin{example} - \begin{lstlisting} -birthyear = int(input("What year were you born?")) -if birthyear < 2000: - print("You're old!") -elif birthyear < 1990: - print("Wow, you're ancient!") -else: - print("Congrats, you're a millenial!") - \end{lstlisting} - \end{example} - - \pause - - \begin{question} - \begin{itemize} - \item Funkar inte som tänkt, varför? - \end{itemize} - \end{question} -\end{frame} - - -\mode{\endinput} - -\section{Villkor och slingor} - -\subsection{Slingor} - -\begin{frame}[fragile] - \begin{center} - \begin{lstlisting}[basicstyle=\Large,numbers=none] -while villkor: - print(True) -print(False) - \end{lstlisting} - \end{center} -\end{frame} - -\begin{frame}[fragile] - \begin{example}[Räkna ner] - \begin{lstlisting} -n = 10 -while n > 0: - print(f"n = {n}") - n -= 1 -print("Done") - \end{lstlisting} - \end{example} -\end{frame} - -\begin{frame}[fragile] - \begin{example}[Gissa talet] - \begin{lstlisting} -guess = int(input("Guess what number I'm thinking of:")) -while guess != 2: - guess = int(input("Wrong, guess again:")) -print("Finally, that's correct!") - \end{lstlisting} - \end{example} -\end{frame} - -\begin{frame}[fragile] - \begin{example}[Mer gissande] - \begin{lstlisting} -guess = int(input("Guess one of my favourite numbers:")) -while guess != 2 and guess != 3 and guess != 5: - guess = int(input("Wrong, guess again:")) -print(f"That's correct, {guess} is one of my favourites.") - \end{lstlisting} - \end{example} -\end{frame} - -\begin{frame}[fragile] - \begin{example}[Ännu mer gissande] - \begin{lstlisting} -guess = int(input("Guess one of my favourite numbers:")) -while True: - if guess == 2: - break - elif guess == 3: - break - elif guess == 5: - break - else: - guess = int(input("Wrong, guess again:")) -print(f"That's correct, {guess} is one of my favourites.") - \end{lstlisting} - \end{example} -\end{frame} - -\begin{frame}[fragile] - \begin{example}[Nog med gissande] - \begin{lstlisting} -guess = int(input("Guess one of my favourite numbers:")) -while True: - if guess == 2 or guess == 3 or guess == 5: - break - else: - guess = int(input("Wrong, guess again:")) -print(f"That's correct, {guess} is one of my favourites.") - \end{lstlisting} - \end{example} -\end{frame} - diff --git a/modules/conditionals/dansa.py b/modules/conditionals/tutorial-advanced/dansa.py similarity index 100% rename from modules/conditionals/dansa.py rename to modules/conditionals/tutorial-advanced/dansa.py diff --git a/modules/conditionals/tutorial-advanced/fibonacci.py b/modules/conditionals/tutorial-advanced/fibonacci.py new file mode 100644 index 00000000..9c1aa8a8 --- /dev/null +++ b/modules/conditionals/tutorial-advanced/fibonacci.py @@ -0,0 +1,17 @@ +from functools import lru_cache + +# Det Fibonacci number som ska skrivas ut +FIBONACCI_NUMMER = 500 + + +@lru_cache +def fibonacci(n: int) -> int: + """Beräkna det n:te Fibonacci numret. Krav: n >= 0.""" + if n < 2: + return 1 + else: + return fibonacci(n-2) + fibonacci(n-1) + + +if __name__ == "__main__": + print(f"fibonacci({FIBONACCI_NUMMER}) = {fibonacci(FIBONACCI_NUMMER)}") diff --git a/modules/conditionals/tutorial.md b/modules/conditionals/tutorial-advanced/instruction.md similarity index 78% rename from modules/conditionals/tutorial.md rename to modules/conditionals/tutorial-advanced/instruction.md index 903f9902..4dcc18bd 100644 --- a/modules/conditionals/tutorial.md +++ b/modules/conditionals/tutorial-advanced/instruction.md @@ -1,35 +1,92 @@ --- -title: Övning om inmatning och villkorssatser +title: Fördjupande övning om inmatning och villkorssatser authors: - Daniel Bosk + - Celina Soori --- -# Övning: inmatning och villkorssatser +# Fördjupande övning: inmatning, felhantering och villkorssatser -Målet med övningen är att du ska blir bättre på att +Målet med övningen är att du ska få en fördjupad förståelse för hur du ska - tillämpa styrstrukturer, + - felhantera inmatning, - konstruera interaktiva program, - dela upp problem i mindre problem, - - minimera kodupprepning, - - bekanta dig med rekursion. + - minimera kodupprepning +## Veckans övningsgrupp -## Laborationen +... -Hur har olika grupper löst samma labb? Oftast väldigt olika. Vi går igenom -några lösningar. Hur löser man extrauppgiften? +## Önskemål från gruppen + +Var det något särskilt från veckans föreläsning och/eller OLI-material som gruppen vill gå in djupare på? + +Är det någon som vill visa upp något särskilt från förra veckans laboration som kan ge inspiration till gruppen? + +## Övningsuppgifter + +### Finn fem fel + +Dela upp er i par och låt en av er ladda ner ett program för [att köpa +biobiljetter](https://github.com/dbosk/intropy/blob/master/modules/conditionals/tutorial/movietickets.py) + +Läs igenom koden och få ett hum om vad den är tänkt att göra. Testa att köra koden. + +Hitta nu tillsammans minst fem fel/utvecklingsområden i koden (tänk på vad ni lärt er under veckan). + +Förbättra nu koden efter det ni hittat. Blev koden mer lättläst, användbar och/eller användarvänlig? Varför? + +### Bombspelet + +Vi har satt ihop ett frågespel. Svarar man fel detoneras bomben. + +Det behövs två filer: [bomben.py][bomben] och [bomb.py][bomb]. Båda måste ligga +i samma katalog. Därefter kör man bomben.py: `python3 bomben.py`. + +[bomben]: https://github.com/dbosk/intropy/blob/master/modules/conditionals/tutorial/bomben.py +[bomb]: https://github.com/dbosk/intropy/blob/master/modules/conditionals/tutorial/bomb.py + + + +### Frågesport + +Ett klassiskt program för att experimentera med villkor är frågesport. Skriv +ett frågeprogram med kluriga frågor. För att mäta hur lång tid en användare tar +på sig kan man använda följande konstruktion: +```python +""" +Exempelprogram för tidsmätning + +Vi sparar klockslaget vid start och klockslaget vid slut, sedan tar vi +skillnaden. +""" + +import datetime as dt -## Att göra saker +start_time = dt.datetime.now() + +svar = input("Vad är svaret på frågan? ") + +end_time = dt.datetime.now() + +print(f"Tidsåtgång: {end_time-start_time}") +``` + +Tips: använd funktioner för att åstadkomma straffrundor vid fel svar. -Vi ska nu fokusera på att skriva funktioner som fokuserar på att dela upp -algoritmer i deras beståndsdelar. Den här gången kommer algoritmerna att kunna -bli lite mer avancerade, de ska kunna göra olika saker beroende på olika + +### Att göra saker + +Vi ska nu fokusera på att skriva funktioner som fokuserar på att dela upp +algoritmer i deras beståndsdelar. Den här gången kommer algoritmerna att kunna +bli lite mer avancerade, de ska kunna göra olika saker beroende på olika villkor. Vi börjar med [ett exempel för att gå][walk]: ```python -"""Ett program som illustrerar funktionsuppdelningen i att gå, dock med en +"""Ett program som illustrerar funktionsuppdelningen i att gå, dock med en tämligen udda gångstil.""" def take_step_first(the_leg): @@ -68,23 +125,24 @@ def walk_fwd(meters): walk_fwd(2) ``` -Givetvis kan vi dela upp funktionen `lift_leg` ytterligare. Du kan även se en +Givetvis kan vi dela upp funktionen `lift_leg` ytterligare. Du kan även se en [interaktiv genomgång av exekveringen][walk-tutor]. -[walk]: https://github.com/dbosk/intropy/blob/master/modules/conditionals/walk.py +[walk]: https://github.com/dbosk/intropy/blob/master/modules/conditionals/tutorial-advanced/walk.py [walk-tutor]: https://pythontutor.com/visualize.html#code=%22%22%22Ett%20program%20som%20illustrerar%20funktionsuppdelningen%20i%20att%20g%C3%A5,%20dock%20med%20en%20%0At%C3%A4mligen%20udda%20g%C3%A5ngstil.%22%22%22%0A%0Adef%20take_step_first%28the_leg%29%3A%0A%20%20%20%20%22%22%22En%20funktion%20som%20anropar%20funktionerna%20som%20beh%C3%B6vs%20f%C3%B6r%20att%20ta%20ett%20steg%22%22%22%0A%20%20%20%20lift_leg%28the_leg%29%0A%20%20%20%20lean_body%28%22fram%C3%A5t%22%29%0A%0Adef%20take_step_second%28the_leg%29%3A%0A%20%20%20%20%22%22%22En%20funktion%20som%20anropar%20funktionerna%20f%C3%B6r%20att%20ta%20det%20kompletterande%20steget%22%22%22%0A%20%20%20%20lift_leg%28the_leg%29%0A%20%20%20%20lean_body%28%22bak%C3%A5t%22%29%0A%20%20%20%20put_leg%28the_leg%29%0A%0Adef%20lift_leg%28the_leg%29%3A%0A%20%20%20%20%22%22%22Lyfter%20ett%20ben,%20the_leg%20anger%20h%C3%B6ger%20eller%20v%C3%A4nster%22%22%22%0A%20%20%20%20print%28f%22lyft%20%7Bthe_leg%7D%20ben%22%29%0A%0Adef%20put_leg%28the_leg%29%3A%0A%20%20%20%20%22%22%22S%C3%A4tter%20ner%20ett%20ben%20som%20%C3%A4r%20i%20luften%22%22%22%0A%20%20%20%20print%28f%22s%C3%A4tt%20ned%20%7Bthe_leg%7D%20ben%22%29%0A%0Adef%20lean_body%28direction%29%3A%0A%20%20%20%20%22%22%22Luta%20kroppen,%20direction%20anger%20riktning%22%22%22%0A%20%20%20%20print%28f%22luta%20kroppen%20%7Bdirection%7D%22%29%0A%0Adef%20walk_1m_fwd%28%29%3A%0A%20%20%20%20%22%22%22En%20funktion%20som%20g%C3%A5r%20en%20meter%20fram%C3%A5t%22%22%22%0A%20%20%20%20take_step_first%28%22h%C3%B6ger%22%29%0A%20%20%20%20take_step_second%28%22v%C3%A4nster%22%29%0A%0Adef%20walk_fwd%28meters%29%3A%0A%20%20%20%20%22%22%22En%20funktion%20som%20g%C3%A5r%20meters%20antal%20meter%20fram%C3%A5t%22%22%22%0A%20%20%20%20if%20meters%20%3E%200%3A%0A%20%20%20%20%20%20%20%20walk_1m_fwd%28%29%0A%20%20%20%20%20%20%20%20walk_fwd%28meters-1%29%0A%0Awalk_fwd%282%29&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false Skriv program som, på samma sätt som ovan, skriver ut instruktioner för - att gå till olika platser som användaren kan välja mellan. - - gå en slumpmässig promenad (höger, vänster, framåt, bakåt) som är $n$ meter + - gå en slumpmässig promenad (höger, vänster, framåt, bakåt) som är $n$ meter lång. - - att dansa (valfri dans) $n$ takter, vilka steg ska tas med vilka fötter vid + - att dansa (valfri dans) $n$ takter, vilka steg ska tas med vilka fötter vid de olika tillfällena i musiken? + - reagerar om användaren går in i en vägg, ramlar ner i ett hål m.m. Vi går igenom olika lösningar. -En användbar byggsten för promenaden och för att få lite variation i dansen är +En användbar byggsten för promenaden och för att få lite variation i dansen är slump. Följande kod illustrerar hur vi kan slumpa tal. ```python """Ett program som illustrerar hur man skapar slumptal i Python""" @@ -95,51 +153,7 @@ slumptal = random.randint(1, 10) print(f"Slumptalet är {slumptal}.") ``` -Vi kan även gå igenom [ett exempel som använder denna och skapar en slumpmässig +Vi kan även gå igenom [ett exempel som använder denna och skapar en slumpmässig dans][random-dance]. -[random-dance]: https://github.com/dbosk/intropy/blob/master/modules/conditionals/dance.py - - -## Bombspelet - -Vi har satt ihop ett frågespel. Svarar man fel detoneras bomben. - -Det behövs två filer: [bomben.py][bomben] och [bomb.py][bomb]. Båda måste ligga -i samma katalog. Därefter kör man bomben.py: `python3 bomben.py`. - -[bomben]: https://github.com/dbosk/intropy/blob/master/modules/conditionals/bomben.py -[bomb]: https://github.com/dbosk/intropy/blob/master/modules/conditionals/bomb.py - - - -## Frågesport - -Ett klassiskt program för att experimentera med villkor är frågesport. Skriv -ett frågeprogram med kluriga frågor. För att mäta hur lång tid en användare tar -på sig kan man använda följande konstruktion: -```python -""" -Exempelprogram för tidsmätning - -Vi sparar klockslaget vid start och klockslaget vid slut, sedan tar vi -skillnaden. -""" - -import datetime as dt - -start_time = dt.datetime.now() - -svar = input("Vad är svaret på frågan? ") - -end_time = dt.datetime.now() - -print(f"Tidsåtgång: {end_time-start_time}") -``` - -Tips: använd funktioner för att åstadkomma straffrundor vid fel svar. - - -## Önskemål från gruppen - -Vad vill gruppen gå igenom igen från veckan som var? +[random-dance]: https://github.com/dbosk/intropy/blob/master/modules/conditionals/tutorial-advanced/dansa.py diff --git a/modules/conditionals/walk.py b/modules/conditionals/tutorial-advanced/walk.py similarity index 100% rename from modules/conditionals/walk.py rename to modules/conditionals/tutorial-advanced/walk.py diff --git a/modules/conditionals/walk_to.py b/modules/conditionals/tutorial-advanced/walk_to.py similarity index 100% rename from modules/conditionals/walk_to.py rename to modules/conditionals/tutorial-advanced/walk_to.py diff --git a/modules/conditionals/bomb.py b/modules/conditionals/tutorial/bomb.py similarity index 67% rename from modules/conditionals/bomb.py rename to modules/conditionals/tutorial/bomb.py index 4a0354bf..a7f2a922 100644 --- a/modules/conditionals/bomb.py +++ b/modules/conditionals/tutorial/bomb.py @@ -1,33 +1,45 @@ -"""Ett bibliotek för att animera en bomb i terminalen +""" +Ett bibliotek för att animera en bomb i terminalen ASCII-art från ASCII Art Archive: - https://www.asciiart.eu/weapons/explosives""" + https://www.asciiart.eu/weapons/explosives + +ANSI-escape för att sudda animeringen från: + + https://gist.github.com/pfreixes/a911dd6e17aca6bcc6a2 +""" import time import sys -SCREEN_SIZE = 50 - def detonera(): """Denna funktion detonerar bomben""" oantänd() time.sleep(0.5) + sudda() antänd() time.sleep(0.5) - for n in range(6): + for n in range(7): + sudda() explodera(n) - time.sleep(0.1) sys.exit(1) +def sudda(): + """Sudda 11 rader""" + for n in range(11): + print("\033[K", end="") + print("\033[1A", end="") + def oantänd(): """Skriver ut en oantänd dynamit""" - for x in range(SCREEN_SIZE): - print() print(""" + + + ) ( .-`-. @@ -38,9 +50,10 @@ def oantänd(): def antänd(): """Skriver ut en antänd dynamit""" - for x in range(SCREEN_SIZE): - print() print(""" + + + \|/ - o - /-`-. @@ -51,39 +64,62 @@ def antänd(): def explodera(n): """Skriver ut steg n i explosionsförloppet, 0 <= n <= 5.""" - for x in range(SCREEN_SIZE): - print() if n == 0: print(""" + + + + + .---. : | : :-o-: :_|_: """) + time.sleep(0.1) elif n == 1: print(""" + + + + + .---. (\|/) --0-- (/|\) """) + time.sleep(0.1) elif n == 2: print(""" + + + + '.\|/.' (\ /) - -O- - (/ \) ,'/|\'. """) + time.sleep(0.1) elif n == 3: print(""" + + + + + '. \ | / ,' `. `.' ,' ( .`.|,' .) - ~ -0- ~ - """) + time.sleep(0.1) elif n == 4: print(""" + + ','|'.` ) .' .'. '. ,' / | \ '. @@ -92,6 +128,7 @@ def explodera(n): . `` ,'. " ~ ( ~ - """) + time.sleep(0.1) elif n == 5: print(""" . ','|` ` . @@ -103,4 +140,17 @@ def explodera(n): ( ) ) / ,---. +""") + time.sleep(0.5) + elif n == 6: + print(""" + + + + + + + + + ,--. """) diff --git a/modules/conditionals/bomben.py b/modules/conditionals/tutorial/bomben.py similarity index 100% rename from modules/conditionals/bomben.py rename to modules/conditionals/tutorial/bomben.py diff --git a/modules/conditionals/tutorial/instruction.md b/modules/conditionals/tutorial/instruction.md new file mode 100644 index 00000000..cdbc237f --- /dev/null +++ b/modules/conditionals/tutorial/instruction.md @@ -0,0 +1,81 @@ +--- +title: Övning om inmatning och villkorssatser +authors: + - Daniel Bosk + - Celina Soori +--- +# Övning: inmatning, felhantering och villkorssatser + +Målet med övningen är att du ska bli bättre på att + + - tillämpa styrstrukturer, + - felhantera inmatning, + - konstruera interaktiva program, + - dela upp problem i mindre problem, + - minimera kodupprepning + +## Veckans övningsgrupp + +... + + +## Önskemål från gruppen + +Var det något särskilt från veckans föreläsning och/eller OLI-material som gruppen vill gå igenom igen? + +Gick förra veckans laboration bra? Finns det något ni skulle vilja gå igenom från laborationen? + +## Övningsuppgifter + +### Finn fem fel + +Dela upp er i par och låt en av er ladda ner ett program för [att köpa +biobiljetter](https://github.com/dbosk/intropy/blob/master/modules/conditionals/tutorial/movietickets.py) + +Läs igenom koden och få ett hum om vad den är tänkt att göra. Testa att köra koden. + +Hitta nu tillsammans minst fem fel/utvecklingsområden i koden (tänk på vad ni lärt er under veckan). + +Förbättra nu koden efter det ni hittat. Blev koden mer lättläst, användbar och/eller användarvänlig? Varför? + +### Bombspelet + +Vi har satt ihop ett frågespel. Svarar man fel detoneras bomben. + +Det behövs två filer: [bomben.py][bomben] och [bomb.py][bomb]. Båda måste ligga +i samma katalog. Därefter kör man bomben.py: `python3 bomben.py`. + +[bomben]: +https://github.com/dbosk/intropy/blob/master/modules/conditionals/tutorial/bomben.py +[bomb]: +https://github.com/dbosk/intropy/blob/master/modules/conditionals/tutorial/bomb.py + +Kör igenom spelet utan att detonera bomben. Skapa därefter ett eget bombspel åt +de andra i klassen. + + +### Frågesport + +Ett klassiskt program för att experimentera med villkor är frågesport. Skriv +ett frågeprogram med kluriga frågor. För att mäta hur lång tid en användare tar +på sig kan man använda följande konstruktion: +```python +""" +Exempelprogram för tidsmätning + +Vi sparar klockslaget vid start och klockslaget vid slut, sedan tar vi +skillnaden. +""" + +import datetime as dt + +start_time = dt.datetime.now() + +svar = input("Vad är svaret på frågan? ") + +end_time = dt.datetime.now() + +print(f"Tidsåtgång: {end_time-start_time}") +``` + +Tips: använd funktioner för att åstadkomma straffrundor vid fel svar. diff --git a/modules/conditionals/tutorial/movietickets.py b/modules/conditionals/tutorial/movietickets.py new file mode 100644 index 00000000..aad5a82f --- /dev/null +++ b/modules/conditionals/tutorial/movietickets.py @@ -0,0 +1,15 @@ +barn_pris = 10 +vuxen_pris = 20 + +antal_biljetter = input("Hur många biljetter vil du köpa? ") +antalBiljetter = int(antal_biljetter) + +antal_vuxen = input("Hur många av de biljetterna är för en vuxen? ") +antalVuxen = int(antal_vuxen) + +antal_barn = antalBiljetter - antalVuxen + +total_pris = antal_barn*barn_pris + antalVuxen*vuxen_pris + +print("Du ska betala:") +print(total_pris) diff --git a/modules/conditionals/slump.py b/modules/conditionals/tutorial/slump.py similarity index 100% rename from modules/conditionals/slump.py rename to modules/conditionals/tutorial/slump.py diff --git a/modules/conditionals/timing.py b/modules/conditionals/tutorial/timing.py similarity index 100% rename from modules/conditionals/timing.py rename to modules/conditionals/tutorial/timing.py diff --git a/modules/containers/lab/instruction.md b/modules/containers/lab/instruction.md index 39a859c3..40dfb68c 100644 --- a/modules/containers/lab/instruction.md +++ b/modules/containers/lab/instruction.md @@ -1,54 +1,113 @@ -# Laboration: Behållare och iterationer +--- +title: Laboration om Klasser, behållare och upprepningar +authors: + - Celina Soori + - Daniel Bosk +--- +# Laboration: Klasser, behållare och upprepningar -Hittills har vi arbetat med aritmetiska och geometriska talföljder, d.v.s. att -$d$ och $q$ har varit konstanta. Nu ska vi fokusera på den geometriska -talföljden och vi ska dessutom låta värdet på $q$ variera över tid. Som vi -nämnt tidigare kan geometriska talföljder användas för att räkna på räntor. -Räntor kan dock variera över tid och det är därför vi vill låta $q$ variera. +Hittills i kursen har vi jobbat med existerande datatyper i Python. +I den här laborationen ska ni istället skapa er egen sammansatta datatyp genom att +skriva er första klass. Ni kommer öva på att skapa objekt av er typ och +att spara ner dessa i en behållare som ni sedan ska iterera igenom. -När vi arbetar med räntor, då är det dock de olika talen i följden som är -intressanta, inte summan. Vi påminner oss om definitionen för en geometrisk -talföljd från tidigare: Låt oss säga att det första elementet i följden är -$g_1$ (det ursprungliga beloppet) och kvoten är $q$ (räntan som är densamma för -alla månader). Då kan vi beräkna $g_n = g_1 q^{n-1}$, d.v.s. beloppet $n$ -månader senare. +I laborationen ska ni öva på att representera ett objekt med en sträng. Fördelen med +att representera objekt på ett bättre sätt är att det underlättar +för den som ska programmera. Det kan göra koden mer intuitiv, mer läsbar. Detta +minskar risken för fel (buggar). +## Innan du börjar koda + +Läs på om [klasser][klasser], [listor][listor] och [upprepningar][upprepningar]. + +[klasser]: https://docs.python.org/3/tutorial/classes.html +[listor]: https://docs.python.org/3/library/stdtypes.html#lists +[upprepningar]: https://docs.python.org/3/reference/compound_stmts.html?highlight=while#the-while-statement ## Uppgift -Skriv en funktion som returnerar $g_n$ givet en lista -$$q = (q_1, \ldots, q_{n-1})$$ -(d.v.s. $q$ som varierar över tid). Tidigare hade vi endast ett värde i $q$ och -använde samma värde alla $n$ gånger. Låt $q$ innehålla en lista med $n$ värden -istället. (Rent terminologiskt betyder detta också att vi inte längre arbetar -med en geometrisk talföljd, då definitionen förutsätter att $q$ är konstant.) -Vi måste alltså iterera över listan, då formeln inte längre fungerar. - -**Test**: Vi kan testa koden med korta exempel som vi kan beräkna för hand (som -ovan). Vi kan även testa koden genom att mata in samma värden för $q$, d.v.s. -att $q_1 = q_2 = \cdots = q_n$, för då kan vi använda formlerna för att beräkna -det sista talet i följden. - -**Exempeltillämpning**: Säg att vi har ett sparkonto där räntan varierar och vi -vill uppskatta inkomsten från räntan för ett år framåt. Då låter vi $g_1$ vara -vårt ursprungliga sparkapital, medan $q_1, \ldots, q_{12}$ är räntan för varje -månad. Då kommer vi att ha $g_1\cdot q_1\cdot q_2\cdots q_{12}$ kronor på -sparkontot när alla månader passerat. - -**Inlämning**: Låt ditt program fråga användaren efter antalet månader ($n$) -och det ursprungliga sparkapitalet ($g_1$). Skriv ut sparkapitalets totala -värde och värdeökning månad för månad. Exempelvis: +Definiera en klass "Student" som har minst tre attribut: __förnamn__, __efternamn__ och __personnummer__. +Klassen ska ha minst två metoder, `__init__` och `__str__`. + +Skapa minst tre objekt av typen "Student" genom att be användaren skriva in +information om studenter. Fundera på bästa sättet att spara ner de skapade objekten. + +När alla objekt är skapade ska programmet skriva ut alla skapade objekt. + +### Exempelutskrift + +``` +Vad heter studenten? Jan Jansson +Vad är studentens personnummer? 0404040010 + +Objektet skapat! + +Vad heter studenten? Per Persson +Vad är studentens personnummer? 0303030030 + +Objektet skapat! + +Vad heter studenten? Emma Emilsson +Vad är studentens personnummer? 010101000a +Personnumret får bara innehålla siffror, försök igen! +Vad är studentens personnummer? 0101010000 + +Objektet skapat! + +Här är alla sparade objekt: +Namn: Jan Jansson Personnr: 0404040010 +Namn: Per Persson Personnr: 0303030030 +Namn: Emma Emilsson Personnr: 0101010000 ``` -Hur mycket sparkapital har du (ange i kr)? 1000 -Hur många månader avser du spara? 2 -Ange ränta för månad 1 (i procent): 2 -Ange ränta för månad 2 (i procent): 1 - - Total Ökning -Månad 0: 1000.00 kr 0.00 kr -Månad 1: 1020.00 kr 20.00 kr -Månad 2: 1030.20 kr 30.20 kr + +### Krav + +* Programmet ska uppfylla alla krav nämnda i beskrivningen. +* All inmatning ska felhanteras med hjälp av lämplig hjälpfunktion. +* Din kod ska uppfylla kraven i rättningsmatrisen. + +### Kamraträttning + +Denna laboration redovisas inte för en lärarassistent, utan kommer kamraträttas av en kurskamrat. När du lämnat in din kod på Canvas kommer du automatiskt bli tilldelad en annan persons kod, som du ska rätta utifrån den rättningsmatris som syns bredvid inlämningen. Ladda ner koden, provkör den på din dator och fyll sedan i rättningsmatrisen. Lämna gärna konstruktiva kommentarer för att hjälpa varandra att bli ännu bättre på att koda! + +## Frivilliga extrauppgifter + +### Redigera listan + +I grunduppgiften kan vi endast lägga till objekt av typen Student. +Lägg till så att användaren kan ändra och ta bort objekt från listan. + +#### Exempelutskrift + +``` +Vill du lägga till (l), ändra (a) eller ta bort (t) ett objekt? a + +Skriv in personnumret på objektet du vill ändra: 0101010000 +Vill du ändra namn på Emma Löv (j/n)? j +Skriv in det nya namnet: Ebba Löv + +Nu är namnet för 0101010000 ändrat till Ebba Löv! +``` + +### Lägga till många studenter + +Ändra så att programmet kan fråga efter $n$ studenter istället för bara tre. + +#### Exempelutskrift +``` +Hur många studenter vill du lägga till? 2 + +Vad heter studenten? Jan Jansson +Vad är studentens personnummer? 0404040010 + +Objektet skapat! + +Vad heter studenten? Per Persson +Vad är studentens personnummer? 0303030030 + +Objektet skapat! + +Här är alla sparade objekt: +Namn: Jan Jansson Personnr: 0404040010 +Namn: Per Persson Personnr: 0303030030 ``` -Använd din funktion för att beräkna värdena. (Inmatningarna ska givetvis -repeteras tills att värdena är korrekta, återanvänd funktionerna från -föregående laboration --- men du får givetvis skriva om dem om det behövs.) diff --git a/modules/containers/tutorial/advanced_instruction.md b/modules/containers/tutorial/advanced_instruction.md new file mode 100644 index 00000000..3084fc8e --- /dev/null +++ b/modules/containers/tutorial/advanced_instruction.md @@ -0,0 +1,126 @@ +--- +title: Övning om klasser och behållare +authors: + - Daniel Bosk + - Celina Soori +--- +# Fördjupande övning: Fler behållare och mer klasser + +Målet med övningen är att du ska få en djupare förståelse för för hur du ska + + - tillämpa olika behållare för att lagra mängder med data, + - se textsträngar som en lista med bokstäver, + - tillämpa olika former av upprepningar för att arbeta med behållarna, + - skapa enkla klasser för att skapa nya datatyper, + - dela upp problem i mindre problem, + - minimera kodupprepning, + - konstruera interaktiva program, + - leta i Pythons dokumentation. + +## Önskemål från gruppen + +Var det något särskilt från veckans föreläsning och/eller OLI-material som gruppen vill gå in djupare på? + +Är det någon som vill visa upp något särskilt från förra veckans laboration som kan ge inspiration till gruppen? + +## Övningsuppgifter + +### Finn fem fel + +Den här övningen ska ni kvalitet-checka en kurskamrats kod. + +Förra veckans övning skrev ni ett program för att skapa bankkonton. Byt kod med en annan person i gruppen. + +Läs igenom koden och få ett hum om vad den är tänkt att göra. Testa att köra koden. + +Hitta nu minst fem fel/utvecklingsområden i koden (tänk på vad ni lärt er under kursen). + +Förbättra nu koden efter det du hittat. Blev koden mer lättläst, användbar och/eller användarvänlig? Varför? + +Finns det en gräns till hur mycket man kan komprimera en kod utan att påverka kodens läsbarhet? + +### Fortune cookies + +Det finns många intressanta kommandon i den UNIX-lika terminalen. Förra +övningen nämnde vi `cowsay`. Det finns även ett kommando `fortune` som ger +lustiga korta utsagor och citat: +``` +(0|13:23)dbosk@X1:tutorial (master) +$ fortune +Q: What is printed on the bottom of beer bottles in Minnesota? +A: Open other end. +(0|13:23)dbosk@X1:tutorial (master) +$ fortune +Go not to the elves for counsel, for they will say both yes and no. + -- J.R.R. Tolkien +(0|13:24)dbosk@X1:tutorial (master) +$ fortune +You never hesitate to tackle the most difficult problems. +(0|13:24)dbosk@X1:tutorial (master) +$ +``` +Skriv ett program som skriver ut en slumpvis vald humoristisk "fortune cookie" +relaterad till era studier. Exempelvis: +``` +$ python3 fortune.py +Alla kommer att få A på matematiktentan! +$ python3 fortune.py +Det är en lovande dag för dig! +``` + + +### Ett bättre `cowsay` + +Förra övningen hade vi med en uppgift att implementera [en enkel version av +kommandot `cowsay`][cowsay.py]. Resultatet när man körde programmet såg ut +något i stil med följande: +``` + -------------------------------------------------------- +| Smaka på den här utmaningen! Fast så svår är den inte. | + -------------------------------------------------------- + \ ^__^ + \ (oo)\_______ + (__)\ )\/\ + ||----w | + || || +``` + +Om texten blir för lång funkar inte programmet då skärmbredden tar slut. Nu +vill vi kunna hantera längre texter genom att bryta dem till lagom långa rader, +exempelvis: +``` + ------------------------------- +| Smaka på den här utmaningen! | +| Fast så svår är den inte. | + ------------------------------- + \ ^__^ + \ (oo)\_______ + (__)\ )\/\ + ||----w | + || || +``` + +[cowsay.py]: https://github.com/dbosk/intropy/blob/master/modules/containers/tutorial/cowsay.py + + +### `fortune` + `cowsay` = humor + +Skriv dina fortune- och cowsay-program som moduler och kombinera dem: +``` + --------------------------- +| Alla kommer att | +| få A på matematiktentan! | + --------------------------- + \ ^__^ + \ (oo)\_______ + (__)\ )\/\ + ||----w | + || || +``` +När ni känner er nöjda finns följande lösningsförslag: + +- [fortune.py][fortune.py], +- [radbrytande cowsay_good.py][cowsay_good.py]. + +[fortune.py]: https://github.com/dbosk/intropy/blob/master/modules/containers/tutorial/fortune.py +[cowsay_good.py]: https://github.com/dbosk/intropy/blob/master/modules/containers/tutorial/cowsay_good.py diff --git a/modules/containers/tutorial/instruction.md b/modules/containers/tutorial/instruction.md index 3ca540de..aaa0be9b 100644 --- a/modules/containers/tutorial/instruction.md +++ b/modules/containers/tutorial/instruction.md @@ -1,143 +1,106 @@ --- -title: Övning om behållare +title: Övning om klasser och behållare authors: - Daniel Bosk + - Celina Soori --- -# Övning: behållare +# Övning: Fler behållare och mer klasser -Målet med övningen är att du ska blir bättre på att +Målet med övningen är att du ska bli bättre på att - - tillämpa behållare för att lagra mängder med data, + - tillämpa olika behållare för att lagra mängder med data, - se textsträngar som en lista med bokstäver, - tillämpa olika former av upprepningar för att arbeta med behållarna, + - skapa enkla klasser för att skapa nya datatyper, - dela upp problem i mindre problem, - minimera kodupprepning, - konstruera interaktiva program, - leta i Pythons dokumentation. +## Genomgång av veckans svårigheter -## Laborationen - -Hur har olika grupper löst samma labb? Oftast väldigt olika. Vi går igenom -några lösningar. Hur löser man extrauppgiften? - - -## Förfina fulkoden! - -Vi har lagt vantarna på lite fulkod. Fulkod är vi allergiska emot, så vi -behöver omedelbart fixa den till finkod. Finkod uppfyller kriterierna: - -- Informativa utskrifter -- Enkel inmatning -- Kommentarer: doc-strings, komplexa delar (`pylint` och `pydoc`!) -- Beskrivande namn -- Konsekvent språk och typografi (`pylint`!) -- Uppdelning i funktioner/metoder (och moduler?) -- Funktioner har lämpliga parametrar och returvärden -- Ingen kodupprepning - -Fulkoden som behöver fixas är följande: - -- [Ett gissningsspel, guess.py][guess.py] - ([lösningsförslag, guess-good.py][guess-good.py]) -- [En multiplikationskolumn, multcol.py][multcol.py] -- [En multiplikationstabell, multtable.py][multtable.py] - ([lösningsförslag, multtable-good.py][multtable-good.py]) - -[guess.py]: https://github.com/dbosk/intropy/blob/master/modules/containers/tutorial/guess.py -[guess-good.py]: https://github.com/dbosk/intropy/blob/master/modules/containers/tutorial/guess-good.py -[multcol.py]: https://github.com/dbosk/intropy/blob/master/modules/containers/tutorial/multcol.py -[multtable.py]: https://github.com/dbosk/intropy/blob/master/modules/containers/tutorial/multtable.py -[multtable-good.py]: https://github.com/dbosk/intropy/blob/master/modules/containers/tutorial/multtable-good.py - - -## Fortune cookies - -Det finns många intressanta kommandon i den UNIX-lika terminalen. Förra -övningen nämnde vi `cowsay`. Det finns även ett kommando `fortune` som ger -lustiga korta utsagor och citat: -``` -(0|13:23)dbosk@X1:tutorial (master) -$ fortune -Q: What is printed on the bottom of beer bottles in Minnesota? -A: Open other end. -(0|13:23)dbosk@X1:tutorial (master) -$ fortune -Go not to the elves for counsel, for they will say both yes and no. - -- J.R.R. Tolkien -(0|13:24)dbosk@X1:tutorial (master) -$ fortune -You never hesitate to tackle the most difficult problems. -(0|13:24)dbosk@X1:tutorial (master) -$ -``` -Skriv ett program som skriver ut en slumpvis vald humoristisk "fortune cookie" -relaterad till era studier. Exempelvis: -``` -$ python3 fortune.py -Alla kommer att få A på matematiktentan! -$ python3 fortune.py -Det är en lovande dag för dig! -``` - - -## Ett bättre `cowsay` - -Förra övningen hade vi med en uppgift att implementera [en enkel version av -kommandot `cowsay`][cowsay.py]. Resultatet när man körde programmet såg ut -något i stil med följande: -``` - -------------------------------------------------------- -| Smaka på den här utmaningen! Fast så svår är den inte. | - -------------------------------------------------------- - \ ^__^ - \ (oo)\_______ - (__)\ )\/\ - ||----w | - || || -``` - -Om texten blir för lång funkar inte programmet då skärmbredden tar slut. Nu -vill vi kunna hantera längre texter genom att bryta dem till lagom långa rader, -exempelvis: -``` - ------------------------------- -| Smaka på den här utmaningen! | -| Fast så svår är den inte. | - ------------------------------- - \ ^__^ - \ (oo)\_______ - (__)\ )\/\ - ||----w | - || || -``` - -[cowsay.py]: https://github.com/dbosk/intropy/blob/master/modules/containers/tutorial/cowsay.py - - -## `fortune` + `cowsay` = humor - -Skriv dina fortune- och cowsay-program som moduler och kombinera dem: -``` - --------------------------- -| Alla kommer att | -| få A på matematiktentan! | - --------------------------- - \ ^__^ - \ (oo)\_______ - (__)\ )\/\ - ||----w | - || || -``` -När ni känner er nöjda finns följande lösningsförslag: - -- [fortune.py][fortune.py], -- [radbrytande cowsay_good.py][cowsay_good.py]. - -[fortune.py]: https://github.com/dbosk/intropy/blob/master/modules/containers/tutorial/fortune.py -[cowsay_good.py]: https://github.com/dbosk/intropy/blob/master/modules/containers/tutorial/cowsay_good.py +Vi går igenom det vi upptäckt i OLI är extra svårt den här veckan. +Zoomlänk: ## Önskemål från gruppen -Vad vill gruppen gå igenom igen från veckan som var? +Var det något särskilt från veckans föreläsning och/eller OLI-material som gruppen vill gå igenom igen? + +Gick förra veckans laboration bra? Finns det något ni skulle vilja gå igenom från laborationen? + +## Övningsuppgifter + +### Finn fem fel + +[Gissningsspelet](https://github.com/dbosk/intropy/blob/master/modules/containers/tutorial/guess.py) låter användaren gissa. + +Läs igenom koden och få ett hum om vad den är tänkt att göra. Testa att köra koden. + +Hitta nu tillsammans minst fem fel/utvecklingsområden i koden (tänk på vad ni lärt er under veckan). + +Förbättra nu koden efter det ni hittat. Blev koden mer lättläst, användbar och/eller användarvänlig? Varför? + +[Lösningsförslag](https://github.com/dbosk/intropy/blob/master/modules/containers/tutorial/guess-good.py) + +### Avgöra om en e-postadress är giltig + +Skriv ett program som läser in en e-postadress från användaren och avgör om det är en giltig adress. + +Fundera på: +- Vad avgör om en e-postadress är giltig +- Vad är gemensamt med alla e-postadresser? Hur kan vi använda det för att skapa ett flexibelt program? + +### Bankkontot + +Vi ska skriva ett enkelt program som hanterar konton åt en bank. Vi behöver en +sammansatt datatyp (klass) som kan representera ett bankkonto: + + - Det ska lagra ägarens uppgifter. Ägaren är en person. (Hm, kanske vi har en + klass lämplig för att spara en persons data? Hint: se folkbokföringen + ovan.) + - Det ska lagra nuvarande saldo. + - Det ska gå att sätta in pengar. + - Det ska gå att ta ut pengar, men bara om det finns tillräckligt med pengar + på kontot. Inga negativa saldon! + +Testa att lagra objekten i en lista och i en uppslagslista. Vad fungerar bäst i det här fallet? + +Lösningsförslag: + + - [En modul med klasser för en bank, bank.py][bank.py] + - [En modul med klasser för en bank (använder arv), bank_arv.py][bank_arv.py] + - [Ett program med gränssnitt för en bank, banken.py][banken.py] + - [Ett program med gränssnitt för en bank (arv), banken_arv.py][banken_arv.py] + - [En modul för inmatning av specifika typer, input_type.py][input_type.py] + +[bank.py]: https://github.com/dbosk/intropy/blob/master/modules/classes/tutorial/bank.py +[bank_arv.py]: https://github.com/dbosk/intropy/blob/master/modules/classes/tutorial/bank_arv.py +[banken.py]: https://github.com/dbosk/intropy/blob/master/modules/classes/tutorial/banken.py +[banken_arv.py]: https://github.com/dbosk/intropy/blob/master/modules/classes/tutorial/banken_arv.py +[input_type.py]: https://github.com/dbosk/intropy/blob/master/modules/classes/tutorial/input_type.py + +### En bråkig klass + +Vi vill ha en klass för att räkna med rationella tal, eller bråk. Vi ska kunna: + + - skapa bråk, exempelvis `a = Bråk(1, 3)` och `b = Bråk(2, 6)`; + - jämföra bråk, exempelvis `a == b` eller `a < b`; + - skriva ut bråk på läsbar form, exempelvis `print(f"{a} och {b}")` ger + utskriften `1/3 och 2/6`. + - addera, subtrahera, multiplicera och dividera bråk. + - typkonvertera bråket till ett flyttal (`float`). + - förkorta bråk, exempelvis så att `b` (som är 2/6) kan förkortas till 1/3. + +Detta kräver en del specialmetoder. Se [dokumentationen för Pythons +specialmetoder för jämförelse][doc-cmp] och [dokumentationen för Pythons +specialmetoder för att emulera numeriska typer][doc-numtypemethods]. + +[doc-cmp]: https://docs.python.org/3/reference/datamodel.html#object.__lt__ +[doc-numtypemethods]: https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types + +Lösningsförslag: + + - [Lösningsförslag: en modul med en klass för bråktal, frac.py][frac.py] + +[frac.py]: https://github.com/dbosk/intropy/blob/master/modules/classes/tutorial/frac.py diff --git a/modules/files/lab/instruction.md b/modules/files/lab/instruction.md index b26b717c..2a86fa03 100644 --- a/modules/files/lab/instruction.md +++ b/modules/files/lab/instruction.md @@ -1,42 +1,123 @@ +--- +title: Laboration om Filer och felhantering +authors: + - Celina Soori + - Daniel Bosk +--- # Laboration: Filer och felhantering -Tidigare har vi låtit användaren ange ett följd av $q$-värden som har använts i -beräkningarna av en talföljd. Ibland kan det bli långa följder, exempelvis om -vi har månadsräntorna för flera år. Då kan det vara bekvämt att lagra värdena -på fil och läsa dem därifrån. +Tidigare har vi låtit användaren ange all information om studenterna. Detta +känns dock inte helt rimligt för administrativ personal på en stor skola att +göra, därför ska vi nu istället låta programmet läsa in den informationen från +en fil. +## Innan du börjar koda -## Uppgift +Läs på om [filhantering][filhantering] i Python. + +Ladda ner filen [students.txt](https://github.com/dbosk/intropy/files/9403483/students.txt) +och spara den på ett bra ställe på datorn. -För en längre följd av värden för $q$ blir det jobbigt för användaren att mata -in dessa för hand. Vanligtvis finns dessa värden att tillgå i en fil. +[filhantering]: https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files + +## Uppgift I denna laboration ska du låta användaren mata in namnet på en fil som -innehåller värdena för $q$. Därefter läser du in värdena och använder dem i -ditt program. Om filen inte finns ska användaren mata in ett nytt filnamn. +innehåller alla studenters uppgifter. Därefter läser du in uppgifterna på filen +och använder dem i ditt program som du skrev i förra laborationen. Om filen +inte finns ska användaren mata in ett nytt filnamn. + +### Exempelutskrift + +``` +Vad heter filen med alla studenter? students.cs +Den filen fanns inte! Skriv in en ny fil: students.csv + +Dessa studenter är skrivna på KTH: +Namn: Johan Tierney Personnr: 8411285597 +Namn: Erik Bolin Personnr: 9910247016 +Namn: Per Edenström Personnr: 8410024155 + +... + +Vilken student vill du söka efter? Jan + +Den studenten läser på KTH: +Namn: Jan Jansson Personnr: 0404040010 +``` + +### Krav +* Användaren ska få mata in ett nytt filnamn om filen inte hittas. +* Alla krav från laboration 5 ska vara uppfyllda. +* Din kod ska uppfylla kraven i rättningsmatrisen. + +### Redovisning + +Denna laboration ska redovisas för en lärarassistent på ett laborationstillfälle. +Information om bokning av redovisningstillfälle kommer komma upp på Canvas. +På redovisningen ska du kunna köra ditt program och beskriva din kod detaljerat. + +## Frivillig extrauppgift: Redigera + +Ge användaren möjlighet att lägga till, ändra eller ta bort objekt. +I slutet av programmet ska alla objekt läsas tillbaka till en fil som +användaren får skriva in namnet på. + +### Exempelutskrift + +``` +Vad heter filen med alla studenter? students.cs +Den filen fanns inte! Skriv in en ny fil: students.csv + +Dessa studenter är skrivna på KTH: +Johan Tierney 8411285597 +Erik Bolin 9910247016 +Per Edenström 8410024155 +... + +Vill du lägga till (l), ändra (a) eller ta bort (t) ett objekt? a + +Skriv in personnumret på objektet du vill ändra: 0101010000 +Vill du ändra namn på Emma Löv (j/n)? j +Skriv in det nya namnet: Ebba Löv + +Nu är namnet för 0101010000 ändrat till Ebba Löv! + +Ange namn på den fil som uppgifterna ska sparas på: students.csv + +Nu är alla uppgifter sparade på filen students.csv +``` + +## Frivillig extrauppgift: Fel i filen + +Lägg till felhantering när programmet läser in en fil. Om det +är något som är fel i filen ska programmet varna användaren för det +och hoppa vidare till nästa rad. + +### Exempelutskrift -Du kan låta användaren mata in $g_1$, värdet för $n$ får du genom antalet -värden för $q$ som finns i filen. Ett exempel på inmatning: ``` -Hur mycket sparkapital har du (ange i kr)? 1000 -Ange fil med förväntad ränteutveckling: räntor.txt +Vad heter filen med alla studenter? students.cs +Den filen fanns inte! Skriv in en ny fil: students.csv - Total Ökning -Månad 0: 1000.00 kr 0.00 kr -Månad 1: 1020.00 kr 20.00 kr -Månad 2: 1030.20 kr 30.20 kr +Det är fel på rad 21 i filen students.csv. Hoppar över raden. + +Dessa studenter är skrivna på KTH: +Johan Tierney 8411285597 +Erik Bolin 9910247016 +Per Edenström 8410024155 +... ``` -Givetvis ska vi hantera att användaren försöker mata in felaktiga värden. +## Frivillig extrauppgift: CSV-formaterad fil -## Extrauppgift +Ladda ner filen [students.csv](https://github.com/dbosk/intropy/files/9403241/students.csv) Använd Pythons inbyggda [`csv`-modul][csv] för att läsa in en fil på -CSV-format. Då kan filen med räntor skapas i ett kalkylarksprogram som Google -Sheets, LibreOffice Calc eller Microsoft Excel. +CSV-format. Då kan filen med studenter skapas i ett kalkylarksprogram som +Google Sheets, LibreOffice Calc eller Microsoft Excel. [csv]: https://docs.python.org/3/library/csv.html Om resultaten även skrivs till fil i CSV-format (med hjälp av `csv`-modulen), då kan även resultatet importeras tillbaka i kalkylarksprogrammet. - diff --git a/modules/files/tutorial/advanced_instruction.md b/modules/files/tutorial/advanced_instruction.md new file mode 100644 index 00000000..23c02db0 --- /dev/null +++ b/modules/files/tutorial/advanced_instruction.md @@ -0,0 +1,144 @@ +--- +title: Övning om filer +authors: + - Daniel Bosk + - Olle Bälter + - Celina Soori +--- +# Fördjupande övning: filer + +Målet med övningen är att du ska få en djupare förståelse för för hur du ska + + - överföra data mellan fil och program, d.v.s. + - läsa data från filer, + - lagra data i filer; + - tillämpa behållare för att lagra mängder med data, + - se textsträngar som en lista med bokstäver, + - tillämpa olika former av upprepningar för att arbeta med data, + - dela upp problem i mindre problem, + - minimera kodupprepning, + - konstruera interaktiva program, + - leta i Pythons dokumentation. + + +## Önskemål från gruppen + +Var det något särskilt från veckans föreläsning och/eller OLI-material som gruppen vill gå in djupare på? + +Är det någon som vill visa upp något särskilt från förra veckans laboration som kan ge inspiration till gruppen? + +## Övningsuppgifter + +### Fortune cookies + +Under förra övningen skrev vi ett program som heter `fortune.py`. Det skriver +ut en slumpvis vald humoristisk "fortune cookie" relaterad till era studier. +Exempelvis: +``` +$ python3 fortune.py +Alla kommer att få A på matematiktentan! +$ python3 fortune.py +Det är en lovande dag för dig! +``` +I den förra versionen hårdkodade vi databasen med fortunes i programmet. Nu ska +vi lagra dem på fil. Ändra programmet så att det läser alla fortunes från en +fil. + +### Extra utmaning med fortune och cowsay + +Hantera fortunes som innehåller flera rader. Anpassa även `cowsay.py` så att +den kan hantera flerradiga inmatningar utan problem. +``` + --------------------------------- +| Vi vill även ha fortunes som | +| kan vara flera rader. | +| | +| Och till och med flera stycken. | + --------------------------------- + \ ^__^ + \ (oo)\_______ + (__)\ )\/\ + ||----w | + || || +``` + +Hint: dela först upp i stycken, därefter meningar med ord. + +Filer i lösningsförslaget: + +- [Ett förbättrat fortune-program, fortune_better.py][fortune_better.py], +- [En fortunesdatabas, fortunes.txt][fortunes.txt] +- [En förbättrad cowsay-funktion, cowsay_better.py][cowsay_better.py], + +[fortune_better.py]: https://github.com/dbosk/intropy/blob/master/modules/files/tutorial/fortune_better.py +[cowsay_better.py]: https://github.com/dbosk/intropy/blob/master/modules/files/tutorial/cowsay_better.py +[fortunes.txt]: https://github.com/dbosk/intropy/blob/master/modules/files/tutorial/fortunes.txt + + +### Räkna ord och bokstäver + +Skriv ett program som frågar användaren om ett filnamn, läser in filen och +räknar förekomsten av varje ord i filen. + +Låt programmet även fråga användaren om ett filnamn och skriv sedan ut +resultatet i CSV-format till filen. +``` +Vilken fil ska vi analysera? något +Finns ingen fil som heter något, försök igen. +Vilken fil ska vi analysera? madicken.txt +Vill du analysera antalet ord eller bokstäver? +Ange ett av alternativen ['ord', 'bokstäver']: något +Tyvärr är något inte ett av alternativen. +Ange ett av alternativen ['ord', 'bokstäver']: ord +Till vilken fil ska vi skriva resultatet (CSV-format)? madicken.txt +Det finns redan en fil som heter madicken.txt, försök igen. +Till vilken fil ska vi skriva resultatet (CSV-format)? madicken.csv +``` +(Ni kan antingen använda Pythons CSV-modul, d.v.s. `import csv`, eller skriva +ut på egen hand.) Sedan kan ni prova att öppna filen i ett kalkylbladsprogram +(exempelvis LibreOffice Calc, Microsoft Excel eller Google Sheets). + +Exempelfiler att arbeta med: +- [Textfil att räkna ord och bokstäver i, madicken.txt][madicken.txt], [utdrag + ur wikipediauppslaget "Madicken (bok)"][madicken-wiki]. +- [Resultat av ordräkning, madicken.csv][madicken.csv]. + +[madicken.txt]: https://github.com/dbosk/intropy/blob/master/modules/files/tutorial/madicken.txt +[madicken-wiki]: https://sv.wikipedia.org/wiki/Madicken_(bok) +[madicken.csv]: https://github.com/dbosk/intropy/blob/master/modules/files/tutorial/madicken.csv + +Lösningsförslag: +- [Ett ord- och bokstavsräkningsprogram, wc.py][wc.py], + +[wc.py]: https://github.com/dbosk/intropy/blob/master/modules/files/tutorial/wc.py + + +### Översättare till och från rövarspråket + +Skriv ett program som frågar efter ett filnamn, frågar om översättning till +eller från rövarspråket, läser filen och översätter all text. Översättningen +ska sedan skriva över originalfilen. + +När du har en översättar från rövarspråket tillbaka till vanligt språk kan du +läsa [filen rövare.txt][rövare.txt]. + +[rövare.txt]: https://github.com/dbosk/intropy/blob/master/modules/files/tutorial/rövare.txt + +Lösningsförslag: +- [Översättare till och från rövarspråket, rövare.py][rövare.py] +- [Ett ord- och bokstavsräkningsprogram, wc.py][wc.py], + +[rövare.py]: https://github.com/dbosk/intropy/blob/master/modules/files/tutorial/rövare.py + + +### Rövarspråket eller inte? + +Skriv ett program som använder `wc`- och `rövare`-modulerna ovan för att +undersöka hur bokstavsförekomsterna förändras när en text översätts till +rövarspråket. + +Lösningsförslag: +- [Analysprogram som jämför text med översättning till rövarspråket, + analys.py][analys.py] + +[analys.py]: https://github.com/dbosk/intropy/blob/master/modules/files/tutorial/analys.py diff --git a/modules/files/tutorial/instruction.md b/modules/files/tutorial/instruction.md index c69c270c..8c071865 100644 --- a/modules/files/tutorial/instruction.md +++ b/modules/files/tutorial/instruction.md @@ -3,10 +3,11 @@ title: Övning om filer authors: - Daniel Bosk - Olle Bälter + - Celina Soori --- # Övning: filer -Målet med övningen är att du ska blir bättre på att +Målet med övningen är att du ska bli bättre på att - överföra data mellan fil och program, d.v.s. - läsa data från filer, @@ -19,60 +20,37 @@ Målet med övningen är att du ska blir bättre på att - konstruera interaktiva program, - leta i Pythons dokumentation. +## Genomgång av veckans svårigheter -## Laborationen +Vi går igenom det vi upptäckt i OLI är extra svårt den här veckan. -Hur har olika grupper löst samma labb? Oftast väldigt olika. Vi går igenom -några lösningar. Hur löser man extrauppgiften? +Zoomlänk: +## Önskemål från gruppen -## Fortune cookies +Var det något särskilt från veckans föreläsning och/eller OLI-material som gruppen vill gå igenom igen? -Under förra övningen skrev vi ett program som heter `fortune.py`. Det skriver -ut en slumpvis vald humoristisk "fortune cookie" relaterad till era studier. -Exempelvis: -``` -$ python3 fortune.py -Alla kommer att få A på matematiktentan! -$ python3 fortune.py -Det är en lovande dag för dig! -``` -I den förra versionen hårdkodade vi databasen med fortunes i programmet. Nu ska -vi lagra dem på fil. Ändra programmet så att det läser alla fortunes från en -fil. +Gick förra veckans laboration bra? Finns det något ni skulle vilja gå igenom från laborationen? -### Extra utmaning med fortune och cowsay +## Övningsuppgifter -Hantera fortunes som innehåller flera rader. Anpassa även `cowsay.py` så att -den kan hantera flerradiga inmatningar utan problem. -``` - --------------------------------- -| Vi vill även ha fortunes som | -| kan vara flera rader. | -| | -| Och till och med flera stycken. | - --------------------------------- - \ ^__^ - \ (oo)\_______ - (__)\ )\/\ - ||----w | - || || -``` +### Finn fem fel + +Den här övningen ska ni kvalitet-checka en kurskamrats kod. -Hint: dela först upp i stycken, därefter meningar med ord. +Förra veckans övning skrev ni ett program för att skapa bankkonton. Byt kod med en annan person i gruppen. +Om du inte var med eller inte hann skriva programmet på förra övningen, byt istället med en annan kod +du skrivit under en övning! -Filer i lösningsförslaget: +Läs igenom koden och få ett hum om vad den är tänkt att göra. Testa att köra koden. -- [Ett förbättrat fortune-program, fortune_better.py][fortune_better.py], -- [En fortunesdatabas, fortunes.txt][fortunes.txt] -- [En förbättrad cowsay-funktion, cowsay_better.py][cowsay_better.py], +Hitta nu minst fem fel/utvecklingsområden i koden (tänk på vad ni lärt er under kursen). -[fortune_better.py]: https://github.com/dbosk/intropy/blob/master/modules/files/tutorial/fortune_better.py -[cowsay_better.py]: https://github.com/dbosk/intropy/blob/master/modules/files/tutorial/cowsay_better.py -[fortunes.txt]: https://github.com/dbosk/intropy/blob/master/modules/files/tutorial/fortunes.txt +Förbättra nu koden efter det du hittat. Blev koden mer lättläst, användbar och/eller användarvänlig? Varför? +Finns det en gräns till hur mycket man kan komprimera en kod utan att påverka kodens läsbarhet? -## Räkna ord och bokstäver +### Räkna ord och bokstäver Skriv ett program som frågar användaren om ett filnamn, läser in filen och räknar förekomsten av varje ord i filen. @@ -110,7 +88,7 @@ Lösningsförslag: [wc.py]: https://github.com/dbosk/intropy/blob/master/modules/files/tutorial/wc.py -## Översättare till och från rövarspråket +### Översättare till och från rövarspråket Skriv ett program som frågar efter ett filnamn, frågar om översättning till eller från rövarspråket, läser filen och översätter all text. Översättningen @@ -126,21 +104,3 @@ Lösningsförslag: - [Ett ord- och bokstavsräkningsprogram, wc.py][wc.py], [rövare.py]: https://github.com/dbosk/intropy/blob/master/modules/files/tutorial/rövare.py - - -## Rövarspråket eller inte? - -Skriv ett program som använder `wc`- och `rövare`-modulerna ovan för att -undersöka hur bokstavsförekomsterna förändras när en text översätts till -rövarspråket. - -Lösningsförslag: -- [Analysprogram som jämför text med översättning till rövarspråket, - analys.py][analys.py] - -[analys.py]: https://github.com/dbosk/intropy/blob/master/modules/files/tutorial/analys.py - - -## Önskemål från gruppen - -Vad vill gruppen gå igenom igen från veckan som var? diff --git a/modules/functions/lab/instruction.md b/modules/functions/lab/instruction.md deleted file mode 100644 index 0c8f53aa..00000000 --- a/modules/functions/lab/instruction.md +++ /dev/null @@ -1,26 +0,0 @@ -# Laboration: Funktioner och moduler - -Vi har skrivit flera funktioner hittills: flera för talföljder och åtminstone -en för inmatning. Hittills har vi inte haft något krav på att funktionerna ska -ligga i egna moduler. - - -## Uppgift - -Lägg funktionerna i moduler (exempelvis en modul för talföljder och en modul -för inmatning) som du kan återanvända i andra program genom `import`. Skriv -sedan om programmet i föregående laboration så att det använder funktionerna -genom modulerna. - -Använd även [`pylint`][pylint] för att säkerställa kodens kvalitet. - -[pylint]: https://pylint.pycqa.org/en/latest/ - - -## Extrauppgift - -Läs om [paketering][packaging] i Python och gör dina moduler installerbara -genom `pip`. Då kan andra enkelt installera dina moduler på sina system. - -[packaging]: https://packaging.python.org/tutorials/packaging-projects/ - diff --git a/modules/functions/slides-more/.gitignore b/modules/functions/slides-builtins/.gitignore similarity index 100% rename from modules/functions/slides-more/.gitignore rename to modules/functions/slides-builtins/.gitignore diff --git a/modules/functions/slides/Makefile b/modules/functions/slides-builtins/Makefile similarity index 96% rename from modules/functions/slides/Makefile rename to modules/functions/slides-builtins/Makefile index 4c9d0e24..e631f618 100644 --- a/modules/functions/slides/Makefile +++ b/modules/functions/slides-builtins/Makefile @@ -1,6 +1,8 @@ .PHONY: all all: notes.pdf slides.pdf +LATEXFLAGS+= -shell-escape + SRC+= preamble.tex SRC+= abstract.tex contents.tex diff --git a/modules/variables/slides-more/abstract.tex b/modules/functions/slides-builtins/abstract.tex similarity index 100% rename from modules/variables/slides-more/abstract.tex rename to modules/functions/slides-builtins/abstract.tex diff --git a/modules/functions/slides-builtins/contents.tex b/modules/functions/slides-builtins/contents.tex new file mode 100644 index 00000000..df78dcea --- /dev/null +++ b/modules/functions/slides-builtins/contents.tex @@ -0,0 +1,68 @@ +\mode* + +\section{Inbyggda funktioner} + +\begin{frame} + \includegraphics[width=\columnwidth]{figs/docs-built-in.png} +\end{frame} + +\subsection{map() och filter()} + +\begin{frame}[fragile] + \begin{example}[mapping.py, del 1] + \inputminted[firstline=3,lastline=15]{python}{examples/mapping.py} + \end{example} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[mapping.py, del 2] + \inputminted[firstline=16]{python}{examples/mapping.py} + \end{example} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[filtering.py, del 1] + \inputminted[firstline=3,lastline=15]{python}{examples/filtering.py} + \end{example} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[filtering.py, del 2] + \inputminted[firstline=21]{python}{examples/filtering.py} + \end{example} +\end{frame} + +\subsection{Namnlösa (lambda-)funktioner} + +\begin{frame}[fragile] + \begin{example}[filter-lambda.py] + \inputminted{python}{examples/filter-lambda.py} + \end{example} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[any-all.py, del 1] + \inputminted[firstline=7,lastline=18]{python}{examples/any-all.py} + \end{example} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[any-all.py, del 2] + \inputminted[firstline=20]{python}{examples/any-all.py} + \end{example} +\end{frame} + +\subsection{zip() och enumerate()} + +\begin{frame}[fragile] + \begin{example}[enum.py] + \inputminted{python}{examples/enum.py} + \end{example} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[zip.py] + \inputminted{python}{examples/zip.py} + \end{example} +\end{frame} + diff --git a/modules/functions/slides/examples/any-all.py b/modules/functions/slides-builtins/examples/any-all.py similarity index 100% rename from modules/functions/slides/examples/any-all.py rename to modules/functions/slides-builtins/examples/any-all.py diff --git a/modules/functions/slides/examples/enum.py b/modules/functions/slides-builtins/examples/enum.py similarity index 100% rename from modules/functions/slides/examples/enum.py rename to modules/functions/slides-builtins/examples/enum.py diff --git a/modules/functions/slides/examples/filter-lambda.py b/modules/functions/slides-builtins/examples/filter-lambda.py similarity index 100% rename from modules/functions/slides/examples/filter-lambda.py rename to modules/functions/slides-builtins/examples/filter-lambda.py diff --git a/modules/functions/slides/examples/filter-lists.py b/modules/functions/slides-builtins/examples/filter-lists.py similarity index 100% rename from modules/functions/slides/examples/filter-lists.py rename to modules/functions/slides-builtins/examples/filter-lists.py diff --git a/modules/functions/slides/examples/filter-strings.py b/modules/functions/slides-builtins/examples/filter-strings.py similarity index 100% rename from modules/functions/slides/examples/filter-strings.py rename to modules/functions/slides-builtins/examples/filter-strings.py diff --git a/modules/functions/slides/examples/filter-strints.py b/modules/functions/slides-builtins/examples/filter-strints.py similarity index 100% rename from modules/functions/slides/examples/filter-strints.py rename to modules/functions/slides-builtins/examples/filter-strints.py diff --git a/modules/functions/slides/examples/filtering.py b/modules/functions/slides-builtins/examples/filtering.py similarity index 100% rename from modules/functions/slides/examples/filtering.py rename to modules/functions/slides-builtins/examples/filtering.py diff --git a/modules/functions/slides/examples/func.py b/modules/functions/slides-builtins/examples/func.py similarity index 100% rename from modules/functions/slides/examples/func.py rename to modules/functions/slides-builtins/examples/func.py diff --git a/modules/functions/slides/examples/input-int-default.py b/modules/functions/slides-builtins/examples/input-int-default.py similarity index 100% rename from modules/functions/slides/examples/input-int-default.py rename to modules/functions/slides-builtins/examples/input-int-default.py diff --git a/modules/functions/slides/examples/input-int.py b/modules/functions/slides-builtins/examples/input-int.py similarity index 100% rename from modules/functions/slides/examples/input-int.py rename to modules/functions/slides-builtins/examples/input-int.py diff --git a/modules/functions/slides/examples/input-type.py b/modules/functions/slides-builtins/examples/input-type.py similarity index 100% rename from modules/functions/slides/examples/input-type.py rename to modules/functions/slides-builtins/examples/input-type.py diff --git a/modules/functions/slides/examples/mapping-own.py b/modules/functions/slides-builtins/examples/mapping-own.py similarity index 100% rename from modules/functions/slides/examples/mapping-own.py rename to modules/functions/slides-builtins/examples/mapping-own.py diff --git a/modules/functions/slides/examples/mapping.py b/modules/functions/slides-builtins/examples/mapping.py similarity index 100% rename from modules/functions/slides/examples/mapping.py rename to modules/functions/slides-builtins/examples/mapping.py diff --git a/modules/functions/slides/examples/summera.py b/modules/functions/slides-builtins/examples/summera.py similarity index 100% rename from modules/functions/slides/examples/summera.py rename to modules/functions/slides-builtins/examples/summera.py diff --git a/modules/functions/slides/examples/zip.py b/modules/functions/slides-builtins/examples/zip.py similarity index 100% rename from modules/functions/slides/examples/zip.py rename to modules/functions/slides-builtins/examples/zip.py diff --git a/modules/functions/slides/figs/docs-built-in.png b/modules/functions/slides-builtins/figs/docs-built-in.png similarity index 100% rename from modules/functions/slides/figs/docs-built-in.png rename to modules/functions/slides-builtins/figs/docs-built-in.png diff --git a/modules/functions/slides-builtins/notes.tex b/modules/functions/slides-builtins/notes.tex new file mode 100644 index 00000000..6b5b2d2d --- /dev/null +++ b/modules/functions/slides-builtins/notes.tex @@ -0,0 +1,45 @@ +\documentclass{article} + +\usepackage[hyphens]{url} +\usepackage[hidelinks]{hyperref} + +\input{preamble.tex} + +\usepackage[noamsthm,notheorems]{beamerarticle} +\setjobnamebeamerversion{slides} + +%\usepackage{authblk} +%\let\institute\affil + +\declaretheorem[numbered=unless unique,style=theorem]{theorem} +\declaretheorem[numbered=unless unique,style=definition]{definition} +\declaretheorem[numbered=unless unique,style=definition]{assumption} +\declaretheorem[numbered=unless unique,style=definition]{protocol} +\declaretheorem[numbered=unless unique,style=example]{example} +%\declaretheorem[style=definition,numbered=unless unique, +% name=Example,refname={example,examples}]{example} +\declaretheorem[numbered=unless unique,style=remark]{remark} +\declaretheorem[numbered=unless unique,style=remark]{idea} +\declaretheorem[numbered=unless unique,style=exercise]{exercise} +\declaretheorem[numbered=unless unique,style=exercise]{question} +\declaretheorem[numbered=unless unique,style=solution]{solution} + +\begin{document} +\title{% + Inbyggda funktioner +} +\author{Daniel Bosk} +\institute{% + KTH EECS +} + +\maketitle + +\begin{abstract} + \input{abstract.tex} +\end{abstract} + +\input{contents.tex} + +\printbibliography +\end{document} diff --git a/modules/functions/slides-builtins/preamble.tex b/modules/functions/slides-builtins/preamble.tex new file mode 100644 index 00000000..adb0af91 --- /dev/null +++ b/modules/functions/slides-builtins/preamble.tex @@ -0,0 +1,39 @@ +\usepackage[utf8]{inputenc} +\usepackage[T1]{fontenc} +\usepackage[british]{babel} +\usepackage{booktabs} + +\usepackage[natbib,style=alphabetic,maxbibnames=99]{biblatex} +\addbibresource{slides.bib} + +\usepackage[all]{foreign} +\renewcommand{\foreignfullfont}{} +\renewcommand{\foreignabbrfont}{} + +\usepackage{newclude} +\usepackage{import} + +\usepackage[strict]{csquotes} +\usepackage[single]{acro} + +\usepackage{subcaption} + +\usepackage[noend]{algpseudocode} +\usepackage{xparse} + +\let\email\texttt + +\usepackage[outputdir=ltxobj]{minted} +\setminted{autogobble,fontsize=\footnotesize} + +\usepackage{amsmath} +\usepackage{amssymb} +\usepackage{mathtools} +\usepackage{amsthm} +\usepackage{thmtools} +\usepackage[unq]{unique} +\DeclareMathOperator{\powerset}{\mathcal{P}} + +\usepackage[binary-units]{siunitx} + +\usepackage[capitalize]{cleveref} diff --git a/modules/functions/slides-more/slides.tex b/modules/functions/slides-builtins/slides.tex similarity index 98% rename from modules/functions/slides-more/slides.tex rename to modules/functions/slides-builtins/slides.tex index 97901656..90af167e 100644 --- a/modules/functions/slides-more/slides.tex +++ b/modules/functions/slides-builtins/slides.tex @@ -97,7 +97,7 @@ \begin{document} \title{% - Moduler, rekursion och generatorer + Inbyggda funktioner } \author{Daniel Bosk} \institute{% diff --git a/modules/functions/slides/.gitignore b/modules/functions/slides-generators/.gitignore similarity index 100% rename from modules/functions/slides/.gitignore rename to modules/functions/slides-generators/.gitignore diff --git a/modules/functions/slides-more/Makefile b/modules/functions/slides-generators/Makefile similarity index 100% rename from modules/functions/slides-more/Makefile rename to modules/functions/slides-generators/Makefile diff --git a/modules/functions/slides-generators/abstract.tex b/modules/functions/slides-generators/abstract.tex new file mode 100644 index 00000000..4012d9d3 --- /dev/null +++ b/modules/functions/slides-generators/abstract.tex @@ -0,0 +1,22 @@ +% What's the problem? +% Why is it a problem? Research gap left by other approaches? +% Why is it important? Why care? +% What's the approach? How to solve the problem? +% What's the findings? How was it evaluated, what are the results, limitations, +% what remains to be done? + +% XXX Summary +\emph{Summary:} +\dots + +% XXX Motivation and intended learning outcomes +\emph{Intended learning outcomes:} +\dots + +% XXX Prerequisites +\emph{Prerequisites:} +\dots + +% XXX Reading material +\emph{Reading:} +\dots diff --git a/modules/functions/slides-generators/contents.tex b/modules/functions/slides-generators/contents.tex new file mode 100644 index 00000000..943c9763 --- /dev/null +++ b/modules/functions/slides-generators/contents.tex @@ -0,0 +1,54 @@ +\mode* + +\section{Generatorer} + +\begin{frame}[fragile] + \begin{lstlisting}[basicstyle=\huge,numbers=none] +def gen(): + i = 0 + while True: + yield i + i += 1 + \end{lstlisting} +\end{frame} + +\subsection{Filtrering och mappning igen} + +\begin{frame}[fragile] + \begin{example}[filter-own.py] + \lstinputlisting[linerange=7-12,firstnumber=7]{examples/filter_own.py} + \end{example} + + \pause + + \begin{example}[filter-gen.py] + \lstinputlisting[linerange=7-11,firstnumber=7]{examples/filter_gen.py} + \end{example} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[mapping-own.py] + \lstinputlisting[linerange=16-20,firstnumber=16]{examples/mapping_own.py} + \end{example} + + \pause + + \begin{example}[mapping-gen.py] + \lstinputlisting[linerange=16-20,firstnumber=16]{examples/mapping_gen.py} + \end{example} +\end{frame} + +\subsection{Vad är egentligen skillnaden?} + +\begin{frame}[fragile] + \begin{example}[gen\textunderscore adv.py, del 1] + \lstinputlisting[linerange=3-13,firstnumber=3]{examples/gen_adv.py} + \end{example} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[gen\textunderscore adv.py, del 2] + \lstinputlisting[firstline=15,firstnumber=15]{examples/gen_adv.py} + \end{example} +\end{frame} + diff --git a/modules/functions/slides-more/examples/filter_gen.py b/modules/functions/slides-generators/examples/filter_gen.py similarity index 100% rename from modules/functions/slides-more/examples/filter_gen.py rename to modules/functions/slides-generators/examples/filter_gen.py diff --git a/modules/functions/slides-more/examples/filter_own.py b/modules/functions/slides-generators/examples/filter_own.py similarity index 100% rename from modules/functions/slides-more/examples/filter_own.py rename to modules/functions/slides-generators/examples/filter_own.py diff --git a/modules/functions/slides-more/examples/gen_adv.py b/modules/functions/slides-generators/examples/gen_adv.py similarity index 100% rename from modules/functions/slides-more/examples/gen_adv.py rename to modules/functions/slides-generators/examples/gen_adv.py diff --git a/modules/functions/slides-more/examples/input_type.py b/modules/functions/slides-generators/examples/input_type.py similarity index 100% rename from modules/functions/slides-more/examples/input_type.py rename to modules/functions/slides-generators/examples/input_type.py diff --git a/modules/functions/slides-more/examples/mapping_gen.py b/modules/functions/slides-generators/examples/mapping_gen.py similarity index 100% rename from modules/functions/slides-more/examples/mapping_gen.py rename to modules/functions/slides-generators/examples/mapping_gen.py diff --git a/modules/functions/slides-more/examples/mapping_own.py b/modules/functions/slides-generators/examples/mapping_own.py similarity index 100% rename from modules/functions/slides-more/examples/mapping_own.py rename to modules/functions/slides-generators/examples/mapping_own.py diff --git a/modules/functions/slides-more/examples/search.py b/modules/functions/slides-generators/examples/search.py similarity index 100% rename from modules/functions/slides-more/examples/search.py rename to modules/functions/slides-generators/examples/search.py diff --git a/modules/functions/slides-generators/notes.tex b/modules/functions/slides-generators/notes.tex new file mode 100644 index 00000000..6850b2fc --- /dev/null +++ b/modules/functions/slides-generators/notes.tex @@ -0,0 +1,45 @@ +\documentclass{article} + +\usepackage[hyphens]{url} +\usepackage[hidelinks]{hyperref} + +\input{preamble.tex} + +\usepackage[noamsthm,notheorems]{beamerarticle} +\setjobnamebeamerversion{slides} + +%\usepackage{authblk} +%\let\institute\affil + +\declaretheorem[numbered=unless unique,style=theorem]{theorem} +\declaretheorem[numbered=unless unique,style=definition]{definition} +\declaretheorem[numbered=unless unique,style=definition]{assumption} +\declaretheorem[numbered=unless unique,style=definition]{protocol} +\declaretheorem[numbered=unless unique,style=example]{example} +%\declaretheorem[style=definition,numbered=unless unique, +% name=Example,refname={example,examples}]{example} +\declaretheorem[numbered=unless unique,style=remark]{remark} +\declaretheorem[numbered=unless unique,style=remark]{idea} +\declaretheorem[numbered=unless unique,style=exercise]{exercise} +\declaretheorem[numbered=unless unique,style=exercise]{question} +\declaretheorem[numbered=unless unique,style=solution]{solution} + +\begin{document} +\title{% + Generatorer +} +\author{Daniel Bosk} +\institute{% + KTH EECS +} + +\maketitle + +\begin{abstract} + \input{abstract.tex} +\end{abstract} + +\input{contents.tex} + +\printbibliography +\end{document} diff --git a/modules/functions/slides/preamble.tex b/modules/functions/slides-generators/preamble.tex similarity index 100% rename from modules/functions/slides/preamble.tex rename to modules/functions/slides-generators/preamble.tex index 9e96be71..7fa313f0 100644 --- a/modules/functions/slides/preamble.tex +++ b/modules/functions/slides-generators/preamble.tex @@ -3,6 +3,9 @@ \usepackage[british]{babel} \usepackage{booktabs} +\usepackage[natbib,style=alphabetic,maxbibnames=99]{biblatex} +\addbibresource{slides.bib} + \usepackage[all]{foreign} \renewcommand{\foreignfullfont}{} \renewcommand{\foreignabbrfont}{} @@ -13,9 +16,6 @@ \usepackage[strict]{csquotes} \usepackage[single]{acro} -\usepackage[natbib,style=alphabetic,maxbibnames=99]{biblatex} -\addbibresource{slides.bib} - \usepackage{subcaption} \usepackage[noend]{algpseudocode} diff --git a/modules/functions/slides-generators/slides.tex b/modules/functions/slides-generators/slides.tex new file mode 100644 index 00000000..0dc00ee3 --- /dev/null +++ b/modules/functions/slides-generators/slides.tex @@ -0,0 +1,118 @@ +\documentclass[ignoreframetext]{beamer} +\input{preamble.tex} + +\usetheme{Berlin} +\setbeamertemplate{footline}%{miniframes theme} +{% + \begin{beamercolorbox}[colsep=1.5pt]{upper separation line foot} + \end{beamercolorbox} + \begin{beamercolorbox}[ht=2.5ex,dp=1.125ex,% + leftskip=.3cm,rightskip=.3cm plus1fil]{author in head/foot}% + \leavevmode{\usebeamerfont{author in head/foot}\insertshortauthor}% + \hfill% + {\usebeamerfont{institute in head/foot}\usebeamercolor[fg]{institute in head/foot}\insertshortinstitute}% + \end{beamercolorbox}% + \begin{beamercolorbox}[ht=2.5ex,dp=1.125ex,% + leftskip=.3cm,rightskip=.3cm plus1fil]{title in head/foot}% + {\usebeamerfont{title in head/foot}\insertshorttitle} \hfill \insertframenumber% + \end{beamercolorbox}% + \begin{beamercolorbox}[colsep=1.5pt]{lower separation line foot} + \end{beamercolorbox} +} +\setbeamercovered{transparent} +\setbeamertemplate{bibliography item}[text] + +\AtBeginSection[]{% + \begin{frame} + \tableofcontents[currentsection] + \end{frame} +} + +\ProvideDocumentEnvironment{assumption}{o}{% + \IfValueTF{#1}{% + \begin{block}{Assumption: #1} + }{% + \begin{block}{Assumption} + } +}{% + \end{block} +} + +\ProvideDocumentEnvironment{protocol}{o}{% + \IfValueTF{#1}{% + \begin{block}{Protocol: #1} + }{% + \begin{block}{Protocol} + } +}{% + \end{block} +} + +\ProvideDocumentEnvironment{remark}{o}{% + \IfValueTF{#1}{% + \begin{alertblock}{Note: #1} + }{% + \begin{alertblock}{Note} + } +}{% + \end{alertblock} +} + +\ProvideDocumentEnvironment{idea}{o}{% + \IfValueTF{#1}{% + \begin{block}{Idea: #1} + }{% + \begin{block}{Idea} + } +}{% + \end{block} +} + +\ProvideDocumentEnvironment{question}{o}{% + \setbeamercolor{block body}{bg=orange!15,fg=black} + \setbeamercolor{block title}{bg=orange,fg=white} + \setbeamercolor{local structure}{fg=orange} + \IfValueTF{#1}{% + \begin{block}{Question: #1} + }{% + \begin{block}{Question} + } +}{% + \end{block} +} + +\ProvideDocumentEnvironment{exercise}{o}{% + \setbeamercolor{block body}{bg=yellow!10,fg=black} + \setbeamercolor{block title}{bg=yellow,fg=black} + \setbeamercolor{local structure}{fg=yellow} + \IfValueTF{#1}{% + \begin{block}{Exercise: #1} + }{% + \begin{block}{Exercise} + } +}{% + \end{block} +} + + +\begin{document} +\title{% + Generatorer +} +\author{Daniel Bosk} +\institute{% + KTH EECS +} + +\begin{frame} + \maketitle +\end{frame} + +\mode +\input{contents.tex} +\mode* + +\begin{frame}[allowframebreaks] + \printbibliography +\end{frame} +\end{document} diff --git a/modules/functions/slides-more/contents.tex b/modules/functions/slides-more/contents.tex deleted file mode 100644 index 21a8f0f8..00000000 --- a/modules/functions/slides-more/contents.tex +++ /dev/null @@ -1,186 +0,0 @@ -\mode* - -\section{Moduler} - -\begin{frame}[fragile] - \begin{lstlisting}[numbers=none,basicstyle=\huge] -import module - \end{lstlisting} -\end{frame} - -\subsection{Hur?} - -\begin{frame}[fragile] - \begin{example}[bad-module.py] - \lstinputlisting{examples/bad_module.py} - \end{example} -\end{frame} - -\begin{frame}[fragile] - \begin{example}[test-good-bad.py] - \lstinputlisting{examples/test_good_bad.py} - \end{example} -\end{frame} - -\begin{frame}[fragile] - \begin{example}[good-module.py] - \lstinputlisting{examples/good_module.py} - \end{example} -\end{frame} - -\subsection{Ett gammalt exempel} - -\begin{frame}[fragile] - \begin{example}[input-type.py, del 1] - \lstinputlisting[linerange=1-13]{examples/input_type.py} - \end{example} -\end{frame} - -\begin{frame}[fragile] - \begin{example}[input-type.py, del 2] - \lstinputlisting[firstline=14,firstnumber=14]{examples/input_type.py} - \end{example} -\end{frame} - -\begin{frame}[fragile] - \begin{example}[Använda modulen] - \begin{lstlisting} -import input_type - -x = input_type(int, "x = ") -print(f"x = {x}") - \end{lstlisting} - \end{example} -\end{frame} - - -\section{Linting} - -\begin{frame}[fragile] - \begin{lstlisting}[numbers=none,basicstyle=\huge] -$ pylint prog.py - \end{lstlisting} -\end{frame} - -\section{Rekursion} - -\begin{frame}[fragile] - \begin{lstlisting}[basicstyle=\huge,numbers=none] -def f(x): - if p(x): - return c - else: - return f(g(x)) - \end{lstlisting} -\end{frame} - -\subsection{Fakultet} - -\begin{frame}[fragile] - \begin{example}[factorial.py, del 1] - \lstinputlisting[linerange=1-12]{examples/factorial.py} - \end{example} -\end{frame} - -\begin{frame}[fragile] - \begin{example}[factorial.py, del 2] - \lstinputlisting[firstline=12,firstnumber=12]{examples/factorial.py} - \end{example} -\end{frame} - -\subsection{Sökning} - -\begin{frame}[fragile] - \begin{example}[search.py, del 1] - \lstinputlisting[linerange=5-20,firstnumber=5]{examples/search.py} - \end{example} -\end{frame} - -\begin{frame}[fragile] - \begin{example}[search.py, del 2] - \lstinputlisting[linerange=3-3,firstnumber=3]{examples/search.py} - \dots - \lstinputlisting[firstline=21,firstnumber=21]{examples/search.py} - \end{example} -\end{frame} - - -\section{Generatorer} - -\begin{frame}[fragile] - \begin{lstlisting}[basicstyle=\huge,numbers=none] -def gen(): - i = 0 - while True: - yield i - i += 1 - \end{lstlisting} -\end{frame} - -\subsection{Filtrering och mappning igen} - -\begin{frame}[fragile] - \begin{example}[filter-own.py] - \lstinputlisting[linerange=7-12,firstnumber=7]{examples/filter_own.py} - \end{example} - - \pause - - \begin{example}[filter-gen.py] - \lstinputlisting[linerange=7-11,firstnumber=7]{examples/filter_gen.py} - \end{example} -\end{frame} - -\begin{frame}[fragile] - \begin{example}[mapping-own.py] - \lstinputlisting[linerange=16-20,firstnumber=16]{examples/mapping_own.py} - \end{example} - - \pause - - \begin{example}[mapping-gen.py] - \lstinputlisting[linerange=16-20,firstnumber=16]{examples/mapping_gen.py} - \end{example} -\end{frame} - -\subsection{Vad är egentligen skillnaden?} - -\begin{frame}[fragile] - \begin{example}[gen\textunderscore adv.py, del 1] - \lstinputlisting[linerange=3-13,firstnumber=3]{examples/gen_adv.py} - \end{example} -\end{frame} - -\begin{frame}[fragile] - \begin{example}[gen\textunderscore adv.py, del 2] - \lstinputlisting[firstline=15,firstnumber=15]{examples/gen_adv.py} - \end{example} -\end{frame} - - -\section{PyPI} - -\begin{frame} - \includegraphics[width=\columnwidth]{figs/pypi.png} -\end{frame} - -\begin{frame} - \includegraphics[width=\columnwidth]{figs/pypi-scipy.png} -\end{frame} - -\begin{frame} - \includegraphics[width=\columnwidth]{figs/pypi-matplotlib.png} -\end{frame} - -\begin{frame}[fragile] - \begin{example}[Installation] - \begin{lstlisting}[language={},numbers=none] -$ pip install numpy scipy matplotlib - \end{lstlisting} - \end{example} -\end{frame} - -\begin{frame} - \includegraphics[width=\columnwidth]{figs/pypi-torch.png} -\end{frame} - diff --git a/modules/functions/slides-recursion/.gitignore b/modules/functions/slides-recursion/.gitignore new file mode 100644 index 00000000..aaae5fd9 --- /dev/null +++ b/modules/functions/slides-recursion/.gitignore @@ -0,0 +1,3 @@ +notes.pdf +slides.pdf + diff --git a/modules/functions/slides-recursion/Makefile b/modules/functions/slides-recursion/Makefile new file mode 100644 index 00000000..bfd70696 --- /dev/null +++ b/modules/functions/slides-recursion/Makefile @@ -0,0 +1,25 @@ +.PHONY: all +all: notes.pdf slides.pdf + +SRC+= preamble.tex +SRC+= abstract.tex contents.tex + +SRC+= examples/bad_module.py +SRc+= examples/good_module.py +SRC+= examples/test_good_bad.py +SRC+= examples/input_type.py + +notes.pdf: notes.tex +notes.pdf: ${SRC} + +slides.pdf: slides.tex +slides.pdf: ${SRC} + + +.PHONY: clean +clean: + ${RM} notes.pdf slides.pdf + + +INCLUDE_MAKEFILES=../../../makefiles +include ${INCLUDE_MAKEFILES}/tex.mk diff --git a/modules/functions/slides-recursion/abstract.tex b/modules/functions/slides-recursion/abstract.tex new file mode 100644 index 00000000..4012d9d3 --- /dev/null +++ b/modules/functions/slides-recursion/abstract.tex @@ -0,0 +1,22 @@ +% What's the problem? +% Why is it a problem? Research gap left by other approaches? +% Why is it important? Why care? +% What's the approach? How to solve the problem? +% What's the findings? How was it evaluated, what are the results, limitations, +% what remains to be done? + +% XXX Summary +\emph{Summary:} +\dots + +% XXX Motivation and intended learning outcomes +\emph{Intended learning outcomes:} +\dots + +% XXX Prerequisites +\emph{Prerequisites:} +\dots + +% XXX Reading material +\emph{Reading:} +\dots diff --git a/modules/functions/slides-recursion/contents.tex b/modules/functions/slides-recursion/contents.tex new file mode 100644 index 00000000..027a8824 --- /dev/null +++ b/modules/functions/slides-recursion/contents.tex @@ -0,0 +1,46 @@ +\mode* + +\section{Rekursion} + +\begin{frame}[fragile] + \begin{lstlisting}[basicstyle=\huge,numbers=none] +def f(x): + if p(x): + return c + else: + return f(g(x)) + \end{lstlisting} +\end{frame} + +\subsection{Fakultet} + +\begin{frame}[fragile] + \begin{example}[factorial.py, del 1] + \lstinputlisting[linerange=1-12]{examples/factorial.py} + \end{example} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[factorial.py, del 2] + \lstinputlisting[firstline=12,firstnumber=12]{examples/factorial.py} + \end{example} +\end{frame} + +\subsection{Sökning} + +\begin{frame}[fragile] + \begin{example}[search.py, del 1] + \lstinputlisting[linerange=5-20,firstnumber=5]{examples/search.py} + \end{example} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[search.py, del 2] + \lstinputlisting[linerange=3-3,firstnumber=3]{examples/search.py} + \dots + \lstinputlisting[firstline=21,firstnumber=21]{examples/search.py} + \end{example} +\end{frame} + + + diff --git a/modules/functions/slides-more/examples/bad_module.py b/modules/functions/slides-recursion/examples/bad_module.py similarity index 100% rename from modules/functions/slides-more/examples/bad_module.py rename to modules/functions/slides-recursion/examples/bad_module.py diff --git a/modules/functions/slides-more/examples/factorial.py b/modules/functions/slides-recursion/examples/factorial.py similarity index 100% rename from modules/functions/slides-more/examples/factorial.py rename to modules/functions/slides-recursion/examples/factorial.py diff --git a/modules/functions/slides-more/examples/good_module.py b/modules/functions/slides-recursion/examples/good_module.py similarity index 100% rename from modules/functions/slides-more/examples/good_module.py rename to modules/functions/slides-recursion/examples/good_module.py diff --git a/modules/functions/slides-recursion/examples/input_type.py b/modules/functions/slides-recursion/examples/input_type.py new file mode 100644 index 00000000..52a136be --- /dev/null +++ b/modules/functions/slides-recursion/examples/input_type.py @@ -0,0 +1,26 @@ +"""Take input more easily.""" + +def input_type(t, prompt=""): + """Take input, convert to type t; repeat if error.""" + while True: + try: + return t(input(prompt)) + except ValueError: + if t == int: + print(f"Sorry, can't convert to integer.") + else: + print(f"Sorry, can't convert to {t}.") + +def main(): + """Test functionality of this module""" + x = input_type(int, "x = ") + y = input_type(int, "y = ") + z = input_type(float, "z = ") + name = input_type(str, "Your name: ") + + print(f"{x} + {y} = {x+y}") + print(f"z = {z}") + print(f"Your name is {name}") + +if __name__ == "__main__": + main() diff --git a/modules/functions/slides-recursion/examples/search.py b/modules/functions/slides-recursion/examples/search.py new file mode 100644 index 00000000..d605b79a --- /dev/null +++ b/modules/functions/slides-recursion/examples/search.py @@ -0,0 +1,32 @@ +""" Search through a list """ + +import input_type + +def in_list(item, lst): + """ Check if item is in lst """ + if len(lst) < 1: + return False + elif len(lst) == 1: + return lst[0] == item + + middle = len(lst)//2 + if item == lst[middle]: + return True + elif item < lst[middle]: + half_lst = lst[:middle] # lst[0:middle] + else: + half_lst = lst[middle+1:] + return in_list(item, half_lst) + + +def main(): + """Test functionality""" + l = sorted([1, 2, 4, 5, 8, 10, 18, 20, 21, 22, 30]) + x = input_type.input_type(int, "What to search for? ") + if in_list(x, l): + print("Yes!") + else: + print("No!") + +if __name__ == "__main__": + main() diff --git a/modules/functions/slides-more/examples/test_good_bad.py b/modules/functions/slides-recursion/examples/test_good_bad.py similarity index 100% rename from modules/functions/slides-more/examples/test_good_bad.py rename to modules/functions/slides-recursion/examples/test_good_bad.py diff --git a/modules/functions/slides-more/examples/testarmodul.py b/modules/functions/slides-recursion/examples/testarmodul.py similarity index 100% rename from modules/functions/slides-more/examples/testarmodul.py rename to modules/functions/slides-recursion/examples/testarmodul.py diff --git a/modules/functions/slides-more/figs/pypi-matplotlib.png b/modules/functions/slides-recursion/figs/pypi-matplotlib.png similarity index 100% rename from modules/functions/slides-more/figs/pypi-matplotlib.png rename to modules/functions/slides-recursion/figs/pypi-matplotlib.png diff --git a/modules/functions/slides-more/figs/pypi-scipy.png b/modules/functions/slides-recursion/figs/pypi-scipy.png similarity index 100% rename from modules/functions/slides-more/figs/pypi-scipy.png rename to modules/functions/slides-recursion/figs/pypi-scipy.png diff --git a/modules/functions/slides-more/figs/pypi-torch.png b/modules/functions/slides-recursion/figs/pypi-torch.png similarity index 100% rename from modules/functions/slides-more/figs/pypi-torch.png rename to modules/functions/slides-recursion/figs/pypi-torch.png diff --git a/modules/functions/slides-more/figs/pypi.png b/modules/functions/slides-recursion/figs/pypi.png similarity index 100% rename from modules/functions/slides-more/figs/pypi.png rename to modules/functions/slides-recursion/figs/pypi.png diff --git a/modules/functions/slides-more/figs/pytorch-install.png b/modules/functions/slides-recursion/figs/pytorch-install.png similarity index 100% rename from modules/functions/slides-more/figs/pytorch-install.png rename to modules/functions/slides-recursion/figs/pytorch-install.png diff --git a/modules/functions/slides-more/figs/pytorch.png b/modules/functions/slides-recursion/figs/pytorch.png similarity index 100% rename from modules/functions/slides-more/figs/pytorch.png rename to modules/functions/slides-recursion/figs/pytorch.png diff --git a/modules/functions/slides/notes.tex b/modules/functions/slides-recursion/notes.tex similarity index 98% rename from modules/functions/slides/notes.tex rename to modules/functions/slides-recursion/notes.tex index 922a441f..6cd59a06 100644 --- a/modules/functions/slides/notes.tex +++ b/modules/functions/slides-recursion/notes.tex @@ -26,7 +26,7 @@ \begin{document} \title{% - Funktioner + Rekursion } \author{Daniel Bosk} \institute{% diff --git a/modules/functions/slides-more/preamble.tex b/modules/functions/slides-recursion/preamble.tex similarity index 100% rename from modules/functions/slides-more/preamble.tex rename to modules/functions/slides-recursion/preamble.tex index 9e96be71..7fa313f0 100644 --- a/modules/functions/slides-more/preamble.tex +++ b/modules/functions/slides-recursion/preamble.tex @@ -3,6 +3,9 @@ \usepackage[british]{babel} \usepackage{booktabs} +\usepackage[natbib,style=alphabetic,maxbibnames=99]{biblatex} +\addbibresource{slides.bib} + \usepackage[all]{foreign} \renewcommand{\foreignfullfont}{} \renewcommand{\foreignabbrfont}{} @@ -13,9 +16,6 @@ \usepackage[strict]{csquotes} \usepackage[single]{acro} -\usepackage[natbib,style=alphabetic,maxbibnames=99]{biblatex} -\addbibresource{slides.bib} - \usepackage{subcaption} \usepackage[noend]{algpseudocode} diff --git a/modules/functions/slides/slides.tex b/modules/functions/slides-recursion/slides.tex similarity index 99% rename from modules/functions/slides/slides.tex rename to modules/functions/slides-recursion/slides.tex index acd1b1b6..6282e342 100644 --- a/modules/functions/slides/slides.tex +++ b/modules/functions/slides-recursion/slides.tex @@ -97,7 +97,7 @@ \begin{document} \title{% - Funktioner + Rekursion } \author{Daniel Bosk} \institute{% diff --git a/modules/functions/slides/contents.tex b/modules/functions/slides/contents.tex deleted file mode 100644 index 173be36c..00000000 --- a/modules/functions/slides/contents.tex +++ /dev/null @@ -1,151 +0,0 @@ -\mode* - -\section{Funktioner} - -\subsection{Vad är bra med funktioner?} - -\begin{frame}[fragile] - \begin{block}{Funktioner} - \begin{itemize} - \item Som \enquote{miniprogram} som går att återanvända. - \item Gör att vi kan minimera kodupprepningar. - \item Ger färre problem, underlättar underhåll och utbyggnad. - \end{itemize} - \end{block} -\end{frame} - -\begin{frame}[fragile] - \begin{example}[Summera] - \begin{lstlisting} -l = [1, 2, 3, 4] -print(sum(l)) - \end{lstlisting} - \end{example} - - \begin{example}[Konkatenera] - \begin{lstlisting} -l = ["flag", "pole", "polishing"] -print(sum(l)) - \end{lstlisting} - \end{example} -\end{frame} - -\begin{frame}[fragile] - \begin{example}[Summera själv] - \begin{lstlisting} -summa = 0 - -for i in lst: - summa += i - \end{lstlisting} - \end{example} -\end{frame} - - -\subsection{Egna funktioner} - -\begin{frame}[fragile] - \begin{lstlisting}[basicstyle=\huge,numbers=none] -def func(parameters): - # use {parameters} - return results - \end{lstlisting} -\end{frame} - -\begin{frame}[fragile] - \begin{example}[summera.py] - \lstinputlisting{examples/summera.py} - \end{example} -\end{frame} - -\begin{frame}[fragile] - \begin{example}[input-int.py] - \lstinputlisting{examples/input-int.py} - \end{example} -\end{frame} - -\begin{frame}[fragile] - \begin{example}[input-int-default.py] - \lstinputlisting{examples/input-int-default.py} - \end{example} -\end{frame} - -\begin{frame}[fragile] - \begin{example}[input-type.py, del 1] - \lstinputlisting[linerange=3-12,firstnumber=3]{examples/input-type.py} - \end{example} -\end{frame} - -\begin{frame}[fragile] - \begin{example}[input-type.py, del 2] - \lstinputlisting[firstline=14,firstnumber=14]{examples/input-type.py} - \end{example} -\end{frame} - - -\section{Inbyggda funktioner} - -\begin{frame} - \includegraphics[width=\columnwidth]{figs/docs-built-in.png} -\end{frame} - -\subsection{map() och filter()} - -\begin{frame}[fragile] - \begin{example}[mapping.py, del 1] - \lstinputlisting[linerange=3-15,firstnumber=3]{examples/mapping.py} - \end{example} -\end{frame} - -\begin{frame}[fragile] - \begin{example}[mapping.py, del 2] - \lstinputlisting[firstline=16,firstnumber=17]{examples/mapping.py} - \end{example} -\end{frame} - -\begin{frame}[fragile] - \begin{example}[filtering.py, del 1] - \lstinputlisting[linerange=3-15,firstnumber=3]{examples/filtering.py} - \end{example} -\end{frame} - -\begin{frame}[fragile] - \begin{example}[filtering.py, del 2] - \lstinputlisting[firstline=21,firstnumber=21]{examples/filtering.py} - \end{example} -\end{frame} - -\subsection{Namnlösa (lambda-)funktioner} - -\begin{frame}[fragile] - \begin{example}[filter-lambda.py] - \lstinputlisting{examples/filter-lambda.py} - \end{example} -\end{frame} - -\begin{frame}[fragile] - \begin{example}[any-all.py, del 1] - \lstinputlisting[linerange=7-18,firstnumber=7]{examples/any-all.py} - \end{example} -\end{frame} - -\begin{frame}[fragile] - \begin{example}[any-all.py, del 2] - \lstinputlisting[firstline=20,firstnumber=20]{examples/any-all.py} - \end{example} -\end{frame} - -\subsection{zip() och enumerate()} - -\begin{frame}[fragile] - \begin{example}[enum.py] - \lstinputlisting{examples/enum.py} - \end{example} -\end{frame} - -\begin{frame}[fragile] - \begin{example}[zip.py] - \lstinputlisting{examples/zip.py} - \end{example} -\end{frame} - diff --git a/modules/helloworld/README.md b/modules/helloworld/README.md new file mode 100644 index 00000000..4c7a0551 --- /dev/null +++ b/modules/helloworld/README.md @@ -0,0 +1,7 @@ +# Hello World! + +Tanken med denna modul är att studenterna får lära sig terminalen genom [The +Terminal-modulen från introtools][introtools]. De får även börja med Hello +World-prgoram i Python genom att testa olika textredigerare och IDE:er. + +[introtools]: https://daniel.bosk.se/introtools/modules/terminal/terminal diff --git a/modules/helloworld/advanced_tutorial.md b/modules/helloworld/advanced_tutorial.md new file mode 100644 index 00000000..5c34c847 --- /dev/null +++ b/modules/helloworld/advanced_tutorial.md @@ -0,0 +1,78 @@ +--- +title: Fördjupande övning om terminalen, IDE:er och versionshantering +authors: + - Daniel Bosk + - Celina Soori +--- +# Fördjupande övning: Terminalen, IDE:er och versionshantering + +Målet med övningen är att du ska bli bättre på att + + - kontrollera datorn med terminalen, + - hantera filsystemet, + - använda en textredigerare eller IDE för att skriva program. + - versionshantera källkod. + + +## Repetition och förtydliganden + +Är det något ni skulle vilja repetera kort innan övningen kör igång? + + +## Textredigerare och IDE:er + +Under den här övningen ska vi jobba med __Laboration (0) Hello World__ som +ni hittar på Canvas. Dela upp er i smågrupper och hitta den textredigerare +som passar er bäst och se till att ni kan skapa och köra ett Hello +World-program i den. + +### Exempelkod + +```python +print("Hello World!") +``` +eller +```python +name = "World" +print(f"Hello {name}!") +``` + +## Hantera egna filer för kursen + +Vi vill hantera de egna filerna på kursen, så att vi håller koll på våra +inlämningar. + +### Terminalen och IDE:n + +Först vill vi ha en terminal. Hitta terminalen i IDE:n. Alternativt, om du +föredrar, använd terminalen utanför IDE:n. + + +### Skapa en mappstruktur för kursen + +Använd terminalen (och eventuellt den grafiska filhanteraren) för att skapa en +mappstruktur för kursen. Exempelvis en mapp för kursen. I den finns en mapp för +varje labb: labb1, labb2, ..., labb6. Lägg sedan in ett program i varje +labbmapp som skriver ut "Hello labb N" när det körs, där $N$ är labbens nummer. + +### Skapa ett Git repo för kursen + +Gör kursmappen ovan till ett Git-repo för att versionshantera dina inlämningar. + +Gör en redigering av labb 1 och spara ändringarna i repot. + + +### Pusha repot till GitHub + +Skapa ett privat repo på [GitHub][gh] eller [KTH GitHub][gits15]. Pusha +innehållet i repot ovan till repot på GitHub. + +[gh]: https://github.com +[gits15]: https://gits-15.sys.kth.se + + +### Utforska Git-integrering i din IDE + +Många IDE:er stödjer tillägg för versionshantering med Git (och andra system). +Utforska ur du kan integrera Git i din IDE för att hantera dina labbar. + diff --git a/modules/helloworld/lab.md b/modules/helloworld/lab.md new file mode 100644 index 00000000..f409f43c --- /dev/null +++ b/modules/helloworld/lab.md @@ -0,0 +1,91 @@ +--- +title: Laboration: Kom igång med Hello world +authors: + - Celina Soori +--- +# Laboration: Kom igång med Hello world + +Det här är en frivillig laboration för att hjälpa dig att komma igång med kodandet. +Du behöver inte lämna in något för denna laboration. + +Målet med laborationen är att: + +1. Installera Python. +2. Välj, installera och förstå en textredigerare. +3. Skriva ett enkelt program "Hello World". + +## Ladda ner Python + +Första steget vi ska göra är att installera Python. Det gör du enklast genom +att gå till [Pythons nedladdningssida](https://www.python.org/downloads/). + +När du installerar Python, missa inte att klicka i boxen musen pekar på +i bilden nedan (bilden är från Windows-versionen): + +![download_python](https://user-images.githubusercontent.com/105818197/186904393-23505d95-c172-4c9e-a949-952a4b8ded18.PNG) + +## Välj textredigerare + +Det finns många textredigerare därute, i den här kursen får du välja själv +vilken textredigerare du känner dig mest bekväm vid. Nedan kommer några +av de textredigerare vi rekommenderar. Under varje textredigerare finns en +länk till en tutorial som hjälper dig att skriva ditt första python-program. + +Hur din textredigerare ser ut på din dator stämmer inte alltid överens med +hur den ser ut i den tutorial du tittar på. Om du stöter på problem är du +välkommen till ett laborationstillfälle för att få hjälp! + +### PyCharm + +Installera PyCharm Community från [PyCharms nedladdningssida](https://www.jetbrains.com/pycharm/download/#section=windows). + +Läs genomgången [Create and run your first Python project](https://www.jetbrains.com/help/pycharm/creating-and-running-your-first-python-project.html#summary) +för att skapa ditt första program i PyCharm. Koden som används i genomgången +behöver du inte förstå, utan viktiga är att du förstår hur du öppnar PyCharm, +skapar ett program, skriver in kod i programmet och kör programmet. + +### IDLE + +IDLE är en textredigerare som installeras automatiskt när du installerar Python +(på de flesta system, på vissa Linux-system måste den installeras separat). + +Gå till sökbaren på din dator. Skriv in "IDLE" och öppna programmet IDLE +(Python GUI). Nu borde du se detta fönster: + +![idle_part1](https://user-images.githubusercontent.com/105818197/186905321-49a6c171-0786-4342-b0c9-0a4eb77ff16e.PNG) + +Följ nu [Writing, Saving and Running Python Programs with IDLE](https://thehelloworldprogram.com/python/python-program-idle/) för att +skapa ditt första program i IDLE. + + +### VSCode + +Installera VSCode från [VSCodes nedladdningssida](https://code.visualstudio.com/download). +När du installerat VSCode och startat det borde det se ut ungefär så här: + +![vscode_part1](https://user-images.githubusercontent.com/105818197/186906373-e111faad-a7bc-4900-a5a1-c98913098fe2.PNG) + +Följ nu de första 5 minuterna av [videon Visual Studio Code Python for Beginners: Hello World & Beyond](https://www.youtube.com/watch?v=dGeUH_bqNpA) +för att skriva ditt första Python-program! + + +## Skriv ett enkelt program + +Nu har du förhoppningsvis installerat Python och en textredigerare. Dags att skriva +ditt första egna program! + +Skapa en fil i din textredigerare och döp den till helloworld.py (eller något +annat skoj). Skriv in: +```python +message = "Hello World!" + +print(message) + +``` +Kör din fil helloworld.py i din textredigerare. Utskriften i terminalen ska nu +se ut så här: +``` +Hello World! +``` +Om du har lyckats med detta är du klar med Laboration 0 och är redo för veckans +utmaningar! diff --git a/modules/helloworld/slides/.gitignore b/modules/helloworld/slides/.gitignore new file mode 100644 index 00000000..30b2edc6 --- /dev/null +++ b/modules/helloworld/slides/.gitignore @@ -0,0 +1,3 @@ +notes.pdf +slides.pdf +beamer-didactic.sty diff --git a/modules/helloworld/slides/Makefile b/modules/helloworld/slides/Makefile new file mode 100644 index 00000000..1d9d9db6 --- /dev/null +++ b/modules/helloworld/slides/Makefile @@ -0,0 +1,26 @@ +.PHONY: all +all: notes.pdf slides.pdf + +LATEXFLAGS+= -shell-escape + +SRC+= preamble.tex +SRC+= abstract.tex contents.tex + +DEPENDS+= beamer-didactic.sty + + +notes.pdf: notes.tex +slides.pdf: slides.tex + +notes.pdf slides.pdf: ${SRC} ${DEPENDS} + + +.PHONY: clean +clean: + ${RM} notes.pdf slides.pdf + + +INCLUDE_MAKEFILES=../../../makefiles +include ${INCLUDE_MAKEFILES}/tex.mk +INCLUDE_BEAMERDIDACTIC=../../../beamer-didactic +include ${INCLUDE_BEAMERDIDACTIC}/beamer-didactic.mk diff --git a/modules/helloworld/slides/abstract.tex b/modules/helloworld/slides/abstract.tex new file mode 100644 index 00000000..4012d9d3 --- /dev/null +++ b/modules/helloworld/slides/abstract.tex @@ -0,0 +1,22 @@ +% What's the problem? +% Why is it a problem? Research gap left by other approaches? +% Why is it important? Why care? +% What's the approach? How to solve the problem? +% What's the findings? How was it evaluated, what are the results, limitations, +% what remains to be done? + +% XXX Summary +\emph{Summary:} +\dots + +% XXX Motivation and intended learning outcomes +\emph{Intended learning outcomes:} +\dots + +% XXX Prerequisites +\emph{Prerequisites:} +\dots + +% XXX Reading material +\emph{Reading:} +\dots diff --git a/modules/helloworld/slides/contents.tex b/modules/helloworld/slides/contents.tex new file mode 100644 index 00000000..75687938 --- /dev/null +++ b/modules/helloworld/slides/contents.tex @@ -0,0 +1,216 @@ +\title{% + Hello World! +} +\author{Daniel Bosk} +\institute{% + KTH EECS +} + +\mode
{\maketitle} +\mode{% + \begin{frame} + \maketitle + \end{frame} +} + +\mode* + +\begin{abstract} + \input{abstract.tex} +\end{abstract} + + +\section{Programmering} + +\subsection{Vad är programmering?} + +\begin{frame} + \begin{block}{Dator} + \begin{itemize} + \item Processor + \item Minne + \item Annan hårdvara + \end{itemize} + \end{block} +\end{frame} + +\begin{frame} + \begin{block}{Processorn} + \begin{itemize} + \item Exekverar maskinkod --- program + \end{itemize} + \end{block} + + \pause + + \begin{example} + \begin{itemize} + \item<1-2> 00012000050000020500 + \item<3-> 0001 2000 0500 + \item<3-> 0002 0500 + \end{itemize} + \end{example} +\end{frame} + +\begin{frame} + \begin{block}{Svar} + \begin{itemize} + \item Programmering är att skriva program. + \end{itemize} + \end{block} +\end{frame} + + +\subsection{Programmeringsspråk} + +\begin{frame} + \begin{block}{Programmeringsspråk} + \begin{itemize} + \item Ett språk för människor att skriva datorprogram. + \end{itemize} + \end{block} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[Python] + \begin{minted}{python} +print("Hello, World!") + \end{minted} + \end{example} + + \pause + + \begin{example}[C++] + \begin{minted}{c++} +#include +using namespace std; + +int main(void) { + std::cout << "Hello, World!" << std::endl; + return 0; +} + \end{minted} + \end{example} +\end{frame} + +\begin{frame} + \begin{remark} + \begin{itemize} + \item C++ måste översättas till maskinkod! + \item Python läses av ett program (maskinkod), och det programmet + exekverar koden. + \end{itemize} + \end{remark} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[Terminalen] + \begin{minted}{bash} +echo "Hello World!" + \end{minted} + \end{example} + + \pause + + \begin{remark} + \begin{itemize} + \item Bash läser varje rad och exekverar olika program. + \item Dessa program är redan konverterade till maskinkod. + \end{itemize} + \end{remark} +\end{frame} + + +\section{Köra Python} + +\subsection{Terminalen} + +\begin{frame} + \begin{figure} + \centering + \includegraphics[height=0.8\textheight]{figs/python-terminal.png} + \caption{Ett kodexempel i Python som skriver ut \enquote{hello world!} i + terminalen.} + \end{figure} +\end{frame} + + +\subsection{Andra gränssnitt} + +\begin{frame} + \begin{figure} + \centering + \includegraphics[height=0.8\textheight]{figs/idle.jpg} + \caption{Kod och körning av pythonkod i Idle.} + \end{figure} +\end{frame} + +\begin{frame} + \begin{figure} + \centering + \includegraphics[height=0.8\textheight]{figs/codium.png} + \caption{Gränssnittet till VSCodium (öppen källkodsvariant av Visual Studio + Code).} + \end{figure} +\end{frame} + +\begin{frame} + \begin{figure} + \centering + \includegraphics[height=0.8\textheight]{figs/atom.png} + \caption{Gränssnittet för Atom.} + \end{figure} +\end{frame} + +\begin{frame} + \begin{figure} + \centering + \includegraphics[height=0.8\textheight]{figs/pycharm.png} + \caption{Gränssnittet för PyCharm.} + \end{figure} +\end{frame} + + +\section{Hello World!} + +\begin{frame}[fragile] + \begin{example} + \begin{minted}{python} +# Skriver ut till skärmen +print("Hello, World!") + \end{minted} + \end{example} + + \pause + + \begin{example} + \begin{minted}{python} +# Skriver ut "Hello" + namnet till skärmen +name = "World" +print(f"Hello {name}!") + \end{minted} + \end{example} +\end{frame} + +\begin{frame}[fragile] + \begin{example} + \begin{minted}{python} +# Skriver ut "Hello" + namnet till skärmen +name = "World" +print(f"Hello {name}!") + \end{minted} + \end{example} + + \pause + + \begin{example}[Funktioner] + \begin{minted}{python} +def print_hello(name): + """Skriver ut till skärmen""" + print(f"Hello, {name}!") + +print_hello("World") + \end{minted} + \end{example} +\end{frame} + diff --git a/modules/variables/slides/figs/atom.png b/modules/helloworld/slides/figs/atom.png similarity index 100% rename from modules/variables/slides/figs/atom.png rename to modules/helloworld/slides/figs/atom.png diff --git a/modules/variables/slides/figs/codium.png b/modules/helloworld/slides/figs/codium.png similarity index 100% rename from modules/variables/slides/figs/codium.png rename to modules/helloworld/slides/figs/codium.png diff --git a/modules/variables/slides/figs/idle.jpg b/modules/helloworld/slides/figs/idle.jpg similarity index 100% rename from modules/variables/slides/figs/idle.jpg rename to modules/helloworld/slides/figs/idle.jpg diff --git a/modules/variables/slides/figs/pycharm.png b/modules/helloworld/slides/figs/pycharm.png similarity index 100% rename from modules/variables/slides/figs/pycharm.png rename to modules/helloworld/slides/figs/pycharm.png diff --git a/modules/variables/slides/figs/python-terminal.png b/modules/helloworld/slides/figs/python-terminal.png similarity index 100% rename from modules/variables/slides/figs/python-terminal.png rename to modules/helloworld/slides/figs/python-terminal.png diff --git a/modules/helloworld/slides/notes.tex b/modules/helloworld/slides/notes.tex new file mode 100644 index 00000000..b6f9a884 --- /dev/null +++ b/modules/helloworld/slides/notes.tex @@ -0,0 +1,30 @@ +\documentclass{article} + +\usepackage[hyphens]{url} +\usepackage[hidelinks]{hyperref} + +\input{preamble.tex} + +\usepackage[noamsthm,notheorems]{beamerarticle} +\setjobnamebeamerversion{slides} + +%\usepackage{authblk} +%\let\institute\affil + +\declaretheorem[numbered=unless unique,style=theorem]{theorem} +\declaretheorem[numbered=unless unique,style=definition]{definition} +\declaretheorem[numbered=unless unique,style=definition]{assumption} +\declaretheorem[numbered=unless unique,style=definition]{protocol} +\declaretheorem[numbered=unless unique,style=example]{example} +%\declaretheorem[style=definition,numbered=unless unique, +% name=Example,refname={example,examples}]{example} +\declaretheorem[numbered=unless unique,style=remark]{remark} +\declaretheorem[numbered=unless unique,style=remark]{idea} +\declaretheorem[numbered=unless unique,style=exercise]{exercise} +\declaretheorem[numbered=unless unique,style=exercise]{question} +\declaretheorem[numbered=unless unique,style=solution]{solution} + +\begin{document} +\input{contents.tex} +\printbibliography +\end{document} diff --git a/modules/helloworld/slides/preamble.tex b/modules/helloworld/slides/preamble.tex new file mode 100644 index 00000000..ee813387 --- /dev/null +++ b/modules/helloworld/slides/preamble.tex @@ -0,0 +1,39 @@ +\usepackage[utf8]{inputenc} +\usepackage[T1]{fontenc} +\usepackage[british,swedish]{babel} +\usepackage{booktabs} + +\usepackage[natbib,style=alphabetic,maxbibnames=99]{biblatex} +\addbibresource{slides.bib} + +\usepackage[all]{foreign} +\renewcommand{\foreignfullfont}{} +\renewcommand{\foreignabbrfont}{} + +\usepackage{newclude} +\usepackage{import} + +\usepackage[strict]{csquotes} +\usepackage[single]{acro} + +\usepackage{subcaption} + +\usepackage[noend]{algpseudocode} +\usepackage{xparse} + +\let\email\texttt + +\usepackage[outputdir=ltxobj]{minted} +\setminted{autogobble,fontsize=\footnotesize} + +\usepackage{amsmath} +\usepackage{amssymb} +\usepackage{mathtools} +\usepackage{amsthm} +\usepackage{thmtools} +\usepackage[unq]{unique} +\DeclareMathOperator{\powerset}{\mathcal{P}} + +\usepackage[binary-units]{siunitx} + +\usepackage[capitalize]{cleveref} diff --git a/modules/conditionals/slides/slides.tex b/modules/helloworld/slides/slides.tex similarity index 100% rename from modules/conditionals/slides/slides.tex rename to modules/helloworld/slides/slides.tex diff --git a/modules/helloworld/tutorial.md b/modules/helloworld/tutorial.md new file mode 100644 index 00000000..8aa2a7ee --- /dev/null +++ b/modules/helloworld/tutorial.md @@ -0,0 +1,60 @@ +--- +title: Övning om Hello World! +authors: + - Daniel Bosk + - Celina Soori +--- +# Övning: Hello World! + +Målet med övningen är att du ska bli bättre på att + + - kontrollera datorn med terminalen, + - hantera filsystemet, + - använda en textredigerare eller IDE för att skriva program. + +## Genomgång av veckans svårigheter + +Vi går igenom det vi upptäckt i OLI är extra svårt den här veckan. + +Zoomlänk: + +## Terminalen + +Under veckans föreläsning har ni arbetat med terminalen. Om ni +har frågor eller behöver hjälp med terminalen, be en lärarassistent +om hjälp när vi jobbar med Hello World. + +## Hello World! + +Under den här övningen ska vi jobba med __Laboration (0) Hello World__ som +ni hittar på Canvas. Dela upp er i smågrupper och hitta den textredigerare +som passar er bäst och se till att ni kan skapa och köra ett Hello World-program +i den. + +### Exempelkod + +```python +print("Hello World!") +``` +eller +```python +name = "World" +print(f"Hello {name}!") +``` + +### Skapa en mappstruktur för kursen + +Använd terminalen och den grafiska filhanteraren och skapa en mappstruktur för +kursen. Exempelvis en mapp för kursen. I den finns en mapp för varje labb: +labb1, labb2, ..., labb6. Lägg sedan in ett program i varje labbmapp som +skriver ut "Hello labb N" när det körs, där $N$ är labbens nummer. + +Prova att växla mellan labbarna och köra dem. Om programmet skriver ut "Hello +labb N" så vet du att du kör rätt program. + + +### Mer med terminalen + +Använd terminalen för att redigera labb 3 i din mappstruktur. Använd därefter +terminalen för att köra labb 3 i terminalen. + diff --git a/modules/iterations/lab/instruction.md b/modules/iterations/lab/instruction.md index 526ae23a..f729c083 100644 --- a/modules/iterations/lab/instruction.md +++ b/modules/iterations/lab/instruction.md @@ -1,28 +1,60 @@ -# Laboration: Iterationer +--- +title: Laboration om Upprepningar, moduler och mer felhantering +authors: + - Daniel Bosk + - Celina Soori +--- +# Laboration: Upprepningar, moduler och mer felhantering -Hittills har vi antagit att användaren matat in korrekta data, men det är inte -alltid fallet. I den här laborationen ska vi felsäkra det program vi skrev i -föregående laboration. +Hittills har vi avslutat programmet om användaren matat in inkorrekt data, men +det är inte särskilt användbart. I den här laborationen ska vi felsäkra det +program vi skrev i föregående laboration med hjälp av egna +felhanteringsfunktioner som låter användaren skriva in datan igen. De +funktioner vi skriver i denna laboration kommer vara bra verktyg att ha för +kommande laborationer! + +## Innan du börjar koda + +Läs på om [felhantering][felhantering] samt om [moduler][moduler]. + +[felhantering]: https://docs.python.org/3/tutorial/errors.html +[moduler]: https://docs.python.org/3/tutorial/modules.html#:~:text=A%20module%20is%20a%20file,global%20variable%20__name__%20. ## Uppgift -Skriv en funktion (eller flera funktioner om så behövs) som tar inmatning från -användaren och inte returnerar förrän användaren har matat in korrekt data. -Ersätt all inmatning i förra programmet med din(a) nya funktion(er). Föregående -program tog följande inmatning: -``` -Data för den aritmetiska summan: -a_1: 1 -d: 2 -Data för den geometriska summan: -g_1: 1.01 -q: 1.10 -Antal termer i summorna: -n: 10 -Den aritmetiska summan är störst. +I denna laboration kommer vi använda oss av en egenskriven modul som vi +importerar in i vårt huvudprogram. Denna modul ska innehålla två funktioner, en +som kontrollerar att inmatningen är ett heltal (`int`) och en som kontrollerar +att inmatningen är ett flyttal (`float`). De två funktionerna ska ta inmatning +från användaren och inte returnera förrän användaren har matat in korrekt data. + +Ert huvudprogram kommer efteråt likna programmet nedan (med bättre variabelnamn): + +```python +import typed_input + +def sum_arithmetic(a1, d, n): + # Here goes your code from earlier labs + +def sum_geometric(g1, q, n): + # Here goes your code from earlier labs + +def main(): + a1 = typed_input.input_float("Skriv in värdet på a1: ") + d = typed_input.input_float("Skriv in värdet på d: ") + n = typed_input.input_int("Skriv in värdet på n: ") + + arithmetic = sum_arithmetic(a1, d, n) + + g1 = typed_input.input_float("Skriv in värdet på a1: ") + q = typed_input.input_float("Skriv in värdet på d: ") + + geometric = sum_geometric(g1, q, n) + + # and then your code to compare the two sums ``` -Men nu ska vi kunna hantera att användaren matar in fel, exempelvis: +### Exempelutskrift ``` Data för den aritmetiska summan: a_1: a @@ -37,7 +69,41 @@ q: 1.10 Antal termer i summorna: n: 0 n måste vara större än noll. +n: 10.2 +n måste vara ett heltal. n: 10 Den aritmetiska summan är störst. ``` +### Krav + +* Felhanteringsfunktionerna ska vara i en separat modul som importeras in i + huvudprogrammet +* All inmatning ska felhanteras med hjälp av passande hjälpfunktion. +* Användaren ska ha oändligt antal försök på sig att mata in rätt värden. +* Ditt program ska kunna hantera alla testfall som visas i exempelutskriften. +* Din kod ska uppfylla kraven i rättningsmatrisen. + +### Redovisning + +Denna laboration ska redovisas för en lärarassistent på ett +laborationstillfälle. Information om bokning av redovisningstillfälle kommer +komma upp på Canvas. På redovisningen ska du kunna +köra ditt program och beskriva din kod detaljerat. + +## Frivilliga extrauppgifter + +### Mer generell typhantering + +Istället för att ha `typed_input.input_int("Mata in heltal: ")` så kan du +skriva en funktion som tar typen som argument: +`typed_input.input_type(int, "Mata in heltal: ")`. +På så vis kan funktionen hantera alla typer som finns. + +### Paketering + +Läs om [paketering][packaging] i Python och gör din modul installerbar +genom `pip`. Då kan andra enkelt installera din modul på sina system. + +[packaging]: https://packaging.python.org/tutorials/packaging-projects/ + diff --git a/modules/iterations/slides/README.md b/modules/iterations/slides/README.md new file mode 100644 index 00000000..7da713ae --- /dev/null +++ b/modules/iterations/slides/README.md @@ -0,0 +1,5 @@ +- [YouTube: Upprepningar][yt] +- [FeedbackFruits: Upprepningar][fbf] + +[yt]: https://youtu.be/wO0fiuYeXCw +[fbf]: https://eu.feedbackfruits.com/courses/activity-course/a0f42cb6-ad1f-47f0-ad12-ad4787469a60 diff --git a/modules/iterations/slides/contents.tex b/modules/iterations/slides/contents.tex index cf40b2ab..910b544c 100644 --- a/modules/iterations/slides/contents.tex +++ b/modules/iterations/slides/contents.tex @@ -1,56 +1,5 @@ \mode* -\section{En notis om pedagogik} - -\begin{frame} - \begin{question} - \begin{itemize} - \item Learn by trying or by being told? - \end{itemize} - \end{question} -\end{frame} - -\begin{frame} - \begin{example}[Learn by trying or by being told? - {\cite[pp.~214--221]{NecessaryConditionsOfLearning}}] - \begin{itemize} - \item \Textcite{Szekely1950} studied the problem in 1950. - \end{itemize} - \begin{enumerate} - \item<2,3> Presented a puzzling phenomena (Problem A) to a group. - \item<2,3> Presented a text explaining the phenomena afterwards. - \end{enumerate} - \begin{enumerate} - \item<3> Presented a text explaining the phenomena. - \item<3> Presented the puzzling phenomena (Problem A) afterwards. - \end{enumerate} - \begin{itemize} - \item<4> Called them back a week later with related Problem B. - \item<4> The order for Problem A had significant impact on solving - Problem B. - \end{itemize} - \end{example} -\end{frame} - -\begin{frame} - \begin{remark}[Reproduced] - \begin{itemize} - \item Confirmed by later studies as well. - \item \Textcite{BransfordSchwartz1999} studied effect on future learning. - \item Students learn more easily from being told if they tried first. - \end{itemize} - \end{remark} - - \pause - - \begin{remark} - \begin{itemize} - \item \emph{Even if the time spent is the same!} - \end{itemize} - \end{remark} -\end{frame} - - \section{Rekursion} \begin{frame} @@ -63,8 +12,23 @@ \section{Rekursion} \end{frame} \begin{frame}[fragile] - \begin{solution}[En möjlig lösning] + \begin{solution}[En dålig lösning] \begin{minted}{python} + def skriv_ut(meddelande): + """Skriver ut meddelande""" + print(meddelande) + + skriv_ut("hej") + skriv_ut("hej") + ... + skriv_ut("hej") + \end{minted} + \end{solution} +\end{frame} + +\begin{frame}[fragile] + \begin{solution}[En möjlig lösning] + \begin{minted}[highlightlines={1,3-4,7}]{python} def skriv_ut(meddelande, antal_gånger): """Skriver ut meddelande antal_gånger antal gånger""" if antal_gånger <= 0: @@ -72,24 +36,22 @@ \section{Rekursion} print(meddelande) skriv_ut(meddelande, antal_gånger-1) + + skriv_ut("hej", 50) \end{minted} \end{solution} \end{frame} \begin{frame}[fragile] - \begin{definition}[Rekursion] - \begin{minted}{python} - def rekursiv_funktion(argument): - """Rekurserar tills att vi når basfallet""" - if basfall(argument): - return - - rekursiv_funktion(nästa(argument)) - \end{minted} + \begin{definition}[Fibonacci-serien] + \begin{itemize} + \item \(f_0 = 0\) + \item \(f_1 = 1\) + \item \(\vdots\) + \item \(f_n = f_{n-1} + f_{n-2}\) + \end{itemize} \end{definition} -\end{frame} -\begin{frame}[fragile] \begin{example}[Fibonacci] \begin{minted}{python} def fib(n): @@ -105,11 +67,24 @@ \section{Rekursion} \end{frame} \begin{frame}[fragile] - \begin{example}[Gåexemplet] - \inputminted[firstline=32]{python}{examples/walk.py} - \end{example} + \begin{definition}[Rekursion] + \begin{minted}{python} + def rekursiv_funktion(argument): + """Rekurserar tills att vi når basfallet""" + if basfall(argument): + return + + rekursiv_funktion(nästa(argument)) + \end{minted} + \end{definition} \end{frame} +%\begin{frame}[fragile] +% \begin{example}[Gåexemplet] +% \inputminted[firstline=32]{python}{examples/walk.py} +% \end{example} +%\end{frame} + \section{Iterationer} @@ -195,6 +170,34 @@ \section{Iterationer} \footnotetext{Idé: Olle Bälter}} \end{frame} +\begin{frame}[fragile] + \begin{remark} + \begin{itemize} + \item Typ av iteration beror på angreppssätt. + \end{itemize} + \end{remark} +\end{frame} + +\begin{frame}[fragile] + \begin{solution}[Alternativ rekursion] + \inputminted[linenos,firstline=3,lastline=10]{python}{examples/siffersumma.py} + \dots + \inputminted[linenos,firstline=44]{python}{examples/siffersumma.py} + \end{solution} +\end{frame} + +\begin{frame}[fragile] + \begin{solution}[Alternativ while] + \inputminted[linenos,firstline=12,lastline=21]{python}{examples/siffersumma.py} + \end{solution} +\end{frame} + +\begin{frame}[fragile] + \begin{solution}[Alternativ for] + \inputminted[linenos,firstline=23,lastline=31]{python}{examples/siffersumma.py} + \end{solution} +\end{frame} + \mode{\endinput} \section{Större exempel} diff --git a/modules/iterations/slides/examples/countdown.py b/modules/iterations/slides/examples/countdown.py new file mode 100644 index 00000000..68a8c169 --- /dev/null +++ b/modules/iterations/slides/examples/countdown.py @@ -0,0 +1,14 @@ +"""Program som räknar ned""" + +import time + +def count_down(n): + """Räkna ned till noll, börja på n.""" + while n > 0: + print(f"n = {n}") + #n = n - 1 + n -= 1 + time.sleep(1) + +count_down(10) +print("Gott nytt år!") diff --git a/modules/iterations/slides/examples/fib.py b/modules/iterations/slides/examples/fib.py index bfe162f6..08f40aa1 100644 --- a/modules/iterations/slides/examples/fib.py +++ b/modules/iterations/slides/examples/fib.py @@ -2,8 +2,6 @@ def fib(n): """Returnerar n:te talet i Fibonacci-serien""" - print(f"fib({n})") - if n <= 0: return 0 elif n == 1: @@ -11,4 +9,8 @@ def fib(n): return fib(n-1) + fib(n-2) +print(f"fib(1) = {fib(1)}") +print(f"fib(2) = {fib(2)}") +print(f"fib(3) = {fib(3)}") +print(f"fib(4) = {fib(4)}") print(f"fib(5) = {fib(5)}") diff --git a/modules/iterations/slides/examples/guess-short.py b/modules/iterations/slides/examples/guess-short.py new file mode 100644 index 00000000..bdb876b7 --- /dev/null +++ b/modules/iterations/slides/examples/guess-short.py @@ -0,0 +1,9 @@ +guess = int(input("Guess one of my favourite numbers: ")) + +while guess != 2 and guess != 3 and guess != 5: + try: + guess = int(input("Wrong, guess again: ")) + except ValueError: + print("It's an actual number ...", end=" ") + +print("Finally, that's correct!") diff --git a/modules/iterations/slides/examples/guess.py b/modules/iterations/slides/examples/guess.py index a1e827f8..3efffc40 100644 --- a/modules/iterations/slides/examples/guess.py +++ b/modules/iterations/slides/examples/guess.py @@ -6,32 +6,49 @@ NUM_OF_ROUNDS = 2 NUM_OF_ATTEMPTS = 5 -results = [] -for q in range(NUM_OF_ROUNDS): - number = random.randint(0, 10) - for i in range(NUM_OF_ATTEMPTS): +def input_guess(attempt): + """Låter användaren mata in en gissning, + returnerar gissningen när användaren lyckats mata in korrekt.""" while True: - try: - guess = int(input(f"Guess the number between 0--10 (attempt {i+1}): ")) - except: - print("Sorry, that didn't work.") - continue - if 0 <= guess and guess <= 10: - break - else: - print("You should guess between 0 and 10.") - - if guess == number: - break - - if guess == number: - print("Congrats, next round!") - results.append(NUM_OF_ATTEMPTS-i) - else: - print(f"You didn't make it, the correct number was {number}.") - results.append(0) - -score = sum(results)/NUM_OF_ROUNDS -print(f"Your average was {score:.2f}.") + try: + guess = int(input( + f"Guess the number between 0--10 (attempt {attempt}): ")) + except ValueError: + print("Sorry, that didn't work.") + continue + if not(0 <= guess and guess <= 10): + print("You should guess between 0 and 10.") + continue + + return attempt + +def guess_game(num_rounds=NUM_OF_ROUNDS, num_attempts=NUM_OF_ATTEMPTS): + """Kör ett gissningsspel, låter användaren få num_rounds frågor.""" + results = [] + + for q in range(num_rounds): + number = random.randint(0, 10) + for attempt in range(num_attempts): + guess = input_guess(attempt+1) + + if guess == number: + break + + if guess == number: + print("Congrats, next round!") + results.append(NUM_OF_ATTEMPTS-attempt) + else: + print(f"You didn't make it, the correct number was {number}.") + results.append(0) + + return results + +def main(): + """Huvudprogrammet""" + score = sum(guess_game(NUM_OF_ROUNDS, NUM_OF_ATTEMPTS))/NUM_OF_ROUNDS + print(f"Your average was {score:.2f}.") + +if __name__ == "__main__": + main() diff --git a/modules/iterations/slides/examples/hej.py b/modules/iterations/slides/examples/hej.py index 628f4205..07a7754f 100644 --- a/modules/iterations/slides/examples/hej.py +++ b/modules/iterations/slides/examples/hej.py @@ -1,24 +1,25 @@ """Program som skriver ut hej 50 gånger""" -print("for") -for gång in range(50): - print(f"hej {gång}!") - if gång > 2: - break +def hej_for(): + """Skriver ut hej 50 gånger med en for-loop""" + for gång in range(50): + print(f"hej {gång}!") -print("while") -antal = 50 -while antal > 0: - print(f"hej {antal}!") - # antal = antal - 1 - antal -= 1 - if antal < 48: - break +def hej_while(): + """Skriver ut hej 50 gånger med en while-loop""" + antal = 50 + while antal > 0: + print(f"hej {antal}!") + # antal = antal - 1 + antal -= 1 -print("while alternativ") -antal = 0 -while antal < 50: - print(f"hej {antal}!") - antal += 1 - if antal > 2: - break +def hej_while_alt(): + """En alternativ version av hej_while""" + antal = 0 + while antal < 50: + print(f"hej {antal}!") + antal += 1 + + +if __name__ == "__main__": + hej_for() diff --git a/modules/iterations/slides/examples/hej_break.py b/modules/iterations/slides/examples/hej_break.py new file mode 100644 index 00000000..c5dbf401 --- /dev/null +++ b/modules/iterations/slides/examples/hej_break.py @@ -0,0 +1,31 @@ +"""Program som skriver ut hej 50 gånger""" + +def hej_for(): + """Skriver ut hej 50 gånger med en for-loop""" + for gång in range(50): + print(f"hej {gång}!") + if gång > 2: + break + +def hej_while(): + """Skriver ut hej 50 gånger med en while-loop""" + antal = 50 + while antal > 0: + print(f"hej {antal}!") + # antal = antal - 1 + antal -= 1 + if antal < 48: + break + +def hej_while_alt(): + """En alternativ version av hej_while""" + antal = 0 + while antal < 50: + print(f"hej {antal}!") + antal += 1 + if antal > 2: + break + + +if __name__ == "__main__": + hej_for() diff --git a/modules/iterations/slides/examples/hej_rekursion.py b/modules/iterations/slides/examples/hej_rekursion.py new file mode 100644 index 00000000..09728f70 --- /dev/null +++ b/modules/iterations/slides/examples/hej_rekursion.py @@ -0,0 +1,9 @@ +def skriv_ut(meddelande, antal_gånger): + """Skriver ut meddelande antal_gånger antal gånger""" + if antal_gånger <= 0: + return + + print(meddelande) + skriv_ut(meddelande, antal_gånger-1) + +skriv_ut("Hej", 2000) diff --git a/modules/iterations/slides/examples/in.py b/modules/iterations/slides/examples/in.py new file mode 100644 index 00000000..521f444a --- /dev/null +++ b/modules/iterations/slides/examples/in.py @@ -0,0 +1,9 @@ +while True: + try: + x = float(input("Mata in ett tal: ")) + except ValueError as err: + print(f"Tyvärr, det blev fel: {err}, försök igen.") + else: + break + +print(x) diff --git a/modules/iterations/slides/examples/siffersumma.py b/modules/iterations/slides/examples/siffersumma.py index 0cd3eaf4..b31ce9b9 100644 --- a/modules/iterations/slides/examples/siffersumma.py +++ b/modules/iterations/slides/examples/siffersumma.py @@ -12,7 +12,7 @@ def siffersumma(heltal): def siffersumma_while(heltal): """Returnerar siffersumman för heltalet heltal (int)""" summan = 0 - + while heltal > 0: sista_siffran = heltal % 10 summan += sista_siffran @@ -20,6 +20,16 @@ def siffersumma_while(heltal): return summan +def siffersumma_for(heltal): + """Returnerar siffersumman för heltal (int)""" + summan = 0 + siffror = str(heltal) + + for siffra in siffror: + summan += int(siffra) + + return summan + -heltal = int(input("Postivt heltal: ")) -print(f"Siffersumman för {heltal} är {siffersumma_while(heltal)}!") +heltalet = int(input("Postivt heltal: ")) +print(f"Siffersumman för {heltalet} är {siffersumma(heltalet)}!") diff --git a/modules/iterations/slides/examples/skriv_ut.py b/modules/iterations/slides/examples/skriv_ut.py index 0f31ec51..f6b00a8a 100644 --- a/modules/iterations/slides/examples/skriv_ut.py +++ b/modules/iterations/slides/examples/skriv_ut.py @@ -8,4 +8,4 @@ def skriv_ut(meddelande, antal_gånger): print(meddelande) skriv_ut(meddelande, antal_gånger-1) -skriv_ut("hej", 2000) +skriv_ut("hej", 995) diff --git a/modules/iterations/slides/notes.tex b/modules/iterations/slides/notes.tex index 5aee944d..fa967fa5 100644 --- a/modules/iterations/slides/notes.tex +++ b/modules/iterations/slides/notes.tex @@ -26,7 +26,7 @@ \begin{document} \title{% - Rekursion och iterationer + Upprepningar } \author{Daniel Bosk} \institute{% diff --git a/modules/iterations/slides/preamble.tex b/modules/iterations/slides/preamble.tex index 39fe85cc..beac929d 100644 --- a/modules/iterations/slides/preamble.tex +++ b/modules/iterations/slides/preamble.tex @@ -3,6 +3,9 @@ \usepackage[british]{babel} \usepackage{booktabs} +\usepackage[natbib,style=alphabetic,maxbibnames=99]{biblatex} +\addbibresource{pedagogy.bib} + \usepackage[all]{foreign} \renewcommand{\foreignfullfont}{} \renewcommand{\foreignabbrfont}{} @@ -13,9 +16,6 @@ \usepackage[strict]{csquotes} \usepackage[single]{acro} -\usepackage[natbib,style=alphabetic,maxbibnames=99]{biblatex} -\addbibresource{pedagogy.bib} - \usepackage{subcaption} \usepackage[noend]{algpseudocode} diff --git a/modules/iterations/slides/slides.tex b/modules/iterations/slides/slides.tex index f9c3c255..1e8e0002 100644 --- a/modules/iterations/slides/slides.tex +++ b/modules/iterations/slides/slides.tex @@ -97,7 +97,7 @@ \begin{document} \title{% - Rekursion och iterationer + Upprepningar } \author{Daniel Bosk} \institute{% @@ -112,7 +112,7 @@ \input{contents.tex} \mode* -\begin{frame}[allowframebreaks] - \printbibliography -\end{frame} +%\begin{frame}[allowframebreaks] +% \printbibliography +%\end{frame} \end{document} diff --git a/modules/iterations/tutorial/advanced_instruction.md b/modules/iterations/tutorial/advanced_instruction.md new file mode 100644 index 00000000..aecf4882 --- /dev/null +++ b/modules/iterations/tutorial/advanced_instruction.md @@ -0,0 +1,108 @@ +--- +title: Fördjupande övning om upprepningar +authors: + - Daniel Bosk + - Celina Soori +--- +# Fördjupande övning: upprepningar, listor och moduler + +Målet med övningen är att du ska få en djupare förståelse för för hur du ska + + - tillämpa olika former av upprepningar: rekursion, for- och + while-iterationer, + - iterera genom och lägga till element i en lista, + - konstruera interaktiva program, + - dela upp problem i mindre problem, + - minimera kodupprepning, + - leta i Pythons dokumentation. + + +## Önskemål från gruppen + +Var det något särskilt från veckans föreläsning och/eller OLI-material som gruppen vill gå in djupare på? + +Är det någon som vill visa upp något särskilt från förra veckans laboration som kan ge inspiration till gruppen? + +## Övningsuppgifter + +### Fibonacci sekvenser + +Skriv ett program som räknar ut en Fibonacci-sekvens rekursivt. + +För att komma igång: +- Vad är rekursion? +- Hur kan vi skriva en funktion som anropas rekursivt? + +[Lösningsförslag](https://github.com/dbosk/intropy/blob/master/modules/iterations/tutorial/fib.py) + +Finns det några brister i lösningsförslaget? + +### Multiplikationshjälpmedel + +**Multiplikationstabellen** Låt användaren ange vilken multiplikationstabell +hen vill se och skriv ut den. Exempelvis 7:ans multiplikationstabell: +``` +Vilken multiplikationstabell vill du se? 7 + + 7 | 7 14 21 28 35 42 49 56 63 70 +``` + +**Multiplikationstabeller** Låt användaren ange vilket maxtal som ska anges i +multiplikationstabellerna. Skriv sedan ut dem. Exempelvis alla +multiplikationstabeller upp till 7: +``` +Vilket är det högsta tal du vill multiplicera? 7 + + * | 1 2 3 4 5 6 7 +---+--------------------- + 1 | 1 2 3 4 5 6 7 + 2 | 2 4 6 8 10 12 14 + 3 | 3 6 9 12 15 18 21 + 4 | 4 8 12 16 20 24 28 + 5 | 5 10 15 20 25 30 35 + 6 | 6 12 18 24 30 36 42 + 7 | 7 14 21 28 35 42 49 +``` + +Ett lösningsförslag finns i [multtable.py][multtable]. + +[multtable]: https://github.com/dbosk/intropy/blob/master/modules/iterations/tutorial/multtable.py + + +### Primtalsfaktorisering + +Ett [primtal][primtal] är ett tal som endast är delbart med 1 och sig självt, +exempelvis 2, 3, 5, 7, 11 och 13. [Aritmetikens fundamentalsats][aritfund] +säger att "varje heltal större än 1 kan skrivas som en produkt av primtal på +ett och endast ett sätt" (primtalsfaktorerna är sorterade, $2\cdot 3$ och +$3\cdot 2$ räknas som samma). + +Skriv en funktion som tar ett heltal och returnerar en sträng med dess +primtalsfaktorer. Exempelvis: $15 = 3\cdot 5$, $8 = 2\cdot 2\cdot 2$. (Denna +funktion är sannolikt enklast att skriva som en rekursiv funktion.) + +[Lösningsförslag för primtalsfaktorisering, primes.py][primes]. + +[primtal]: https://sv.wikipedia.org/wiki/Primtal +[aritfund]: https://sv.wikipedia.org/wiki/Aritmetikens_fundamentalsats +[primes]: https://github.com/dbosk/intropy/blob/master/modules/iterations/tutorial/primes.py + + +### Cowsay + +I terminalen finns alla möjliga intressanta kommandond. Ett av de lite roligare +är `cowsay`. Det funkar såhär: +``` +$ cowsay "Smaka på den här utmaningen!" + ______________________________ +< Smaka på den här utmaningen! > + ------------------------------ + \ ^__^ + \ (oo)\_______ + (__)\ )\/\ + ||----w | + || || +``` +Skriv en funktion som åstadkommer samma sak som `cowsay`. [Lösningsförslag cowsay.py][cowsay]. + +[cowsay]: https://github.com/dbosk/intropy/blob/master/modules/iterations/tutorial/cowsay.py diff --git a/modules/iterations/tutorial/fib.py b/modules/iterations/tutorial/fib.py new file mode 100644 index 00000000..dc7864a1 --- /dev/null +++ b/modules/iterations/tutorial/fib.py @@ -0,0 +1,13 @@ +# Author: Celina Soori +# Python program to display the Fibonacci sequence + +def fibo(n): + if n <= 1: + return n + else: + return(fibo(n-1) + fibo(n-2)) + + +n = 10 +for i in range(nt): + print(fibo(i)) diff --git a/modules/iterations/tutorial/instruction.md b/modules/iterations/tutorial/instruction.md index c69ad0dd..059021be 100644 --- a/modules/iterations/tutorial/instruction.md +++ b/modules/iterations/tutorial/instruction.md @@ -2,126 +2,69 @@ title: Övning om upprepningar authors: - Daniel Bosk + - Celina Soori --- -# Övning: upprepningar +# Övning: upprepningar, listor och moduler -Målet med övningen är att du ska blir bättre på att +Målet med övningen är att du ska bli bättre på att - - tillämpa olika former av upprepningar: rekursion, for- och + - tillämpa olika former av upprepningar: rekursion, for- och while-iterationer, + - iterera genom och lägga till element i en lista, - konstruera interaktiva program, - dela upp problem i mindre problem, - minimera kodupprepning, - leta i Pythons dokumentation. +## Genomgång av veckans svårigheter -## Laborationen +Vi går igenom det vi upptäckt i OLI är extra svårt den här veckan. -Hur har olika grupper löst samma labb? Oftast väldigt olika. Vi går igenom -några lösningar. Hur löser man extrauppgiften? +Zoomlänk: +## Önskemål från gruppen -## Frågesport - -Skriv ett frågeprogram med kluriga frågor. Enklare frågor ska ha ett begränsat -antal försök, medan svårare frågor ska tillåta oändligt antal försök. Vi vill -också att användaren ska mata in korrekt, exempelvis om användaren skriver -"tre" istället för "3" ber vi användaren att skriva in igen. (Ska detta räknas -som ett försök? Kanske, det får ni avgöra själva.) - - -## Bombspelet 2.0 - -Vi har förbättrat vårt frågespel Bomben till Bomben 2.0. Svarar man fel -detoneras fortfarande bomben, men klurigheterna är uppgraderade. - -Det behövs fortfarande två filer: [bomben2.py][bomben2] och [bomb.py][bomb] -(samma som förra gången). Båda måste ligga i samma katalog. Därefter kör man -bomben2.py: `python3 bomben2.py`. - -[bomben2]: https://github.com/dbosk/intropy/blob/master/modules/iterations/tutorial/bomben2.py -[bomb]: https://github.com/dbosk/intropy/blob/master/modules/conditionals/bomb.py - - -## Fakultet - -Skriv ett program som beräknar n-fakultet, d.v.s. $n! = n\cdot (n-1) \cdots 3 -\cdot 2 \cdot 1$. Skriv tre funktioner som löser problemet: en som använder -rekursion, en som använder for och en som använder while. (Detta är ett -typexempel som enklast löses med rekursion.) - - -## Multiplikationshjälpmedel - -**Multiplikationstabellen** Låt användaren ange vilken multiplikationstabell -hen vill se och skriv ut den. Exempelvis 7:ans multiplikationstabell: -``` -Vilken multiplikationstabell vill du se? 7 - - 7 | 7 14 21 28 35 42 49 56 63 70 -``` - -**Multiplikationstabeller** Låt användaren ange vilket maxtal som ska anges i -multiplikationstabellerna. Skriv sedan ut dem. Exempelvis alla -multiplikationstabeller upp till 7: -``` -Vilket är det högsta tal du vill multiplicera? 7 +Var det något särskilt från veckans föreläsning och/eller OLI-material som gruppen vill gå igenom igen? - * | 1 2 3 4 5 6 7 ----+--------------------- - 1 | 1 2 3 4 5 6 7 - 2 | 2 4 6 8 10 12 14 - 3 | 3 6 9 12 15 18 21 - 4 | 4 8 12 16 20 24 28 - 5 | 5 10 15 20 25 30 35 - 6 | 6 12 18 24 30 36 42 - 7 | 7 14 21 28 35 42 49 -``` +Gick förra veckans laboration bra? Finns det något ni skulle vilja gå igenom från laborationen? -Ett lösningsförslag (för båda) finns i [multtable.py][multtable]. +## Övningsuppgifter -[multtable]: https://github.com/dbosk/intropy/blob/master/modules/iterations/tutorial/multtable.py +### Finn fem fel +Programmet [Fibonacci sekvenser](https://github.com/dbosk/intropy/blob/revision_of_exercises/modules/iterations/tutorial/fib.py) +skriver ut en [fibonacci sekvens](https://sv.wikipedia.org/wiki/Fibonaccital). -## Primtalsfaktorisering +Läs igenom koden och få ett hum om vad den är tänkt att göra. Testa att köra koden. -Ett [primtal][primtal] är ett tal som endast är delbart med 1 och sig självt, -exempelvis 2, 3, 5, 7, 11 och 13. [Aritmetikens fundamentalsats][aritfund] -säger att "varje heltal större än 1 kan skrivas som en produkt av primtal på -ett och endast ett sätt" (primtalsfaktorerna är sorterade, $2\cdot 3$ och -$3\cdot 2$ räknas som samma). +Hitta nu tillsammans minst fem fel/utvecklingsområden i koden (tänk på vad ni lärt er under veckan). -Skriv en funktion som tar ett heltal och returnerar en sträng med dess -primtalsfaktorer. Exempelvis: $15 = 3\cdot 5$, $8 = 2\cdot 2\cdot 2$. (Denna -funktion är sannolikt enklast att skriva som en rekursiv funktion.) +Förbättra nu koden efter det ni hittat. Blev koden mer lättläst, användbar och/eller användarvänlig? Varför? -[Lösningsförslag för primtalsfaktorisering, primes.py][primes]. +### Frågesport -[primtal]: https://sv.wikipedia.org/wiki/Primtal -[aritfund]: https://sv.wikipedia.org/wiki/Aritmetikens_fundamentalsats -[primes]: https://github.com/dbosk/intropy/blob/master/modules/iterations/tutorial/primes.py +Utveckla ditt frågeprogram från förra veckans övning. Enklare frågor ska ha ett begränsat +antal försök, medan svårare frågor ska tillåta oändligt antal försök. Vi vill +också att användaren ska mata in korrekt, exempelvis om användaren skriver +"tre" istället för "3" ber vi användaren att skriva in igen. (Ska detta räknas +som ett försök? Kanske, det får ni avgöra själva.) +Lägg alla frågor i en lista och testa att använda while och for för att iterera genom listan. +Vad fungerar bäst? -## Cowsay +Lägg till en meny för frågesporten och låt användaren köra programmet oändligt många gånger. +Testa att använda for, while och rekursion för att upprepa programmet. Vad fungerar bäst? -I terminalen finns alla möjliga intressanta kommandond. Ett av de lite roligare -är `cowsay`. Det funkar såhär: -``` -$ cowsay "Smaka på den här utmaningen!" - ______________________________ -< Smaka på den här utmaningen! > - ------------------------------ - \ ^__^ - \ (oo)\_______ - (__)\ )\/\ - ||----w | - || || -``` -Skriv en funktion som åstadkommer samma sak som `cowsay`. [Lösningsförslag cowsay.py][cowsay]. +Lägg till ett menyval där användaren får lägga till en fråga. -[cowsay]: https://github.com/dbosk/intropy/blob/master/modules/iterations/tutorial/cowsay.py +### Bombspelet 2.0 +Vi har förbättrat vårt frågespel Bomben till Bomben 2.0. Svarar man fel +detoneras fortfarande bomben, men klurigheterna är uppgraderade. -## Önskemål från gruppen +Det behövs fortfarande två filer: [bomben2.py][bomben2] och [bomb.py][bomb] +(samma som förra gången). Båda måste ligga i samma katalog. Därefter kör man +bomben2.py: `python3 bomben2.py`. -Vad vill gruppen gå igenom igen från veckan som var? +[bomben2]: https://github.com/dbosk/intropy/blob/master/modules/iterations/tutorial/bomben2.py +[bomb]: https://github.com/dbosk/intropy/blob/master/modules/conditionals/bomb.py diff --git a/modules/overview/slides/contents.tex b/modules/overview/slides/contents.tex index ecddea09..13bd7d2b 100644 --- a/modules/overview/slides/contents.tex +++ b/modules/overview/slides/contents.tex @@ -40,41 +40,42 @@ \subsection{Lärare} \begin{frame} \begin{block}{Fler lärare på kursen} \begin{itemize} + \item Olle \item Övningsledare \item Labbhandledare \end{itemize} \end{block} \end{frame} -\subsection{Studenter} - -\begin{frame} - \begin{exercise}[Vad har ni för intressen?] - \begin{itemize} - \item \url{https://menti.com} - \end{itemize} - \end{exercise} -\end{frame} - -\begin{frame} - \begin{exercise}[Vilka är ni?] - \begin{itemize} - \item Break-out rooms: tre personer i varje. - \item Vart kommer ni från? - \item Varför kom ni hit? - \item Vart är ni på väg? - \end{itemize} - \end{exercise} -\end{frame} - +%\subsection{Studenter} +% +%\begin{frame} +% \begin{exercise}[Vad har ni för intressen?] +% \begin{itemize} +% \item \url{https://menti.com} +% \end{itemize} +% \end{exercise} +%\end{frame} +% +%\begin{frame} +% \begin{exercise}[Vilka är ni?] +% \begin{itemize} +% \item Break-out rooms: tre personer i varje. +% \item Vart kommer ni från? +% \item Varför kom ni hit? +% \item Vart är ni på väg? +% \end{itemize} +% \end{exercise} +%\end{frame} -\section{Varför ska ni läsa programmering?} -\begin{frame} - \begin{center} - Varför ska ni lära er att programmera? - \end{center} -\end{frame} +%\section{Varför ska ni läsa programmering?} +% +%\begin{frame} +% \begin{center} +% Varför ska ni lära er att programmera? +% \end{center} +%\end{frame} \section{Om kursen} @@ -110,10 +111,9 @@ \subsection{Hur ska ni få ut detta?} \begin{block}{Moduler} \begin{enumerate} \item Förberedelse - \item Föreläsning - \item Laboration - \item Föreläsning \item Övning + \item Laboration + \item Fördjupande övning \end{enumerate} \end{block} @@ -136,12 +136,13 @@ \subsection{Hur ska ni få ut detta?} \end{block} \pause - - \begin{block}{\enquote{Föreläsningar}} + + \begin{block}{Övningar} \begin{itemize} - \item Ger en översiktlig genomgång. - \item Fokuserar på de viktigaste delarna. + \item Genomgång av problemen som uppdagades under förberedelsen. \item Får information från interaktionen under era förberedelser. + \item Fokuserar på de viktigaste delarna. + \item Interaktiva tillfällen för lärande. \item Praktisk problemlösning för er! \end{itemize} \end{block} @@ -150,8 +151,10 @@ \subsection{Hur ska ni få ut detta?} \begin{frame} \begin{block}{Laborationer} \begin{itemize} - \item Driver ert lärande framåt. - \item Lärande är socialt, arbeta i grupper om två. + \item Ger återkoppling på ert kodande. + \item Lärande är socialt, arbeta i grupper (max tre/grupp). + \item Labbarna 1--2, 4--5 kamraträttas (peer review). + \item Labbarna 3, 6 presenteras för assistent (examinerande). \end{itemize} \end{block} @@ -162,34 +165,44 @@ \subsection{Hur ska ni få ut detta?} \item Skapa studiegrupper! \end{itemize} \end{remark} +\end{frame} - \pause - - \begin{block}{Övningar} +\begin{frame} + \begin{remark} \begin{itemize} - \item Interaktiva tillfällen för lärande. - \item Bygger vidare på laborationerna. + \item Alla tillfällen ges både online och på campus! \end{itemize} - \end{block} + \end{remark} \end{frame} \begin{frame} - \begin{exercise}[Hur studerar ni?] + \begin{block}{Fördjupande övningar} \begin{itemize} - \item Break-out rooms: tre nya personer i varje. - \item Hur har du studerat bäst hittills? Vad är din studieteknik? + \item Interaktiva tillfällen för lärande. + \item Fördjupande innehåll. + \item Lämpligt för dem som har lätt för programmering. + \item Ges endast online, men med salar på campus. \end{itemize} - \end{exercise} + \end{block} \end{frame} +%\begin{frame} +% \begin{exercise}[Hur studerar ni?] +% \begin{itemize} +% \item Break-out rooms: tre nya personer i varje. +% \item Hur har du studerat bäst hittills? Vad är din studieteknik? +% \end{itemize} +% \end{exercise} +%\end{frame} + \subsection{Hur kollar vi att ni kan?} \begin{frame} \begin{block}<+>{Laborationer (LAB1, 1.5 hp)} \begin{itemize} - \item Lämnas in i Canvas. - \item Måste även delta i övningen. - \item \emph{Man får misslyckas}, bara att fixa och lämna in igen! + \item Lämnas in i Canvas och presenteras muntligen (labb 3, 6). + \item \emph{Man får misslyckas}, bara att fixa, lämna in och presentera + igen! \item Första halvan av kursen. \end{itemize} \end{block} @@ -198,7 +211,7 @@ \subsection{Hur kollar vi att ni kan?} \begin{itemize} \item Testar era kunskaper efter att vi täckt allt material. \item Mitten av kursen. - \item Ges en gång i månaden så länge det finns behov. + \item Ges var fjärde fredag kl 15 så länge det finns behov. \end{itemize} \end{block} \end{frame} diff --git a/modules/overview/slides/preamble.tex b/modules/overview/slides/preamble.tex index e2a8ccb2..2ec6312e 100644 --- a/modules/overview/slides/preamble.tex +++ b/modules/overview/slides/preamble.tex @@ -3,6 +3,9 @@ \usepackage[swedish]{babel} \usepackage{booktabs} +\usepackage[natbib,style=alphabetic,maxbibnames=99]{biblatex} +\addbibresource{disciplinary.bib} + \usepackage[all]{foreign} \renewcommand{\foreignfullfont}{} \renewcommand{\foreignabbrfont}{} @@ -13,9 +16,6 @@ \usepackage[strict]{csquotes} \usepackage[single]{acro} -\usepackage[natbib,style=alphabetic,maxbibnames=99]{biblatex} -\addbibresource{disciplinary.bib} - \usepackage{subcaption} \usepackage[noend]{algpseudocode} diff --git a/modules/overview/slides/slides.tex b/modules/overview/slides/slides.tex index d7beb5f0..692a8dd9 100644 --- a/modules/overview/slides/slides.tex +++ b/modules/overview/slides/slides.tex @@ -102,7 +102,7 @@ % %%% REFERENCES %%% -\begin{frame}[allowframebreaks] - \printbibliography -\end{frame} +%\begin{frame}[allowframebreaks] +% \printbibliography +%\end{frame} \end{document} diff --git a/modules/packages/slides/.gitignore b/modules/packages/slides/.gitignore new file mode 100644 index 00000000..aaae5fd9 --- /dev/null +++ b/modules/packages/slides/.gitignore @@ -0,0 +1,3 @@ +notes.pdf +slides.pdf + diff --git a/modules/packages/slides/Makefile b/modules/packages/slides/Makefile new file mode 100644 index 00000000..92e2aada --- /dev/null +++ b/modules/packages/slides/Makefile @@ -0,0 +1,28 @@ +LATEXFLAGS+= -shell-escape +TEX_PYTHONTEX= yes + +.PHONY: all +all: notes.pdf slides.pdf + +SRC+= preamble.tex +SRC+= abstract.tex contents.tex + +SRC+= examples/bad_module.py +SRc+= examples/good_module.py +SRC+= examples/test_good_bad.py +SRC+= examples/input_type.py + +notes.pdf: notes.tex +notes.pdf: ${SRC} + +slides.pdf: slides.tex +slides.pdf: ${SRC} + + +.PHONY: clean +clean: + ${RM} notes.pdf slides.pdf + + +INCLUDE_MAKEFILES=../../../makefiles +include ${INCLUDE_MAKEFILES}/tex.mk diff --git a/modules/packages/slides/README.md b/modules/packages/slides/README.md new file mode 100644 index 00000000..23dc2a01 --- /dev/null +++ b/modules/packages/slides/README.md @@ -0,0 +1,5 @@ +- [YouTube: Moduler och paket][yt] +- [FeedbackFruits: Moduler och paket][fbf] + +[yt]: https://youtu.be/D_iTcOGDncY +[fbf]: https://eu.feedbackfruits.com/courses/activity-course/2095dba0-14b0-4d3b-a562-8bf2ac2ecb62 diff --git a/modules/packages/slides/abstract.tex b/modules/packages/slides/abstract.tex new file mode 100644 index 00000000..4012d9d3 --- /dev/null +++ b/modules/packages/slides/abstract.tex @@ -0,0 +1,22 @@ +% What's the problem? +% Why is it a problem? Research gap left by other approaches? +% Why is it important? Why care? +% What's the approach? How to solve the problem? +% What's the findings? How was it evaluated, what are the results, limitations, +% what remains to be done? + +% XXX Summary +\emph{Summary:} +\dots + +% XXX Motivation and intended learning outcomes +\emph{Intended learning outcomes:} +\dots + +% XXX Prerequisites +\emph{Prerequisites:} +\dots + +% XXX Reading material +\emph{Reading:} +\dots diff --git a/modules/packages/slides/contents.tex b/modules/packages/slides/contents.tex new file mode 100644 index 00000000..cd8b33fb --- /dev/null +++ b/modules/packages/slides/contents.tex @@ -0,0 +1,92 @@ +\mode* + +\section{Moduler} + +\begin{frame}[fragile] + \mintinline[fontsize=\huge]{python}|import module| +\end{frame} + +\subsection{Hur?} + +\begin{frame}[fragile] + \begin{example}[good\textunderscore{}module.py] + \inputminted[firstline=3,highlightlines=7]{python}{examples/good_module.py} + \end{example} + + \begin{example}[bad\textunderscore{}module.py] + \inputminted[firstline=3]{python}{examples/bad_module.py} + \end{example} +\end{frame} + + +\subsection{Varför?} + +%\begin{frame}[fragile] +% \begin{example}[input\textunderscore{}type.py, del 1] +% \inputminted[firstline=14]{python}{examples/input_type.py} +% \end{example} +%\end{frame} + +\begin{frame}[fragile] + \begin{example}[input\textunderscore{}type.py] + \inputminted[firstline=1,lastline=13]{python}{examples/input_type.py} + \end{example} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[Använda modulen] + \begin{minted}{python} +import input_type +x = input_type.input_type(int, "x = ") +print(f"x = {x}") + \end{minted} + \end{example} + + \begin{example}[Använda modulen] + \begin{minted}{python} +import input_type as it +x = it.input_type(int, "x = ") +print(f"x = {x}") + \end{minted} + \end{example} + + \begin{example}[Använda modulen] + \begin{minted}{python} +from input_type import input_type +x = input_type(int, "x = ") +print(f"x = {x}") + \end{minted} + \end{example} +\end{frame} + + +\section{PyPI: Python Package Index} + +\begin{frame} + \includegraphics[width=\columnwidth]{figs/pypi.png} +\end{frame} + +\begin{frame} + \includegraphics[width=\columnwidth]{figs/pypi-scipy.png} +\end{frame} + +\begin{frame} + \includegraphics[width=\columnwidth]{figs/pypi-matplotlib.png} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[Installation] + \begin{minted}{bash} +$ python3 -m pip install numpy scipy matplotlib sympy + \end{minted} + \end{example} + + \begin{example} + \inputminted[lastline=9]{python}{examples/symalg.py} + \end{example} +\end{frame} + +\begin{frame} + \includegraphics[width=\columnwidth]{figs/pypi-torch.png} +\end{frame} + diff --git a/modules/packages/slides/examples/bad_module.py b/modules/packages/slides/examples/bad_module.py new file mode 100644 index 00000000..3a2f0036 --- /dev/null +++ b/modules/packages/slides/examples/bad_module.py @@ -0,0 +1,7 @@ +"""This is a bad module""" + +def hello_world(): + """Prints 'Hello, world!'""" + print("Hello, world!") + +hello_world() diff --git a/modules/packages/slides/examples/good_module.py b/modules/packages/slides/examples/good_module.py new file mode 100644 index 00000000..f9af3fdb --- /dev/null +++ b/modules/packages/slides/examples/good_module.py @@ -0,0 +1,8 @@ +"""This is a good module""" + +def hello_world(): + """Prints 'Hello, world!!!!!!'""" + print("Hello, world!!!!!!!!!!") + +if __name__ == "__main__": + hello_world() diff --git a/modules/packages/slides/examples/input_type.py b/modules/packages/slides/examples/input_type.py new file mode 100644 index 00000000..9884ee14 --- /dev/null +++ b/modules/packages/slides/examples/input_type.py @@ -0,0 +1,34 @@ +"""Take input more easily.""" + +def input_type(the_type, prompt=""): + """Take input, convert to type the_type; repeat if error.""" + while True: + try: + return the_type(input(prompt)) + except ValueError: + if the_type == int: + print(f"Sorry, can't convert to integer.") + else: + print(f"Sorry, can't convert to {the_type}.") + +def input_int(prompt="") + """Läser in ett heltal; fortsätter att fråga prompt till användaren tills att användaren matat in något som går att konvertera till ett heltal""" + while True: + try: + return int(input(prompt)) + except ValueError: + print("Inte heltal, försök igen.") + +def main(): + """Test functionality of this module""" + x = input_type(int, "x = ") + y = input_type(int, "y = ") + z = input_type(float, "z = ") + name = input_type(str, "Your name: ") + + print(f"{x} + {y} = {x+y}") + print(f"z = {z}") + print(f"Your name is {name}") + +if __name__ == "__main__": + main() diff --git a/modules/packages/slides/examples/symalg.py b/modules/packages/slides/examples/symalg.py new file mode 100644 index 00000000..7755ede8 --- /dev/null +++ b/modules/packages/slides/examples/symalg.py @@ -0,0 +1,16 @@ +import sympy + +x = sympy.symbols("x") + +expr = x**2 - 4 +print(f"expr = {expr}") + +print(f"factorization: {expr} = {sympy.factor(expr)}") +print(f"solve: {expr} = 0 har rötterna {sympy.solve(expr, x)}") + +print() +print(f"({expr})*{x} = {expr*x}") +expr *= x + +print(f"factorization: {expr} = {sympy.factor(expr)}") +print(f"solve: {expr} = 0 har rötterna {sympy.solve(expr, x)}") diff --git a/modules/packages/slides/figs/pypi-matplotlib.png b/modules/packages/slides/figs/pypi-matplotlib.png new file mode 100644 index 00000000..db8be456 Binary files /dev/null and b/modules/packages/slides/figs/pypi-matplotlib.png differ diff --git a/modules/packages/slides/figs/pypi-scipy.png b/modules/packages/slides/figs/pypi-scipy.png new file mode 100644 index 00000000..a5f6f6cf Binary files /dev/null and b/modules/packages/slides/figs/pypi-scipy.png differ diff --git a/modules/packages/slides/figs/pypi-torch.png b/modules/packages/slides/figs/pypi-torch.png new file mode 100644 index 00000000..93ac3526 Binary files /dev/null and b/modules/packages/slides/figs/pypi-torch.png differ diff --git a/modules/packages/slides/figs/pypi.png b/modules/packages/slides/figs/pypi.png new file mode 100644 index 00000000..e760199f Binary files /dev/null and b/modules/packages/slides/figs/pypi.png differ diff --git a/modules/packages/slides/figs/pytorch-install.png b/modules/packages/slides/figs/pytorch-install.png new file mode 100644 index 00000000..cb7401ce Binary files /dev/null and b/modules/packages/slides/figs/pytorch-install.png differ diff --git a/modules/packages/slides/figs/pytorch.png b/modules/packages/slides/figs/pytorch.png new file mode 100644 index 00000000..b0cd9fd2 Binary files /dev/null and b/modules/packages/slides/figs/pytorch.png differ diff --git a/modules/packages/slides/notes.tex b/modules/packages/slides/notes.tex new file mode 100644 index 00000000..04db2256 --- /dev/null +++ b/modules/packages/slides/notes.tex @@ -0,0 +1,45 @@ +\documentclass{article} + +\usepackage[hyphens]{url} +\usepackage[hidelinks]{hyperref} + +\input{preamble.tex} + +\usepackage[noamsthm,notheorems]{beamerarticle} +\setjobnamebeamerversion{slides} + +%\usepackage{authblk} +%\let\institute\affil + +\declaretheorem[numbered=unless unique,style=theorem]{theorem} +\declaretheorem[numbered=unless unique,style=definition]{definition} +\declaretheorem[numbered=unless unique,style=definition]{assumption} +\declaretheorem[numbered=unless unique,style=definition]{protocol} +\declaretheorem[numbered=unless unique,style=example]{example} +%\declaretheorem[style=definition,numbered=unless unique, +% name=Example,refname={example,examples}]{example} +\declaretheorem[numbered=unless unique,style=remark]{remark} +\declaretheorem[numbered=unless unique,style=remark]{idea} +\declaretheorem[numbered=unless unique,style=exercise]{exercise} +\declaretheorem[numbered=unless unique,style=exercise]{question} +\declaretheorem[numbered=unless unique,style=solution]{solution} + +\begin{document} +\title{% + Moduler och paket +} +\author{Daniel Bosk} +\institute{% + KTH EECS +} + +\maketitle + +\begin{abstract} + \input{abstract.tex} +\end{abstract} + +\input{contents.tex} + +\printbibliography +\end{document} diff --git a/modules/packages/slides/preamble.tex b/modules/packages/slides/preamble.tex new file mode 100644 index 00000000..24c24849 --- /dev/null +++ b/modules/packages/slides/preamble.tex @@ -0,0 +1,43 @@ +\usepackage[utf8]{inputenc} +\usepackage[T1]{fontenc} +\usepackage[swedish]{babel} +\usepackage{booktabs} + +\usepackage[natbib,style=alphabetic,maxbibnames=99]{biblatex} +\addbibresource{slides.bib} + +\usepackage[all]{foreign} +\renewcommand{\foreignfullfont}{} +\renewcommand{\foreignabbrfont}{} + +\usepackage{newclude} +\usepackage{import} + +\usepackage[strict]{csquotes} +\usepackage[single]{acro} + +\usepackage{subcaption} + +\usepackage[noend]{algpseudocode} +\usepackage{xparse} + +\let\email\texttt + +\usepackage[outputdir=ltxobj]{minted} +\setminted{autogobble,fontsize=\footnotesize} + +\usepackage{pythontex} +\setpythontexoutputdir{.} +\setpythontexworkingdir{..} + +\usepackage{amsmath} +\usepackage{amssymb} +\usepackage{mathtools} +\usepackage{amsthm} +\usepackage{thmtools} +\usepackage[unq]{unique} +\DeclareMathOperator{\powerset}{\mathcal{P}} + +\usepackage[binary-units]{siunitx} + +\usepackage[capitalize]{cleveref} diff --git a/modules/packages/slides/slides.tex b/modules/packages/slides/slides.tex new file mode 100644 index 00000000..2a6f0452 --- /dev/null +++ b/modules/packages/slides/slides.tex @@ -0,0 +1,118 @@ +\documentclass[ignoreframetext]{beamer} +\input{preamble.tex} + +\usetheme{Berlin} +\setbeamertemplate{footline}%{miniframes theme} +{% + \begin{beamercolorbox}[colsep=1.5pt]{upper separation line foot} + \end{beamercolorbox} + \begin{beamercolorbox}[ht=2.5ex,dp=1.125ex,% + leftskip=.3cm,rightskip=.3cm plus1fil]{author in head/foot}% + \leavevmode{\usebeamerfont{author in head/foot}\insertshortauthor}% + \hfill% + {\usebeamerfont{institute in head/foot}\usebeamercolor[fg]{institute in head/foot}\insertshortinstitute}% + \end{beamercolorbox}% + \begin{beamercolorbox}[ht=2.5ex,dp=1.125ex,% + leftskip=.3cm,rightskip=.3cm plus1fil]{title in head/foot}% + {\usebeamerfont{title in head/foot}\insertshorttitle} \hfill \insertframenumber% + \end{beamercolorbox}% + \begin{beamercolorbox}[colsep=1.5pt]{lower separation line foot} + \end{beamercolorbox} +} +\setbeamercovered{transparent} +\setbeamertemplate{bibliography item}[text] + +\AtBeginSection[]{% + \begin{frame} + \tableofcontents[currentsection] + \end{frame} +} + +\ProvideDocumentEnvironment{assumption}{o}{% + \IfValueTF{#1}{% + \begin{block}{Assumption: #1} + }{% + \begin{block}{Assumption} + } +}{% + \end{block} +} + +\ProvideDocumentEnvironment{protocol}{o}{% + \IfValueTF{#1}{% + \begin{block}{Protocol: #1} + }{% + \begin{block}{Protocol} + } +}{% + \end{block} +} + +\ProvideDocumentEnvironment{remark}{o}{% + \IfValueTF{#1}{% + \begin{alertblock}{Note: #1} + }{% + \begin{alertblock}{Note} + } +}{% + \end{alertblock} +} + +\ProvideDocumentEnvironment{idea}{o}{% + \IfValueTF{#1}{% + \begin{block}{Idea: #1} + }{% + \begin{block}{Idea} + } +}{% + \end{block} +} + +\ProvideDocumentEnvironment{question}{o}{% + \setbeamercolor{block body}{bg=orange!15,fg=black} + \setbeamercolor{block title}{bg=orange,fg=white} + \setbeamercolor{local structure}{fg=orange} + \IfValueTF{#1}{% + \begin{block}{Question: #1} + }{% + \begin{block}{Question} + } +}{% + \end{block} +} + +\ProvideDocumentEnvironment{exercise}{o}{% + \setbeamercolor{block body}{bg=yellow!10,fg=black} + \setbeamercolor{block title}{bg=yellow,fg=black} + \setbeamercolor{local structure}{fg=yellow} + \IfValueTF{#1}{% + \begin{block}{Exercise: #1} + }{% + \begin{block}{Exercise} + } +}{% + \end{block} +} + + +\begin{document} +\title{% + Moduler och paket +} +\author{Daniel Bosk} +\institute{% + KTH EECS +} + +\begin{frame} + \maketitle +\end{frame} + +\mode +\input{contents.tex} +\mode* + +%\begin{frame}[allowframebreaks] +% \printbibliography +%\end{frame} +\end{document} diff --git a/modules/project/Makefile b/modules/project/Makefile index 43c1744d..548f294b 100644 --- a/modules/project/Makefile +++ b/modules/project/Makefile @@ -1,4 +1,7 @@ .PHONY: all -all: present.html review.html spec.html +all: present.html review.html spec.html granskningsprotokoll.md + +granskningsprotokoll.md: granskningsprotokoll.odt + pandoc $< -o $@ include ../../html.mk diff --git a/modules/project/admin/grade.sh b/modules/project/admin/grade.sh new file mode 100755 index 00000000..b15e3526 --- /dev/null +++ b/modules/project/admin/grade.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +COURSE="prg[im]2[2-9]" +ASSIGNM="Välj p-uppgift" +HANDINS="/tmp/prgim2x.puppg.handedin" +#HANDINS=$(mktemp) + +get_row() { + egrep "[^a-z]$1" $2 +} + +grade() { + course="$(get_row $1 $HANDINS | cut -f 1)" + echo "$course" "$1" + canvaslms grade -c "$course" -a "$ASSIGNM" -u "$1" -g 'complete' +} + +to_grade() { + cat $HANDINS +} + +grade_all() { + for student in $(cut -f 3 $HANDINS); do + grade $student + done + rm -Rf $HANDINS +} + +update() { + canvaslms submissions -lc "$COURSE" -a "$ASSIGNM" | \ + egrep "[0-9]{4}-[0-9]{2}-[0-9]{2}" | grep -v "complete" > $HANDINS +} + +test -e $HANDINS || update + +$* diff --git a/modules/project/exempelspec.pdf b/modules/project/exempelspec.pdf new file mode 100644 index 00000000..e97fdbeb Binary files /dev/null and b/modules/project/exempelspec.pdf differ diff --git a/modules/project/granskningsprotokoll.md b/modules/project/granskningsprotokoll.md new file mode 100644 index 00000000..8a3fdd43 --- /dev/null +++ b/modules/project/granskningsprotokoll.md @@ -0,0 +1,395 @@ +Granskningsprotokoll + +**Granskning av:** «Fyll i ditt namn» + +**Utvecklare:** «Fyll i utvecklarens namn (den student som har +implementerat P-Uppgiften)» + +**Datum:** «Fyll i datum» + +Mer detaljerad information om kraven som ställs i granskningsprotokollet +finner du i slutet av dokumentet under rubriken [Information om +granskningen](#anchor) på sidan [4](#anchor). + +Användarvänlighet +================= + +1. Informativa utskrifter («"Ja" eller "Nej"») +---------------------------------------------- + +«Fyll i din motivering till ditt svar här» + +«Exempel (om "Ja"): Programmets gränssnitt är tillräckligt tydligt för +att en användare utan tidigare förkunskaper om P-uppgiften kan förstå +vad det handlar om och vad som händer i programmet.» + +«Exempel (om "Nej"): Det första man ser när man startar programmet är +att det frågas om ett tal, det är otydligt vad programmet gör och vad +talet är till för.» + +2. Enkel inmatning («"Ja" eller "Nej"») +--------------------------------------- + +«Fyll i din motivering till ditt svar här» + +«Exempel (om "Ja"): Det är enkelt att använda programmet p.g.a. att +frågorna som ställs till användaren alltid är tydliga. Vi vet att det är +ett Memory program utifrån tidigare utskrifter, och vi vet därför vad +frågan "Vilken storlek på spelet vill du ha \[t.ex. 5\]?" innebär.» + +«Exempel (om "Nej"): Det är otydligt för användaren vad som ska matas +in. Speciellt på menyn där ingen numrering finns för alternativen.» + +Programmerarvänlighet +===================== + +3. Vettiga namn («"Ja" eller "Nej"») +------------------------------------ + +«Fyll i din motivering till ditt svar här» + +4. Kommentarer («"Ja" eller "Nej"») +----------------------------------- + +«Fyll i din motivering till ditt svar här» + +5. Konsekvent språk («"Ja" eller "Nej"») +---------------------------------------- + +«Fyll i din motivering till ditt svar här» + +6. Konsekvent typografi («"Ja" eller "Nej"») +-------------------------------------------- + +«Fyll i din motivering till ditt svar här» + +Strukturering +============= + +7. Lämplig uppdelning i funktioner («"Ja" eller "Nej"») +------------------------------------------------------- + +«Fyll i din motivering till ditt svar här» + +8. Lämplig uppdelning i klasser/moduler («"Ja" eller "Nej"») +------------------------------------------------------------ + +«Fyll i din motivering till ditt svar här» + +9. Temporära variabler så lokalt som möjligt («"Ja" eller "Nej"») +----------------------------------------------------------------- + +«Fyll i din motivering till ditt svar här» + +10. Återanvändbara funktioner/moduler/klasser («"Ja" eller "Nej"») +------------------------------------------------------------------ + +«Fyll i din motivering till ditt svar här» + +11. In- och utdata till funktioner («"Ja" eller "Nej"») +------------------------------------------------------- + +«Fyll i din motivering till ditt svar här» + +12. Flexibelt/utbyggbart program («"Ja" eller "Nej"») +----------------------------------------------------- + +«Fyll i din motivering till ditt svar här» + +13. Ingen kodupprepning («"Ja" eller "Nej"») +-------------------------------------------- + +«Fyll i din motivering till ditt svar här» + +14. Ingen hårdkodning («"Ja" eller "Nej"») +------------------------------------------ + +«Fyll i din motivering till ditt svar här» + +Obligatoriskt +============= + +15. Uppfyller kraven i lydelsen («"Ja" eller "Nej"») +---------------------------------------------------- + +«Fyll i din motivering till ditt svar här» + +Omdöme +====== + +Projektet anses vara godkänt om alla krav under "Obligatoriskt" är +uppfyllda och att inte fler än *två* krav under "Användarvänlighet", +"Programmerarvänlighet" och "Strukturering" är ouppfyllda. + +**Godkänt: «"Ja" eller "Nej"»** + +[]{#anchor}Information om granskningen +====================================== + +Nedan finner du mer detaljerad information om kraven som ställs i +granskningsprotokollet. + +1. Informativa utskrifter +------------------------- + +Programmet ska tala om för användaren vad programmet gör i varje steg +och vilken inmatning som förväntas. Ett dåligt exempel kan se ut så här. + +*Ge tal1 : *26*\ +och tal2 : *54*\ +29 31 37 41 43 47 53* + +Man ska inte behöva titta i en manual eller ännu värre, i själva +programkoden för att förstå vad som händer. Programmet måste vara +självinstruerande. + +*Hej och välkommen till primtalsprogrammet. Programmet\ +skriver ut alla primtal i ett intervall du definierar.\ +\ +Ange undre gränsen i intervallet: *26*\ +Ange högre gränsen i intervallet: *54*\ +De primtal som finns mellan 26 och 54 är:\ +29 31 37 41 43 47 53* + +Den senare varianten är mycket lättare att förstå när man kör +programmet. + +2. Enkel inmatning +------------------ + +Inmatningen ska inte vara onödigt krånglig. + +*\...\ +Vill du boka en biljett? *ja*\ +Varifrån åker du? *Arlanda*\ +Vart ska du åka? *Kastrup*\ +Vilken månad ska du åka? *Mars*\ +Vilken dag ska du åka? *25*\ +Vill du boka returbiljett? *ja*\ +Vilken månad ska du tillbaka? *April*\ +Vilken dag ska du tillbaka? *5*\ +Det går tyvärr inget flyg den 25 mars.\ +Försök igen\ +\ +Vill du boka en biljett? *ja*\ +Varifrån åker du? *Arlanda*\ +Vart ska du åka? *Kastrup*\ +Vilken månad ska du åka? *Mars*\ +\...\ +\ +*Förutom att vara väldigt sen med att kläcka ur sig att det inte finns +något flyg den önskade resdagen så verkar det inte finnas något sätt att +boka en mängd biljetter. Att boka en klassresa med det systemet skulle +vara väldigt enerverande. + +3. Vettiga namn +--------------- + +Programmet ska ha intuitiva namn på variablerna. För den som skrivit +programmet är allt självklart, men inte för andra. + +Nedanstående programkod är ganska svår att tyda + +namn = 0 + +kalle = 0 + +while kalle \< len(pelle): + +if pelle\[kalle\] \> namn: + +namn = pelle\[kalle\] + +kalle = kalle + 1 + +Här följer samma kod med andra variabelnamn. + +max = 0 + +i = 0 + +while i \< len(lista): + +if lista\[i\] \> max: + +max = lista\[i\] + +i = i + 1 + +Man ser nu lättare vad koden gör, nämligen sparar undan det högsta +värdet i listan till variabeln max. Fortfarande är inte namnet på listan +optimalt. Vad för slags värden innehåller den? Är det löner, +skottstatistik eller vad? + +När det gäller en funktion eller metod brukar ett bra namn oftast vara +ett verb som beskriver vad den gör eller vad den returnerar. Booleska +funktioner (som returnerar True/False) bör ha ett namn som talar om hur +läget är det fall den returnerar True, t ex *korrekt()* för en funktion +som kontrollerar om ett värde är korrekt. + +Namnet på en klass kan vara ett substantiv som beskriver vad objektet +representerar. Variabler och attribut är också substantiv. Att komma på +bra namn kräver en del arbete! + +4. Kommentarer +-------------- + +Alla klasser och funktioner måste kommenteras. Syftet med +klassen/funktionen ska framgå. Det ska räcka att läsa kommentaren för +att förstå hur en funktion ska användas (man ska inte behöva sätta sig +in i hela koden). + +In- och utdata till funktioner måste kommenteras. Det gäller både +returvärden och parametrar. Om funktionen är en metod och den ändrar +något attribut ska detta också kommenteras. + +Kommentarerna ska inte förklara hur Python fungerar. Förutsättningen är +att den som läser källkoden redan vet hur man programmerar. Kommentarer +som förklarar t ex att en if-sats gör ett val och att en slinga upprepar +något ska inte vara med vid redovisningen. Den som redovisar måste själv +veta sådant utan anteckningar. + +5. Konsekvent språk +------------------- + +Språkvalet ska vara konsekvent. Alla variabel-, klass- och funktionsnamn +på ett språk. Alla kommentarer på ett språk. Det är OK att ha engelska +variabel/metodnamn och kommentera på svenska. Undvik svengelska (sejva +svenska språket). + +6. Konsekvent typografi +----------------------- + +Programmet ska ha en genomgående typografi. Namn som är sammansatta av +flera ord kan t ex skrivas ihop genom att inleda varje nytt ord med stor +bokstav (t ex summeraVikter), eller genom att skilja orden åt med +understreck (t ex summera\_vikter), men använd samma variant genom hela +ditt program. Variabel- och metodnamn brukar inledas med med liten +bokstav och klasser med stor bokstav. + +class EnBraKlass + +def enMetodSomTarTreParametrar(x, y, z) + +7. Lämplig uppdelning i funktioner/metoder +------------------------------------------ + +Bäst är det med specialiserade funktioner som bara gör en sak. + +def läs\_från\_filen(): + +filnamn = input(\"Vad heter filen?\") + +with open(filnamn, \"r\") as infil: + +lista = infil.readlines() + +lista2 = \[\] + +for element in lista: + +if type(element) == type(0): + +lista2.add(element) + +return lista2 + +Koden ovan gör flera saker; frågar efter en fil, läser in alla data från +filen, stoppar in heltalen i en heltalsvektor och returnerar denna. Det +vore bättre att dela upp dessa uppgifter på flera funktioner så att +funktionsanropen blir: + +filnamn = fråga\_fil() + +fildata = läs\_från\_filen(filnamn) + +intresseanta\_tal = konvertera(fildata) + +Programmet blir då mer flexibelt: Funktionen *fråga\_fil* kan skrivas om +till ett grafiskt GUI där man klickar på rätt fil. Funktionen +*läs\_från\_filen* kan användas i andra sammanhang då man vill läsa från +fil. Man kan skicka fildatan till en ny metod som kontrollerar data +innan man anropar konvertera. + +8. Lämplig uppdelning i klasser/moduler +--------------------------------------- + +Data som hör ihop (t ex namn, födelsedata och adressuppgifter för en +person) kan samlas genom att dom får vara attribut i en klass. +Funktioner som hör ihop med dessa data får bli klassens metoder. Ett +program kan ha flera olika klasser! + +Ett riktigt stort program kan man dela upp i flera moduler, där de +klasser som hör ihop samlas i en modul. + +9. Temporära variabler så lokalt som möjligt +-------------------------------------------- + +Se till att tillfälliga variabler skapas så lokalt som möjligt. En +variabel som bara används inuti en slinga i en metod ska inte vara ett +attribut i klassen, utan en lokal variabel i metoden. + +10. Återanvändbara funktioner/klasser +------------------------------------- + +En del uppgifter kan delas upp i klasser som går att återanvända i andra +program. T ex kan en klass som representerar ett spelkort användas i +olika kortspelsprogram. + +Funktioner ska om möjligt vara skrivna så att dom går att använda i +andra sammanhang. Ett knep är att se till att alla indata ges som +parametrar. Ett annat är att specialisera funktionerna, så att varje +funktion bara gör en liten del. + +11. In- och utdata till funktioner +---------------------------------- + +Var noga med in och utdata till funktionerna. En del funktioner som +t.ex. bara skriver ut på skärmen kan vara parameterlösa och inte +returnera något. Övriga funktioner bör ha alla indata som parametrar och +utdata som returvärden. + +12. Flexibelt/utbyggbart program +-------------------------------- + +Skriv ditt program så att det lätt att utöka och bygga ut. Några +exempel: I ett program som samlar data om Pokémon ska man kunna lägga +till fler Pokémon utan att gå in och ändra i programmet. Om ett program +läser in från fil ska det vara lätt att byta till en annan fil. Om man +vill lägga till en beräkning så ska det vara enkelt att stoppa in en +funktion för det, utan att behöva ändra på många ställen i programmet. + +13. Ingen kodupprepning +----------------------- + +Ett vanligt nybörjarfel när man programmerar är att använda taktiken +klippa och klistra när samma sak ska göras på flera ställen i +programmet. Detta leder dock till kod som är väldigt svår att +underhålla. Om man ändrar på ett ställe måste man göra samma ändring på +flera parallellställen. Det går i regel att skriva om den upprepade +koden till en funktion med parametrar och returvärde. + +14. Ingen hårdkodning +--------------------- + +Förekommer talet 5 på flera ställen i programmet? Om man behöver använda +siffervärden kan dessa deklareras som konstanter. + +ANTAL\_SPELARE = 5 + +PI = 3.14 + +15. Uppfyller kraven i lydelsen +------------------------------- + +Programmet måste uppfylla kraven i P-uppgiftslydelsen. Det är inte +tillåtet att förenkla uppgiften. Den som vill göra några förändringar +måste förankra det med kursledaren först, och kunna visa en bekräftelse +(ett e-post t.ex.) på att kursledaren godkänt kravförändringar. + +Versionsinformation +=================== + +Första versionen av denna granskningsmall skrevs av Mazen Mardini, med +tillägg av Celina Soori, den 28 och 29 november 2022, baserat på ett +granskningsprotokoll med förklaringar av Alexander Baltatzis. diff --git a/modules/project/granskningsprotokoll.odt b/modules/project/granskningsprotokoll.odt new file mode 100644 index 00000000..c5fe5876 Binary files /dev/null and b/modules/project/granskningsprotokoll.odt differ diff --git a/modules/project/spec.md b/modules/project/spec.md index b68c21f4..f93ef9ba 100644 --- a/modules/project/spec.md +++ b/modules/project/spec.md @@ -10,14 +10,15 @@ Specifikationen ska innehålla följande: - Datastruktur. Vilken eller vilka datastrukturer behöver du? Oftast behöver data lagras på något sätt; i minnet (objektinstans av en klass) eller i - filer (serialiserade med CSV, JSON eller annat lämpligt format). Hur ser - din klass (dina klasser) ut (attribut och metoder)? Vilka av Pythons + filer (serialiserade med CSV, JSON eller annat lämpligt format). Vilka av Pythons inbyggda strukturer behöver du? - + + - Klass. Hur ser din klass (dina klasser) ut (attribut och metoder)? + - Funktioner. Du kan dela upp din algoritm i funktioner som med hjälp av de argument de får löser de olika delarna av algoritmen. -Den ska ge en översikt över projektet, så kvalitet är viktigare än kvantitet. +Den ska ge en översikt över projektet, så kvalitet är viktigare än kvantitet: [en exempelspecifikation](https://github.com/dbosk/intropy/blob/v2022/modules/project/exempelspec.pdf) + +**Redovisning**: Specifikationen redovisas muntligen under ett labbtillfälle, tider finns att boka på Canvas. Välj redovisning istället för hjälp i labbkön. -**Redovisning**: Specifikationen redovisas muntligen under ett labbtillfälle. -Välj redovisning istället för hjälp i labbkön. diff --git a/modules/scipy/lab/solution.py b/modules/scipy/lab/solution.py new file mode 100644 index 00000000..7fb2aedc --- /dev/null +++ b/modules/scipy/lab/solution.py @@ -0,0 +1,35 @@ +def aritmetisk_talsumma(a1, d, n): + return n * (a1 + (a1 + d * (n - 1))) / 2 + + +def geometriska_talsumma(g1, q, n): + return (g1 * ((q ** n) - 1) / (q - 1)) + +a1 = 1; d = 2; n = 3 + +print("Summan av den aritmetiska talföljden är", aritmetisk_talsumma(a1, d, n)) + +g1 = 2; q = 2; n = 4 + +print("Summan av den geometriska talföljden är ", geometriska_talsumma(g1, q, n)) + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/variables/Makefile b/modules/variables/Makefile index f3b67171..de0ff503 100644 --- a/modules/variables/Makefile +++ b/modules/variables/Makefile @@ -1,7 +1,7 @@ SUBDIR+= slides SUBDIR_GOALS= all clean distclean -HTML_FILES= lecture.html exercise.html tutorial.html +HTML_FILES= lecture.html exercise.html pythonic.html PANDOCFLAGS= --filter pandoc-xnos @@ -11,7 +11,7 @@ all: ${HTML_FILES} ${PDF_FILES} lecture.html: lecture.md exercise.html: exercise.md -tutorial.html: tutorial.md +pythonic.html: pythonic.md .PHONY: clean diff --git a/modules/variables/lab/README.md b/modules/variables/lab/README.md new file mode 100644 index 00000000..ece4b27f --- /dev/null +++ b/modules/variables/lab/README.md @@ -0,0 +1,5 @@ +- [YouTube: Videogenomgång av labben][yt] +- [FeedbackFruits: Videogenomgång av labben][fbf] + +[yt]: https://youtu.be/8cBbFMVVb5o +[fbf]: https://eu.feedbackfruits.com/courses/activity-course/3c01d16c-ac9b-48bd-9c44-d58054fe6693 diff --git a/modules/variables/lab/instruction.md b/modules/variables/lab/instruction.md index 8a320ab4..32edd2dc 100644 --- a/modules/variables/lab/instruction.md +++ b/modules/variables/lab/instruction.md @@ -1,4 +1,10 @@ -# Laboration: Variabler och utskrifter +--- +title: Laboration om Funktioner, variabler och utskrifter +authors: + - Daniel Bosk + - Celina Soori +--- +# Laboration: Funktioner, variabler och utskrifter Vi ska nu börja med att använda datorn som den räknemaskin den är. Vi ska arbeta med [aritmetiska][aritmetiska] och [geometriska][geometriska] följder. @@ -42,12 +48,60 @@ det förväntade `a*b`.) Vi kan även beräkna summan $S^g_n = g_1 + \cdots + g_n = g_1 \frac{q^n-1}{q-1}$. +## Innan du börjar koda + +Se till att du har koll på hur [parametrar][parametrar], [argument][argument] och [funktioner][funktioner] fungerar i Python. +Kom även ihåg att använda [pylint][pylint] när du kodar. + +[parametrar]: https://docs.python.org/3/glossary.html#term-parameter +[argument]: https://docs.python.org/3/glossary.html#term-argument +[funktioner]: https://docs.python.org/3/reference/compound_stmts.html#function +[pylint]: https://pypi.org/project/pylint/ ## Uppgift Skriv en funktion som beräknar summan för en aritmetisk talföljd (givet $a_1, -d, n$ returnera $S^a_n$) och en som beräknar summan för en geometrisk talföljd -(givet $g_1, q, n$ returnera $S^g_n$). +d, n$ returnera $S^a_n$) och en funktion som beräknar summan för en geometrisk +talföljd (givet $g_1, q, n$ returnera $S^g_n$). Skriv ett program som använder funktionerna. (Kontrollera att funktionerna ger korrekt resultat.) +### Exempelutskrift + +``` +Den aritmetiska summan är: 11 +Den geometriska summan är: 26 +``` + +### Krav + +* De två summa-funktionerna ska returnera summan, som sedan ska skrivas ut från + huvudprogrammet. +* Din kod ska uppfylla kraven i rättningsmatrisen. + +### Kamraträttning + +Denna laboration redovisas inte för en lärarassistent, utan kommer kamraträttas av en kurskamrat. +När du lämnat in din kod på Canvas kommer du automatiskt bli tilldelad en annan persons kod, som +du ska rätta utifrån den rättningsmatris som syns bredvid inlämningen. Ladda ner koden, provkör den +på din dator och fyll sedan i rättningsmatrisen. Lämna gärna konstruktiva kommentarer för att hjälpa +varandra att bli ännu bättre på att koda! + +## Frivillig extrauppgift + +Lägg till så att användaren måste skriva in värdena för $a_1, d, n$ samt $g_1, q, n$. +Räkna därefter ut den aritmetiska respektive geometriska summan av de värdena användaren skrivit in. + +### Exempelutskrift + +``` +Skriv in startvärdet (a1): 1 +Skriv in differensen (d): 2 +Skriv in antal element i följden (n): 3 +Den aritmetiska summan är: 9 + +Skriv in startvärdet (g1): 2 +Skriv in kvoten (q): 2 +Skriv in antal element i följden (n): 4 +Den geometriska summan är: 30 +``` diff --git a/modules/variables/lab/lab_solution.py b/modules/variables/lab/lab_solution.py new file mode 100644 index 00000000..11c3c0c1 --- /dev/null +++ b/modules/variables/lab/lab_solution.py @@ -0,0 +1,14 @@ +def beräkna_aritmetisk(a1, d, n): + return n * (a1 + (a1 + d * (n - 1))) / 2 + + +def beräkna_geometrisk(g1, q, n): + return (g1 * ((q ** n) - 1) / (q - 1)) + +a1 = 1; d = 2; n = 3 + +print("Summan av den aritmetiska talföljden är", beräkna_aritmetisk(a1, d, n)) + +g1 = 2; q = 2; n = 4 + +print("Summan av den geometriska talföljden är ",beräkna_geometrisk(g1, q, n)) diff --git a/modules/variables/posttest.py b/modules/variables/posttest.py new file mode 100644 index 00000000..e93c9e31 --- /dev/null +++ b/modules/variables/posttest.py @@ -0,0 +1,18 @@ +# Math calculation programme + +def divide(x): + return x / 2 + + +x = 2 +y = 2 + +divided = divide(x) + +print(divided) + +x = x + 2 + +print(divided + y) + +print(x / 2 + y) diff --git a/modules/variables/pretest.py b/modules/variables/pretest.py new file mode 100644 index 00000000..fefdadf5 --- /dev/null +++ b/modules/variables/pretest.py @@ -0,0 +1,17 @@ +# Math calculation programme + +def multiply(x, y): + return x*y + +x = 4 +y = 5 + +multiple = multiply(x,y) + +print(multiple) + +x = x + 3 + +print(multiple) + +print(x*y) \ No newline at end of file diff --git a/modules/variables/slides-functions/.gitignore b/modules/variables/slides-functions/.gitignore new file mode 100644 index 00000000..aaae5fd9 --- /dev/null +++ b/modules/variables/slides-functions/.gitignore @@ -0,0 +1,3 @@ +notes.pdf +slides.pdf + diff --git a/modules/variables/slides-functions/Makefile b/modules/variables/slides-functions/Makefile new file mode 100644 index 00000000..772cd9ca --- /dev/null +++ b/modules/variables/slides-functions/Makefile @@ -0,0 +1,24 @@ +.PHONY: all +all: notes.pdf slides.pdf + +LATEXFLAGS+= -shell-escape + +SRC+= preamble.tex +SRC+= abstract.tex contents.tex + +SRC+= examples/age-funcs.py examples/degees.py + +notes.pdf: notes.tex +notes.pdf: ${SRC} + +slides.pdf: slides.tex +slides.pdf: ${SRC} + + +.PHONY: clean +clean: + ${RM} notes.pdf slides.pdf + + +INCLUDE_MAKEFILES=../../../makefiles +include ${INCLUDE_MAKEFILES}/tex.mk diff --git a/modules/variables/slides-functions/README.md b/modules/variables/slides-functions/README.md new file mode 100644 index 00000000..5b387f46 --- /dev/null +++ b/modules/variables/slides-functions/README.md @@ -0,0 +1,5 @@ +- [YouTube: Funktioner][yt] +- [FeedbackFruits: Funktioner][fbf] + +[yt]: https://youtu.be/gdAe9L0mOXQ +[fbf]: https://eu.feedbackfruits.com/courses/activity-course/b5305551-3e6b-409f-93aa-d75e217c4ad6 diff --git a/modules/variables/slides-functions/abstract.tex b/modules/variables/slides-functions/abstract.tex new file mode 100644 index 00000000..4012d9d3 --- /dev/null +++ b/modules/variables/slides-functions/abstract.tex @@ -0,0 +1,22 @@ +% What's the problem? +% Why is it a problem? Research gap left by other approaches? +% Why is it important? Why care? +% What's the approach? How to solve the problem? +% What's the findings? How was it evaluated, what are the results, limitations, +% what remains to be done? + +% XXX Summary +\emph{Summary:} +\dots + +% XXX Motivation and intended learning outcomes +\emph{Intended learning outcomes:} +\dots + +% XXX Prerequisites +\emph{Prerequisites:} +\dots + +% XXX Reading material +\emph{Reading:} +\dots diff --git a/modules/variables/slides-functions/contents.tex b/modules/variables/slides-functions/contents.tex new file mode 100644 index 00000000..66bb3a53 --- /dev/null +++ b/modules/variables/slides-functions/contents.tex @@ -0,0 +1,200 @@ +\mode* + +\section{Funktioner} + +\subsection{Vad är bra med funktioner?} + +\begin{frame}[fragile] + \begin{exercise} + \begin{itemize} + \item Varför är det bra att använda funktioner? + \end{itemize} + \end{exercise} +\end{frame} + +\begin{frame}[fragile] + \begin{solution}[Bra med funktioner] + \begin{itemize} + \item Som \enquote{miniprogram} som går att återanvända. + \item Gör att vi kan minimera kodupprepningar. + \item Ger färre problem, underlättar underhåll och utbyggnad. + \end{itemize} + \end{solution} + + \pause + + \begin{example}[Att steka pannkakor{ {för fyra personer}}] + \begin{enumerate} + \item \alert<2>{Gör pannkakssmet} för fyra personer. + \item För varje portion, medan det finns pannkakssmet kvar: + \begin{enumerate} + \item Häll \SI{1}{\deci\litre} smet i en het stekpanna. + \item Vänta \SI{2}{\minute}. + \item \alert<3>{Vänd} pannkakan. + \item Vänta \SI{2}{\minute}. + \item Servera pannkakan. + \end{enumerate} + \end{enumerate} + \end{example} +\end{frame} + +\subsection{Egna funktioner} + +\begin{frame}[fragile] + \begin{minted}[fontsize=\huge]{python} +def func(parameters): + # use {parameters} + return results + \end{minted} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[Addition] + \begin{minted}[linenos]{python} +def add(x, y): + """Returns x+y""" + return x + y + +print(f"2 + 3 = {2+3}") +print(f"2 + 3 = {add(2, 3)}") + \end{minted} + \end{example} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[Dubblera] + \begin{minted}[linenos]{python} +def double(x): + """Returnerar dubbla x""" + return 2*x + +print(f"Dubbla 3 = {2*3}") +print(f"Dubbla 3 = {double(3)}") + \end{minted} + \end{example} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[Celcius och Farenheit] + \inputminted[linenos]{python}{examples/degees.py} + \end{example} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[Välkomsttext] + \begin{minted}[linenos]{python} +def welcome(name, origin): + """Returnerar en sträng med ett välkomstmeddelande baserat på + - namnet i name, + - avreseorten origin. + """ + return f"Välkommen {name}, du som rest så långt som " \ + f"från {origin}!" + +print(welcome("Daniel", "Kungsängen")) +print(welcome("Kungsängen", "Daniel")) # what?! + \end{minted} + \end{example} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[Utan return, direkt till skärm] + \begin{minted}[linenos,highlightlines={6,9-10}]{python} +def welcome_less_good(name, origin): + """Skriver ut ett välkomstmeddelande baserat på + - namnet i name, + - avreseorten origin. + """ + print(f"Välkommen {name}, du som rest så långt som " + f"från {origin}!") + +welcome("Daniel", "Kungsängen") +welcome("Kungsängen", "Daniel") # what?! + \end{minted} + \end{example} + + \begin{onlyenv}<2> + \begin{exercise} + \begin{itemize} + \item Varför är denna version sämre? + \end{itemize} + \end{exercise} + \end{onlyenv} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[Välkomsttext med variabler] + \begin{minted}[linenos,highlightlines={9-10,12-13}]{python} +def welcome(name, origin): + """Returnerar en sträng med ett välkomstmeddelande baserat på + - namnet i name, + - avreseorten origin. + """ + return f"Välkommen {name}, du som rest så långt som " \ + f"från {origin}!" + +name = "Daniel" +origin = "Kungsängen" + +print(welcome(name, origin)) +print(welcome(origin, name)) # what?! + \end{minted} + \end{example} +\end{frame} + +\begin{frame}[fragile] + \begin{example}[Välkomsttext med variabler, andra namn] + \begin{minted}[linenos,highlightlines={9-10,12-13}]{python} +def welcome(name, origin): + """Returnerar en sträng med ett välkomstmeddelande baserat på + - namnet i name, + - avreseorten origin. + """ + return f"Välkommen {name}, du som rest så långt som " \ + f"från {origin}!" + +var1 = "Daniel" +var2 = "Kungsängen" + +print(welcome(var1, var2)) +print(welcome(var2, var1)) # what?! + \end{minted} + \end{example} +\end{frame} + +\subsection{Dela upp i funktioner} + +\begin{frame}[fragile] + \begin{columns}[t] + \begin{column}{0.3\columnwidth} + \inputminted[linenos,firstline=11]{python}{../slides/examples/age.py} + \end{column} + \begin{column}{0.6\columnwidth} + \begin{exercise} + \begin{itemize} + \item Dela upp i passande funktioner. + \end{itemize} + \end{exercise} + \end{column} + \end{columns} +\end{frame} + +\begin{frame}[fragile] + \inputminted[linenos,firstline=10,lastline=18]{python}{examples/age-funcs.py} +\end{frame} + +\begin{frame}[fragile] + \inputminted[linenos,firstline=10,lastline=10]{python}{examples/age-funcs.py} + \inputminted[linenos,firstline=12,lastline=12]{python}{examples/age-funcs.py} + \inputminted[linenos,firstline=16,lastline=16]{python}{examples/age-funcs.py} + \inputminted[linenos,firstline=20,lastline=34]{python}{examples/age-funcs.py} +\end{frame} + +\begin{frame}[fragile] + \inputminted[linenos,firstline=12,lastline=12]{python}{examples/age-funcs.py} + \inputminted[linenos,firstline=16,lastline=16]{python}{examples/age-funcs.py} + \inputminted[linenos,firstline=20,lastline=20]{python}{examples/age-funcs.py} + \vspace{0.5em} + \inputminted[linenos,firstline=36]{python}{examples/age-funcs.py} +\end{frame} + diff --git a/modules/variables/slides-functions/examples/age-funcs.py b/modules/variables/slides-functions/examples/age-funcs.py new file mode 100644 index 00000000..58842ec1 --- /dev/null +++ b/modules/variables/slides-functions/examples/age-funcs.py @@ -0,0 +1,40 @@ +""" +Ett program om ålder. Illustrerar: + + - kommentarer, + - utskrifter, + - variabler, + - datatyper + - variabelnamn och konstanter +""" +THIS_YEAR = 2022 + +def age(birthyear, this_year): + """Beräknar ålder utifrån två år.""" + return this_year - birthyear + +def birthyear_age(age): + """Retunerar födelseår för att vara age år gammal.""" + return THIS_YEAR - age + +def age_game(name, birthyear): + """Skriver ut lite skoj om ålder""" + print(f"Hej, {name}") + + # beräkna ålder + the_age = age(birthyear, THIS_YEAR) + + print(f"Du är {the_age} gammal.") + print("Nu ska du får bli 25 år igen.") + + # beräkna nytt födelseår + birthyear = birthyear_age(25) + + print(f"Du är {age(birthyear, THIS_YEAR)} år gammal, " + f"det är {the_age-age(birthyear, THIS_YEAR)} år yngre.") + +name = "Daniel" +birthyear = 1985 + +age_game(name, birthyear) +age_game("Urban", 1950) diff --git a/modules/variables/slides-functions/examples/degees.py b/modules/variables/slides-functions/examples/degees.py new file mode 100644 index 00000000..916d8887 --- /dev/null +++ b/modules/variables/slides-functions/examples/degees.py @@ -0,0 +1,11 @@ +def farenheit(celcius): + """Returnerar grader Celcius konverterade till Farenheit""" + return celcius * 9/5 + 32 + +def celcius(farenheit): + """Returnerar grader Farenheit konverterade till Celcius""" + return (farenheit-32)*5/9 + +print(f"20 degC = {farenheit(20)}") +print(f"65 degF = {celcius(65)}") +print(f"celcius(farenheit(20)) = {celcius(farenheit(20))}") diff --git a/modules/variables/slides-functions/examples/func.py b/modules/variables/slides-functions/examples/func.py new file mode 100644 index 00000000..c751fa18 --- /dev/null +++ b/modules/variables/slides-functions/examples/func.py @@ -0,0 +1,8 @@ +"""Returnera värden""" + +def dubblera(x): + return 2*x + +y = dubblera(4) + 1 +print(y) +print(y) diff --git a/modules/variables/slides-functions/examples/test-add.py b/modules/variables/slides-functions/examples/test-add.py new file mode 100644 index 00000000..a50dc7b3 --- /dev/null +++ b/modules/variables/slides-functions/examples/test-add.py @@ -0,0 +1,6 @@ +def add(x, y): + """Adderar x och y""" + return x+y + +print(f"2+3 = {2+3}") +print(f"2+3 = {add(2, 3)}") diff --git a/modules/variables/slides-functions/examples/welcome.py b/modules/variables/slides-functions/examples/welcome.py new file mode 100644 index 00000000..a16e3b55 --- /dev/null +++ b/modules/variables/slides-functions/examples/welcome.py @@ -0,0 +1,9 @@ +def welcome(name, origin): + """Returnerar en välkomsttext""" + return f"Välkommen {name}, du som rest ända från {origin}!" + +var1 = "Daniel" +var2 = "Kungsängen" + +print(welcome(var1, var2)) +print(welcome(var2, var1)) diff --git a/modules/functions/slides-more/notes.tex b/modules/variables/slides-functions/notes.tex similarity index 100% rename from modules/functions/slides-more/notes.tex rename to modules/variables/slides-functions/notes.tex diff --git a/modules/variables/slides-functions/preamble.tex b/modules/variables/slides-functions/preamble.tex new file mode 100644 index 00000000..be6fda42 --- /dev/null +++ b/modules/variables/slides-functions/preamble.tex @@ -0,0 +1,39 @@ +\usepackage[utf8]{inputenc} +\usepackage[T1]{fontenc} +\usepackage[swedish]{babel} +\usepackage{booktabs} + +\usepackage[natbib,style=alphabetic,maxbibnames=99]{biblatex} +\addbibresource{slides.bib} + +\usepackage[all]{foreign} +\renewcommand{\foreignfullfont}{} +\renewcommand{\foreignabbrfont}{} + +\usepackage{newclude} +\usepackage{import} + +\usepackage[strict]{csquotes} +\usepackage[single]{acro} + +\usepackage{subcaption} + +\usepackage[noend]{algpseudocode} +\usepackage{xparse} + +\let\email\texttt + +\usepackage[outputdir=ltxobj]{minted} +\setminted{autogobble,fontsize=\footnotesize} + +\usepackage{amsmath} +\usepackage{amssymb} +\usepackage{mathtools} +\usepackage{amsthm} +\usepackage{thmtools} +\usepackage[unq]{unique} +\DeclareMathOperator{\powerset}{\mathcal{P}} + +\usepackage[binary-units]{siunitx} + +\usepackage[capitalize]{cleveref} diff --git a/modules/variables/slides-functions/slides.tex b/modules/variables/slides-functions/slides.tex new file mode 100644 index 00000000..623cc23f --- /dev/null +++ b/modules/variables/slides-functions/slides.tex @@ -0,0 +1,118 @@ +\documentclass[ignoreframetext]{beamer} +\input{preamble.tex} + +\usetheme{Berlin} +\setbeamertemplate{footline}%{miniframes theme} +{% + \begin{beamercolorbox}[colsep=1.5pt]{upper separation line foot} + \end{beamercolorbox} + \begin{beamercolorbox}[ht=2.5ex,dp=1.125ex,% + leftskip=.3cm,rightskip=.3cm plus1fil]{author in head/foot}% + \leavevmode{\usebeamerfont{author in head/foot}\insertshortauthor}% + \hfill% + {\usebeamerfont{institute in head/foot}\usebeamercolor[fg]{institute in head/foot}\insertshortinstitute}% + \end{beamercolorbox}% + \begin{beamercolorbox}[ht=2.5ex,dp=1.125ex,% + leftskip=.3cm,rightskip=.3cm plus1fil]{title in head/foot}% + {\usebeamerfont{title in head/foot}\insertshorttitle} \hfill \insertframenumber% + \end{beamercolorbox}% + \begin{beamercolorbox}[colsep=1.5pt]{lower separation line foot} + \end{beamercolorbox} +} +\setbeamercovered{transparent} +\setbeamertemplate{bibliography item}[text] + +\AtBeginSection[]{% + \begin{frame} + \tableofcontents[currentsection] + \end{frame} +} + +\ProvideDocumentEnvironment{assumption}{o}{% + \IfValueTF{#1}{% + \begin{block}{Assumption: #1} + }{% + \begin{block}{Assumption} + } +}{% + \end{block} +} + +\ProvideDocumentEnvironment{protocol}{o}{% + \IfValueTF{#1}{% + \begin{block}{Protocol: #1} + }{% + \begin{block}{Protocol} + } +}{% + \end{block} +} + +\ProvideDocumentEnvironment{remark}{o}{% + \IfValueTF{#1}{% + \begin{alertblock}{Note: #1} + }{% + \begin{alertblock}{Note} + } +}{% + \end{alertblock} +} + +\ProvideDocumentEnvironment{idea}{o}{% + \IfValueTF{#1}{% + \begin{block}{Idea: #1} + }{% + \begin{block}{Idea} + } +}{% + \end{block} +} + +\ProvideDocumentEnvironment{question}{o}{% + \setbeamercolor{block body}{bg=orange!15,fg=black} + \setbeamercolor{block title}{bg=orange,fg=white} + \setbeamercolor{local structure}{fg=orange} + \IfValueTF{#1}{% + \begin{block}{Question: #1} + }{% + \begin{block}{Question} + } +}{% + \end{block} +} + +\ProvideDocumentEnvironment{exercise}{o}{% + \setbeamercolor{block body}{bg=yellow!10,fg=black} + \setbeamercolor{block title}{bg=yellow,fg=black} + \setbeamercolor{local structure}{fg=yellow} + \IfValueTF{#1}{% + \begin{block}{Exercise: #1} + }{% + \begin{block}{Exercise} + } +}{% + \end{block} +} + + +\begin{document} +\title{% + Funktioner +} +\author{Daniel Bosk} +\institute{% + KTH EECS +} + +\begin{frame} + \maketitle +\end{frame} + +\mode +\input{contents.tex} +\mode* + +%\begin{frame}[allowframebreaks] +% \printbibliography +%\end{frame} +\end{document} diff --git a/modules/variables/slides-more/contents.tex b/modules/variables/slides-more/contents.tex deleted file mode 100644 index 9255abc9..00000000 --- a/modules/variables/slides-more/contents.tex +++ /dev/null @@ -1,66 +0,0 @@ -\title{% - Mer variabler och funktioner -} -\author{Daniel Bosk} -\institute{% - KTH EECS -} - -\mode
{\maketitle} -\mode{% - \begin{frame} - \maketitle - \end{frame} -} - -\mode* - -\begin{abstract} - \input{abstract.tex} -\end{abstract} - - -\section{Uppdelning i funktioner} - -\begin{frame} - \begin{remark} - \begin{itemize} - \item Funktioner motsvarar verb i dagligt språk! - \end{itemize} - \end{remark} -\end{frame} - -\begin{frame} - \begin{example}[Algoritm för handdisk] - \begin{enumerate} - \item \emph{Lägg} all disk i diskhon med diskvattnet i. - \item \label{glas} \emph{Ta} ett glas, \emph{diska} det, \emph{lägg} det - i diskhon för diskad disk. - \item Repetera \ref{glas} tills att glasen är slut. - \item \label{bestick} \emph{Ta} ett bestick, \emph{diska} det, - \emph{lägg} det i diskhon för diskad disk. - \item Repetera \ref{bestick} tills att besticken är slut. - \item \emph{Ta} en tallrik, \emph{diska} den, \emph{lägg} den i diskhon - för diskad disk. - \end{enumerate} - \end{example} -\end{frame} - -\begin{frame} - \begin{exercise} - \begin{itemize} - \item En person beskriver en process, de andra två fokuserar på att - identifiera funktioner. - \end{itemize} - \begin{enumerate} - \item Slå in en present i presentpapper. - \item Knyta ett par skor. - \item Steka pannpaka. - \end{enumerate} - \end{exercise} -\end{frame} - -\section{Exempel i Python} - -\begin{frame} -\end{frame} diff --git a/modules/variables/slides/Makefile b/modules/variables/slides/Makefile index 1d9d9db6..74b94364 100644 --- a/modules/variables/slides/Makefile +++ b/modules/variables/slides/Makefile @@ -8,6 +8,8 @@ SRC+= abstract.tex contents.tex DEPENDS+= beamer-didactic.sty +SRC+= examples/age.py + notes.pdf: notes.tex slides.pdf: slides.tex diff --git a/modules/variables/slides/README.md b/modules/variables/slides/README.md new file mode 100644 index 00000000..79ff72fe --- /dev/null +++ b/modules/variables/slides/README.md @@ -0,0 +1,5 @@ +- [YouTube: Variabler och utskrifter][yt] +- [FeedbackFruits: Variabler och utskrifter][fbf] + +[yt]: https://youtu.be/KyAXg_PPU4o +[fbf]: https://eu.feedbackfruits.com/courses/activity-course/9f1a090b-700f-4fec-a4b3-ac90d289232c diff --git a/modules/variables/slides/contents.tex b/modules/variables/slides/contents.tex index 3b8dd9c5..c266771d 100644 --- a/modules/variables/slides/contents.tex +++ b/modules/variables/slides/contents.tex @@ -1,5 +1,5 @@ \title{% - Variabler och funktioner + Variabler och utskrifter } \author{Daniel Bosk} \institute{% @@ -20,156 +20,80 @@ \end{abstract} -\section{Programmering} +\section{Ett pythonprogram} -\subsection{Vad är programmering?} - -\begin{frame} - \begin{block}{Dator} - \begin{itemize} - \item Processor - \item Minne - \item Annan hårdvara - \end{itemize} - \end{block} -\end{frame} - -\begin{frame} - \begin{block}{Processorn} - \begin{itemize} - \item Exekverar maskinkod --- program - \end{itemize} - \end{block} - - \pause - - \begin{example} - \begin{itemize} - \item<1-2> 00012000050000020500 - \item<3-> 0001 2000 0500 - \item<3-> 0002 0500 - \end{itemize} - \end{example} -\end{frame} - -\begin{frame} - \begin{block}{Svar} - \begin{itemize} - \item Programmering är att skriva program. - \end{itemize} - \end{block} -\end{frame} - - -\subsection{Programmeringsspråk} - -\begin{frame} - \begin{block}{Programmeringsspråk} +\begin{frame}[fragile] + \begin{exercise} \begin{itemize} - \item Ett språk för människor att skriva datorprogram. + \item Konstruera en algoritm som fungerar som följande + program. + \item Vilka funktioner och variabler behöver du? \end{itemize} - \end{block} + \end{exercise} \end{frame} \begin{frame}[fragile] - \begin{example}[Python] - \begin{minted}{python} -print("Hello, World!") - \end{minted} - \end{example} - - \pause - - \begin{example}[C++] - \begin{minted}{c++} -#include -using namespace std; - -int main(void) { - std::cout << "Hello, World!" << std::endl; - return 0; -} - \end{minted} - \end{example} -\end{frame} - -\begin{frame} - \begin{remark} + \begin{remark}[Språk för dator eller människa] \begin{itemize} - \item Måste översättas till maskinkod! + \item Människor förstår mänskligt språk. + \item Datorer förstår inte mänskligt språk. + \item Datorer förstår bara väldigt specifikt, begränsat språk. \end{itemize} \end{remark} \end{frame} - -\section{Köra Python} - -\subsection{Terminalen} - -\begin{frame} - \includegraphics[width=\columnwidth]{figs/python-terminal.png} -\end{frame} - - -\subsection{Andra gränssnitt} - -\begin{frame} - \centering - \includegraphics[width=\columnwidth]{figs/idle.jpg} -\end{frame} - -\begin{frame} - \centering - \includegraphics[height=\textheight]{figs/codium.png} -\end{frame} - -\begin{frame} - \centering - \includegraphics[height=\textheight]{figs/atom.png} -\end{frame} - -\begin{frame} - \centering - \includegraphics[height=\textheight]{figs/pycharm.png} +\begin{frame}[fragile] + \inputminted[linenos,firstline=11]{python}{examples/age.py} \end{frame} +\section{Kommentarer} -\section{Skriva Pythonprogram} - -\subsection{Kommentarer} - -\begin{frame} +\begin{frame}[fragile] \begin{center} - \huge\# + \mintinline[fontsize=\huge]{python}|#| \end{center} \end{frame} \begin{frame}[fragile] \begin{example} \begin{minted}{python} -# Har kan vi skriva for manniskor. +# Här kan vi skriva for människor. # Python kommer att ignorera allt detta. \end{minted} \end{example} \end{frame} +\begin{frame}[fragile] + \inputminted[highlightlines={16,24},linenos,firstline=11]{python}{examples/age.py} +\end{frame} + \begin{frame}[fragile] \begin{example} \begin{minted}{python} """ -Detta ar dock lite enklare, -iallafall nar vi ska skriva pa flera +Detta är dock lite enklare, +iallafall när vi ska skriva på flera rader """ \end{minted} \end{example} \end{frame} +\begin{frame}[fragile] + \inputminted[highlightlines={1-10},linenos]{python}{examples/age.py} +\end{frame} -\subsection{Utskrifter} + +\section{Utskrifter} \begin{frame}[fragile] - \begin{block}{Funktionen \mint{python}|print|} + \begin{center} + \mintinline[fontsize=\huge]{python}|print| + \end{center} +\end{frame} + +\begin{frame}[fragile] + \begin{block}{Funktionen \mintinline{python}|print|} \begin{itemize} \item Skriver ut sina argument till skärmen. \end{itemize} @@ -179,14 +103,18 @@ \subsection{Utskrifter} \begin{example} \begin{minted}{python} -# Skriver ut till skarmen +# Skriver ut till skärmen print("Hello, World!") \end{minted} \end{example} \end{frame} +\begin{frame}[fragile] + \inputminted[highlightlines={14,20,22,27-28},linenos,firstline=11]{python}{examples/age.py} +\end{frame} -\subsection{Variabler och datatyper} + +\section{Variabler och datatyper} \begin{frame} \begin{block}{Data} @@ -209,6 +137,10 @@ \subsection{Variabler och datatyper} \end{example} \end{frame} +\begin{frame}[fragile] + \inputminted[highlightlines={11-12,14,17,20,22,25,27-28},linenos,firstline=11]{python}{examples/age.py} +\end{frame} + \begin{frame}[fragile] \begin{block}{Variabler} \begin{itemize} @@ -220,6 +152,23 @@ \subsection{Variabler och datatyper} \pause + \begin{example} + \begin{minted}{python} +# Skriver ut till skärmen +print("Hello, World!") + \end{minted} + \end{example} + + \begin{example} + \begin{minted}{python} +# Skriver ut till skärmen +text = "Hello, World!" +print(text) + \end{minted} + \end{example} +\end{frame} + +\begin{frame}[fragile] \begin{example}[Variabler] \begin{minted}{python} x = 5 @@ -229,6 +178,10 @@ \subsection{Variabler och datatyper} \end{example} \end{frame} +\begin{frame}[fragile] + \inputminted[highlightlines={11-12,14,17,18,20,25,27-28},linenos,firstline=11]{python}{examples/age.py} +\end{frame} + \begin{frame} \begin{remark} \begin{itemize} @@ -249,30 +202,75 @@ \subsection{Variabler och datatyper} \end{example} \end{frame} +\begin{frame}[fragile] + \begin{example} + \begin{minted}{python} +x = 5 +y = 2*x +x = 4 +print(y) + \end{minted} + \end{example} + + \begin{exercise}[Vad lagras?] + \begin{itemize} +% \item Vad lagras i variabeln \mintinline{python}|x|? +% \begin{enumerate} +% \item Formeln \(2\cdot x\)? +% \item Värdet \(10\)? +% \end{enumerate} + \item Vad kommer att skrivas ut av \mintinline{python}|print(y)|, + \(10\) eller \(8\)? + \end{itemize} + \end{exercise} +\end{frame} + +\begin{frame}[fragile] + \inputminted[highlightlines={12,25,28},linenos,firstline=11]{python}{examples/age.py} +\end{frame} + \begin{frame}[fragile] \begin{example}[Fler heltalsoperationer] \begin{minted}{python} x = 5 y = x / 2 z = x // 2 -xx = x**2 +x_square = x**2 \end{minted} \end{example} + + \pause + + \begin{remark} + \begin{itemize} + \item Operatorer är typberoende. + \item \mintinline{python}|"hej" / "då"|? + \end{itemize} + \end{remark} \end{frame} \begin{frame}[fragile] \begin{remark} \begin{itemize} - \item \mint{python}|print| behöver datatypen sträng. + \item \mintinline{python}|print| behöver datatypen sträng. \item Finns typkonvertering. \end{itemize} \end{remark} - \begin{example} + \begin{example}[Funkar] \begin{minted}{python} name = "Daniel" x = 5 print("Hej " + name + "!") +print(x) + \end{minted} + \end{example} + + \begin{example}[Funkar inte] + \begin{minted}[highlightlines=3]{python} +name = "Daniel" +x = 5 +print("Hej " + x + "!") print(x) \end{minted} \end{example} @@ -281,29 +279,34 @@ \subsection{Variabler och datatyper} \begin{frame}[fragile] \begin{example} \begin{minted}{python} -print("Ar " + x " stort?") -print("Ar " + str(x) + " stort?") -print("Ar {} stort?".format(x)) -print(f"Ar {x} stort?") +x = 5 +print("Är " + x + " stort?") +print("Är " + str(x) + " stort?") +print("Är {} stort?".format(x)) +print(f"Är {x} stort?") \end{minted} \end{example} \end{frame} +\begin{frame}[fragile] + \inputminted[highlightlines={14,20,27-28},linenos,firstline=11]{python}{examples/age.py} +\end{frame} + -\subsection{Konstanter} +\section{Konstanter} \begin{frame} \begin{remark}[Konstanter varierar inte] \begin{itemize} \item Vissa språk förhindrar ändring av konstanter. \item Python har bara konvention. - \item \mint{python}|PI = 3.14| + \item \mintinline{python}|PI = 3.14| \end{itemize} \end{remark} \end{frame} -\subsection{Variabelnamn} +\section{Variabelnamn} \begin{frame}[fragile] \begin{remark}[Reserverade namn] diff --git a/modules/variables/slides/examples/age.py b/modules/variables/slides/examples/age.py new file mode 100644 index 00000000..1afd8bc3 --- /dev/null +++ b/modules/variables/slides/examples/age.py @@ -0,0 +1,28 @@ +""" +Ett program om ålder. Illustrerar: + + - kommentarer, + - utskrifter, + - variabler, + - datatyper + - variabelnamn och konstanter +""" + +name = "Daniel" +birthyear = 1985 + +print(f"Hej, {name}") + +# beräkna ålder +this_year = 2022 +age = this_year - birthyear + +print(f"Du är {age} gammal.") + +print("Nu ska du får bli 25 år igen.") + +# beräkna nytt födelseår +birthyear = this_year - 25 + +print(f"Du är {this_year-birthyear} år gammal, " + f"det är {age-(this_year-birthyear)} år yngre.") diff --git a/modules/variables/slides/examples/cinek2.py b/modules/variables/slides/examples/cinek2.py deleted file mode 100644 index 7a8cdcbc..00000000 --- a/modules/variables/slides/examples/cinek2.py +++ /dev/null @@ -1,3 +0,0 @@ -"""Ett till test för cinek""" - -print("Hej, CINEK!") diff --git a/modules/variables/slides/examples/cinek.py b/modules/variables/slides/examples/farenheit.py similarity index 100% rename from modules/variables/slides/examples/cinek.py rename to modules/variables/slides/examples/farenheit.py diff --git a/modules/variables/slides/examples/hello.py b/modules/variables/slides/examples/hello.py deleted file mode 100644 index 665c637a..00000000 --- a/modules/variables/slides/examples/hello.py +++ /dev/null @@ -1 +0,0 @@ -print("hello world!") diff --git a/modules/variables/slides/examples/print-test.py b/modules/variables/slides/examples/print-test.py new file mode 100644 index 00000000..64a32e97 --- /dev/null +++ b/modules/variables/slides/examples/print-test.py @@ -0,0 +1,3 @@ +# Skriver ut till skärmen +text = "Hello world!!!!!" +print(text) diff --git a/modules/variables/slides/examples/roligt.py b/modules/variables/slides/examples/roligt.py deleted file mode 100644 index 9740d056..00000000 --- a/modules/variables/slides/examples/roligt.py +++ /dev/null @@ -1,5 +0,0 @@ -print("Vad vill addera?") -x = int(input()) -print(f"Vad vill du addera {x} med?") -y = int(input()) -print(f"Då blir summan {x+y}.") diff --git a/modules/variables/slides/examples/test-int.py b/modules/variables/slides/examples/test-int.py new file mode 100644 index 00000000..b8b3a801 --- /dev/null +++ b/modules/variables/slides/examples/test-int.py @@ -0,0 +1,8 @@ +x = 4 + 1 +print(f"x = {x}") +y = 2 +print(f"y = {y}") +z = x * y +print(f"z = x * y = {z}") +x2 = z / y +print(f"z / y = {x2}") diff --git a/modules/variables/slides/examples/test-intdiv.py b/modules/variables/slides/examples/test-intdiv.py new file mode 100644 index 00000000..9b14dc65 --- /dev/null +++ b/modules/variables/slides/examples/test-intdiv.py @@ -0,0 +1,6 @@ +x = 10 +y = x / 2 +z = x // 2 +print(f"x = {x}") +print(f"y = {y}") +print(f"z = {z}") diff --git a/modules/variables/slides/examples/test-konvertering.py b/modules/variables/slides/examples/test-konvertering.py new file mode 100644 index 00000000..b089dc10 --- /dev/null +++ b/modules/variables/slides/examples/test-konvertering.py @@ -0,0 +1,4 @@ +name = "Daniel" +x = 5 +print(f"Hej {x}!") +print(x) diff --git a/modules/variables/slides/examples/test-mult.py b/modules/variables/slides/examples/test-mult.py new file mode 100644 index 00000000..62e29482 --- /dev/null +++ b/modules/variables/slides/examples/test-mult.py @@ -0,0 +1,5 @@ +x = 5 +y = 2 * x +x = 4 +print(f"x = {x}") +print(f"y = {y}") diff --git a/modules/variables/slides/examples/test2.py b/modules/variables/slides/examples/test2.py deleted file mode 100644 index 6b94de03..00000000 --- a/modules/variables/slides/examples/test2.py +++ /dev/null @@ -1 +0,0 @@ -print("test 2") diff --git a/modules/variables/slides/examples/test3.py b/modules/variables/slides/examples/test3.py deleted file mode 100644 index e69de29b..00000000 diff --git a/modules/variables/slides/examples/vscode-test.py b/modules/variables/slides/examples/vscode-test.py deleted file mode 100644 index 556b3c1a..00000000 --- a/modules/variables/slides/examples/vscode-test.py +++ /dev/null @@ -1 +0,0 @@ -print("from vscode") \ No newline at end of file diff --git a/modules/variables/slides/preamble.tex b/modules/variables/slides/preamble.tex index 9a092c5b..ee813387 100644 --- a/modules/variables/slides/preamble.tex +++ b/modules/variables/slides/preamble.tex @@ -3,6 +3,9 @@ \usepackage[british,swedish]{babel} \usepackage{booktabs} +\usepackage[natbib,style=alphabetic,maxbibnames=99]{biblatex} +\addbibresource{slides.bib} + \usepackage[all]{foreign} \renewcommand{\foreignfullfont}{} \renewcommand{\foreignabbrfont}{} @@ -13,9 +16,6 @@ \usepackage[strict]{csquotes} \usepackage[single]{acro} -\usepackage[natbib,style=alphabetic,maxbibnames=99]{biblatex} -\addbibresource{slides.bib} - \usepackage{subcaption} \usepackage[noend]{algpseudocode} diff --git a/modules/variables/slides/slides.tex b/modules/variables/slides/slides.tex index d7beb5f0..692a8dd9 100644 --- a/modules/variables/slides/slides.tex +++ b/modules/variables/slides/slides.tex @@ -102,7 +102,7 @@ % %%% REFERENCES %%% -\begin{frame}[allowframebreaks] - \printbibliography -\end{frame} +%\begin{frame}[allowframebreaks] +% \printbibliography +%\end{frame} \end{document} diff --git a/modules/variables/tutorial-advanced/Makefile b/modules/variables/tutorial-advanced/Makefile new file mode 100644 index 00000000..3bf2bae0 --- /dev/null +++ b/modules/variables/tutorial-advanced/Makefile @@ -0,0 +1,17 @@ +HTML_FILES= tutorial.html + +PANDOCFLAGS= --filter pandoc-xnos + + +.PHONY: all +all: ${HTML_FILES} ${PDF_FILES} + +tutorial.html: tutorial.md + + +.PHONY: clean +clean: + ${RM} ${HTML_FILES} ${PDF_FILES} + + +include ../../../html.mk diff --git a/modules/variables/tutorial-advanced/bmi.py b/modules/variables/tutorial-advanced/bmi.py new file mode 100644 index 00000000..55f3db11 --- /dev/null +++ b/modules/variables/tutorial-advanced/bmi.py @@ -0,0 +1,27 @@ + +# Ditt namn +NAMN = "Peter" +# Din vikt i kilogram (kg) +VIKT = 80 +# Din längd i centimeter (cm) +LÄNGD = 185 + + +def bmi(vikt: float | int, längd: float | int) -> float: + """Returnerar Body Mass Index (BMI) givet en vikt i kg + och en längd i cm.""" + return vikt / ((längd / 100) ** 2) + + +def main(): + print(f"Välkommen till BMI räknaren, {NAMN}!") + print("Information om BMI:") + print(" BMI < 18.5 ==> Du är underviktig") + print("18.5 ≤ BMI < 25.0 ==> Du är normalviktig") + print("25.0 ≤ BMI ==> Du är överviktig") + print() + print(f"Ditt BMI är: {bmi(VIKT, LÄNGD):.2f}") + + +if __name__ == "__main__": + main() diff --git a/modules/variables/tutorial-advanced/diska.py b/modules/variables/tutorial-advanced/diska.py new file mode 100644 index 00000000..c4e487b0 --- /dev/null +++ b/modules/variables/tutorial-advanced/diska.py @@ -0,0 +1,25 @@ +"""Ett program som skriver ut vad man får i de olika stegen för handdisk""" + + +def diska(sak): + """Diskar sak""" + return skölj(gnugga(doppa_i_vatten(sak))) + + +def skölj(sak): + """Sköljer en sak""" + return f"avsköljt {sak}" + + +def gnugga(sak): + """Gnuggar av en sak med diskborsten""" + return "rengnuggat " + sak + + +def doppa_i_vatten(sak): + """Doppar sak i diskvatten""" + + return "diskvattendränkt " + sak + + +print(diska("smutsigt glas")) diff --git a/modules/variables/tutorial-advanced/hard_house_chores.py b/modules/variables/tutorial-advanced/hard_house_chores.py new file mode 100644 index 00000000..fabb2791 --- /dev/null +++ b/modules/variables/tutorial-advanced/hard_house_chores.py @@ -0,0 +1,32 @@ +def blommor(): + print("Vill du vattna blommorna? ") + yes = input() + + if yes == "yes": + print("Vattnar blommorna") + + +def sopor(string): + print(string) + no: bool = input() + + if not no == "no": + print("Tar ut soporna") + return True + else: + return False + + +chores = ["Tömma diskmaskinen", "Dammsuga mormors hus", "Gå ut med hunden"] + +b = blommor() + +sopor("Vill du ta ut soporna?") + +print("Förutom att vattna blommor och ta ut sopor ska vi:") + +def func(): + for x in chores: + print(x) + +func() diff --git a/modules/variables/tutorial-advanced/snabbt_ibland.py b/modules/variables/tutorial-advanced/snabbt_ibland.py new file mode 100644 index 00000000..7cd4219e --- /dev/null +++ b/modules/variables/tutorial-advanced/snabbt_ibland.py @@ -0,0 +1,23 @@ +from functools import lru_cache +from time import sleep + + +@lru_cache +def multiplicera_med_15(tal: float) -> float: + """Multiplicera ett tal med 15.""" + sleep(10) + return tal * 15 + + +def fråga_om_multiplikation(): + """Fråga användaren om vilket tal denne vill multiplicera med 15.""" + tal = float(input("Skriv ett tal som du vill multiplicera med 15: ")) + print("Multiplicerar... ", end="") + print(multiplicera_med_15(tal)) + + +if __name__ == "__main__": + fråga_om_multiplikation() + fråga_om_multiplikation() + fråga_om_multiplikation() + fråga_om_multiplikation() diff --git a/modules/variables/tutorial-advanced/tutorial.md b/modules/variables/tutorial-advanced/tutorial.md new file mode 100644 index 00000000..93e4c6b1 --- /dev/null +++ b/modules/variables/tutorial-advanced/tutorial.md @@ -0,0 +1,112 @@ +--- +title: Fördjupande övning om variabler och funktioner +authors: + - Daniel Bosk + - Celina Soori +--- +# Fördjupande övning: funktioner och variabler + +Målet med övningen är att du ska få en fördjupad förståelse för hur man ska + + - dela upp problem in mindre problem, + - minimera kodupprepning, + - skapa funktioner med parametrar och returvärden. + + +## Önskemål från gruppen + +Har alla kommit igång med kursens material? Är det några frågetecken om kursuppläget? + +Var det något särskilt från veckans föreläsning och/eller OLI-material som gruppen vill gå in djupare på? + +## Övningsuppgifter + +### Finn fem fel + +Dela upp er i par och låt en av er ladda ner [ett program för att göra hushållssysslor](https://github.com/dbosk/intropy/blob/master/modules/variables/tutorial-advanced/hard_house_chores.py) + +Läs igenom koden och få ett hum om vad den är tänkt att göra. Testa att köra koden. + +Hitta nu tillsammans minst fem fel/utvecklingsområden i koden (tänk på vad ni lärt er under veckan). + +Förbättra nu koden efter det ni hittat. Blev koden mer lättläst, användbar och/eller användarvänlig? Varför? + +### Att göra saker + +Vi ska nu fokusera på att skriva funktioner som fokuserar på att dela upp +algoritmer i deras beståndsdelar. + +Vi börjar med [ett exempel för att gå][walk]: +```python +"""Ett program som illustrerar funktionsuppdelningen i att gå""" + +def take_step_fwd(): + """En funktion som anropar funktionerna som behövs för att ta ett steg""" + lift_leg("vänster") + lean_body("framåt") + lift_leg("höger") + lean_body("bakåt") + +def lift_leg(the_leg): + """Lyfter ett ben, the_leg anger höger eller vänster""" + print(f"lyft {the_leg} ben") + +def lean_body(direction): + """Luta kroppen, direction anger riktning""" + print(f"luta kroppen {direction}") + +def walk_two_steps(): + """En funktion som tar två steg framåt""" + take_step_fwd() + take_step_fwd() + +walk_two_steps() +``` +Givetvis kan vi dela upp funktionen `lift_leg` ytterligare. + +[walk]: https://github.com/dbosk/intropy/blob/master/modules/variables/tutorial-advanced/walk.py + +Skriv program som, på samma sätt som ovan, skriver ut instruktioner för att: + + 1. dansa (valfri dans), vilka steg ska tas med vilka fötter? + 2. diska (handdisk, då diskmaskinen inte är så utmanande, vi såg en algoritm + på föreläsningen). + +Vi går igenom olika lösningar och det här [lösningsförslaget](https://github.com/dbosk/intropy/blob/master/modules/variables/tutorial-advanced/diska.py) + +### Beräkna Body Mass Index (BMI) + +Body Mass Index (BMI) kan användas för att se om man kanske är över- eller underviktigt, eller har en bra vikt. + +Formula är: "BMI" = "vikt i kg" / ("längd i meter" ^ 2) + +Skriv ett program bestående av en funktion som givet en persons vikt och längd beräknar hans/hennes BMI. +Programmet ska använda funktionen för att skriva ut (åtminstone) ett BMI. + +Vi går igenom olika lösningar och det här [lösningsförslaget](https://github.com/dbosk/intropy/blob/master/modules/variables/tutorial-advanced/bmi.py) + +### Optimera en långsam funktion med @lru_cache + +Skriv en långsam funktion. Optimera funktionen m.h.a. [@lru_cache](https://docs.python.org/3/library/functools.html?highlight=lru_cache#functools.lru_cache). + +Tips: du kan använda [sleep](https://docs.python.org/3/library/time.html?highlight=sleep#time.sleep) för att göra funktionen långsam. + +Notera, så här kan du importera lru_cache och sleep för att få tillgång till dem i din kod: +```python +from functools import lru_cache +from time import sleep +``` + +Vi går igenom olika lösningar och det här [lösningsförslaget](https://github.com/dbosk/intropy/blob/master/modules/variables/tutorial-advanced/snabbt_ibland.py) + +### Generera e-postadresser + +Skriv ett program som generar en e-postadress utifrån parametrar som antingen är hårdkodade eller givna av användaren. + +Vi går igenom olika lösningar och det här [lösningsförslaget](https://github.com/dbosk/intropy/blob/master/resources/funktioner/adress.py) + +### Avgöra om en e-postadress är giltig + +Skriv ett program som tar en e-postadress som input och sedan returnerar om +den givna e-postadressen är giltig eller inte. Går det att återanvända kod från +föregående uppgift? diff --git a/modules/variables/walk.py b/modules/variables/tutorial-advanced/walk.py similarity index 100% rename from modules/variables/walk.py rename to modules/variables/tutorial-advanced/walk.py diff --git a/modules/variables/tutorial/Makefile b/modules/variables/tutorial/Makefile new file mode 100644 index 00000000..3bf2bae0 --- /dev/null +++ b/modules/variables/tutorial/Makefile @@ -0,0 +1,17 @@ +HTML_FILES= tutorial.html + +PANDOCFLAGS= --filter pandoc-xnos + + +.PHONY: all +all: ${HTML_FILES} ${PDF_FILES} + +tutorial.html: tutorial.md + + +.PHONY: clean +clean: + ${RM} ${HTML_FILES} ${PDF_FILES} + + +include ../../../html.mk diff --git a/modules/variables/diska.py b/modules/variables/tutorial/diska.py similarity index 93% rename from modules/variables/diska.py rename to modules/variables/tutorial/diska.py index ca1caa72..9a2857e0 100644 --- a/modules/variables/diska.py +++ b/modules/variables/tutorial/diska.py @@ -1,19 +1,24 @@ """Ett program som skriver ut vad man får i de olika stegen för handdisk""" + def diska(sak): """Diskar sak""" return skölj(gnugga(doppa_i_vatten(sak))) + def skölj(sak): - """Sköjler en sak""" + """Sköljer en sak""" return f"avsköljt {sak}" + def gnugga(sak): """Gnuggar av en sak med diskborsten""" return "rengnuggat " + sak + def doppa_i_vatten(sak): """Doppar sak i diskvatten""" return "diskvattendränkt " + sak + print(diska("smutsigt glas")) diff --git a/modules/variables/tutorial/easy_house_chores.py b/modules/variables/tutorial/easy_house_chores.py new file mode 100644 index 00000000..6c1e7cf5 --- /dev/null +++ b/modules/variables/tutorial/easy_house_chores.py @@ -0,0 +1,17 @@ +def blommor(): + print("Vattnar blommorna") + +def sopor(string): + print(string) + return True + +def func(): + print("Tömma diskmaskinen") + print("Dammsuga mormors hus") + +b = blommor() + +sopor("Tar ut soporna") + +print("Förutom att vattna blommor och ta ut sopor ska vi:") +func() diff --git a/modules/variables/tutorial.md b/modules/variables/tutorial/tutorial.md similarity index 60% rename from modules/variables/tutorial.md rename to modules/variables/tutorial/tutorial.md index 4cd4c962..98ded518 100644 --- a/modules/variables/tutorial.md +++ b/modules/variables/tutorial/tutorial.md @@ -1,24 +1,32 @@ --- -title: Övning om variabler och funktioner +title: Övning om funktioner och variabler authors: - Daniel Bosk + - Celina Soori --- # Övning: funktioner och variabler -Målet med övningen är att du ska blir bättre på att +Målet med övningen är att du ska bli bättre på att - dela upp problem in mindre problem, - minimera kodupprepning, - skapa funktioner med parametrar och returvärden. +## Genomgång av veckans svårigheter -## Laborationen +Vi går igenom det vi upptäckt i OLI är extra svårt den här veckan. -Hur har olika grupper löst samma labb? Oftast väldigt olika. Vi går igenom -några lösningar. +Zoomlänk: +## Önskemål från gruppen + +Har alla kommit igång med kursens material? Är det några frågetecken om kursuppläget? + +Var det något särskilt från veckans föreläsning och/eller OLI-material som gruppen vill gå igenom igen? + +## Övningsuppgifter -## Kakelfabriken +### Kakelfabriken En kakelfabrik behöver räkna ut hur mycket färg som går åt för olika kakelmönster och olika storlekar. @@ -29,10 +37,19 @@ Skriv funktioner som beräknar mängden färg givet relevanta inparametrar. ![Kakel: kvadrat](https://github.com/dbosk/intropy/raw/master/modules/variables/fig/kakel2.png) ![Kakel: hexagon](https://github.com/dbosk/intropy/raw/master/modules/variables/fig/kakel3.png) +### Finn fem fel + +Dela upp er i par och låt en av er ladda ner [ett program för att göra hushållssysslor](https://github.com/dbosk/intropy/blob/master/modules/variables/tutorial/easy_house_chores.py) + +Läs igenom koden och få ett hum om vad den är tänkt att göra. Testa att köra koden. + +Hitta nu tillsammans minst fem fel/utvecklingsområden i koden (tänk på vad ni lärt er under veckan). -## Att göra saker +Förbättra nu koden efter det ni hittat. Blev koden mer lättläst, användbar och/eller användarvänlig? Varför? -Vi ska nu fokusera på att skriva funktioner som fokuserar på att dela upp +### Att göra saker + +Vi ska nu fokusera på att skriva funktioner som fokuserar på att dela upp algoritmer i deras beståndsdelar. Vi börjar med [ett exempel för att gå][walk]: @@ -63,22 +80,12 @@ walk_two_steps() ``` Givetvis kan vi dela upp funktionen `lift_leg` ytterligare. -[walk]: https://github.com/dbosk/intropy/blob/master/modules/variables/walk.py +[walk]: https://github.com/dbosk/intropy/blob/master/modules/variables/tutorial/walk.py Skriv program som, på samma sätt som ovan, skriver ut instruktioner för att: 1. dansa (valfri dans), vilka steg ska tas med vilka fötter? - 2. diska (handdisk, då diskmaskinen inte är så utmanande, vi såg en algoritm + 2. diska (handdisk, då diskmaskinen inte är så utmanande, vi såg en algoritm på föreläsningen). -Vi går igenom olika lösningar samt - - - ett [alternativ för vad som händer när man diskar](https://github.com/dbosk/intropy/blob/master/modules/variables/diska.py) - och - - hur man kan [konstruera e-postadresser utifrån namn](https://github.com/dbosk/intropy/blob/master/resources/funktioner/adress.py). - - -## Önskemål från gruppen - -Vad vill gruppen gå igenom igen från veckan som var? - +Vi går igenom olika lösningar och det här [lösningsförslaget](https://github.com/dbosk/intropy/blob/master/modules/variables/tutorial/diska.py) diff --git a/modules/variables/tutorial/walk.py b/modules/variables/tutorial/walk.py new file mode 100644 index 00000000..503be9e9 --- /dev/null +++ b/modules/variables/tutorial/walk.py @@ -0,0 +1,23 @@ +"""Ett program som illustrerar funktionsuppdelningen i att gå""" + +def take_step_fwd(): + """En funktion som anropar funktionerna som behövs för att ta ett steg""" + lift_leg("vänster") + lean_body("framåt") + lift_leg("höger") + lean_body("bakåt") + +def lift_leg(the_leg): + """Lyfter ett ben, the_leg anger höger eller vänster""" + print(f"lyft {the_leg} ben") + +def lean_body(direction): + """Luta kroppen, direction anger riktning""" + print(f"luta kroppen {direction}") + +def walk_two_steps(): + """En funktion som tar två steg framåt""" + take_step_fwd() + take_step_fwd() + +walk_two_steps() diff --git a/research/evaluation/questions22.md b/research/evaluation/questions22.md new file mode 100644 index 00000000..7f8f53c5 --- /dev/null +++ b/research/evaluation/questions22.md @@ -0,0 +1,37 @@ +Tyvärr hade jag mycket att göra innan jag gick på föräldraledighet i januari, +så det blev ingen utvärdering innan dess. Det får bli en nu när jag successivt +börjar komma tillbaka, men bättre sent än aldrig. + +Hoppas att ni haft nytta av pythonprogrammeringen i andra kurser! + + +Unfortunately I had much to finalize before going on parental leave in January, +so there was no course evaluation then. But now I'm starting to come back to +work, so here is the course evaluation --- better late than never. + +I hope you've had use of your Python programming skills in other courses! + + +Om du tycker att någon av assarna är värda lite extra cred, skriv det här. + +If you think that one of the TAs is worth some extra cred, write that here. + +Det var inte särskilt högt deltagande under övningarna (både på campus och +online), vilket är tillfället då den huvudsakliga undervisningen sker, varför +tror du att deltagandet var lågt? + +The participation was low during the tutorials (övningar, both on campus and +online), the main part of teaching/learning takes place during theses sessions, +why do you think participation was so low? + +Vad tyckte du om det interaktiva videomaterialet (där man kan ställa frågor i +videon)? Hur kan det förbättras? + +What did you think about the interactive video material (where you can ask +questions in the videos)? How can that material be improved? + +Vad tyckte du om OLI-materialet (textmaterialet som hade interaktiva frågor i +sig)? Hur kan det förbättras? + +What did you think about the OLI-material (the text material with interactive +questions in it)? How can it be improved? diff --git a/resources/fibsnoop.py b/resources/fibsnoop.py new file mode 100644 index 00000000..cd7002e6 --- /dev/null +++ b/resources/fibsnoop.py @@ -0,0 +1,17 @@ +"""Program som skriver ut Fibonacci-serien""" + +import snoop + +snoop.install(columns="") + +def fib(n): + """Returnerar n:te talet i Fibonacci-serien""" + if n <= 0: + return 0 + if n == 1: + return 1 + + return fib(n-1) + fib(n-2) + +with snoop(depth=10): + print(f"fib(3) = {fib(3)}") diff --git a/resources/vanliga_fel/labb_2_vanliga_fel.md b/resources/vanliga_fel/labb_2_vanliga_fel.md new file mode 100644 index 00000000..832ecca0 --- /dev/null +++ b/resources/vanliga_fel/labb_2_vanliga_fel.md @@ -0,0 +1,93 @@ +Laboration 2 - Vanliga Fel +=========================== + +Vi har kollat igenom många av era Laboration 2 inlämningar och sett att det finns flera vanliga fel som görs. Nedan finns en lista på sådana fel. Om ni ser att ni har gjort ett eller flera av dessa misstag, se då till att rätta dem innan redovisningen av Laboration 3! + +Funktionskommentarer & Docstrings +----------------------- +Varje funktion måste ha en funktionskommentar enligt PEP-8, mer detaljer finns här: [PEP-257](https://peps.python.org/pep-0257/). Från PEP-257: _"The “Specification” text comes mostly verbatim from PEP 8 by Guido van Rossum."_. Det vill säga PEP-8 och PEP-257 är relaterade till varandra. PEP-8 hänvisar också tillbaks till PEP-257. + +Kortfattat, skriv funktionskommentarer på följande vis: + +```python +def factorial(n): + """Beräknar fakulteten av n, d.v.s. n!. + n är ett positivt heltal eller 0. + """ + if n > 1: + return n * factorial(n-1) + else: + return 1 +``` + +Notera att funktionskommentaren: +- Ska vara under funktionssignaturen `def namn(...):`. +- Ska använda """ """. +- Ska beskriva vad funktionen gör, parametrar, returvärden, möjliga exceptions som kan uppstå och eventuella sidoeffekter. + +För mycket global kod +----------------------- +En tumregel är att en moduls innehåll bör vara strukturerad i följande ordning: +1. Eventuell kommentar som beskriver modulen. +2. Imports +3. Globala konstanter +4. Definitioner av funktioner (och klasser om du har det) +5. Global kod + +**Mindre bra:** +```python +def f(): + """Beskrivande kommentar""" + ... + +first_value = f() + +def g(value): + """Beskrivande kommentar""" + ... + +second_value = g(first_value) +print(first_value, second_value) +``` + +**Bättre:** +```python +def f(): + """Beskrivande kommentar""" + ... + +def g(value): + """Beskrivande kommentar""" + ... + +first_value = f() +second_value = g(first_value) +print(first_value, second_value) +``` + +Om ni ser att den globala delen av koden har blivit väldigt lång, se då till att dela upp den i flera funktioner. Funktioner har åtminstone två fördelar här: 1. att de namnger och beskriver delar av koden och 2. att de möjliggör återanvändning av kod. + +**Ser vi att mycket kod finns globalt och inte har delats upp i funktioner så kan det leda till ett påpekande.** + +Inkonsekvent typografi +-------------------------- + +Om du väljer att använda snake_case för funktionsnamn, då bör alla funktioner vara skrivna på samma sätt. Samma princip gäller för variabelnamn också. + +**Fel:** +```python +def min_första_funktion(ettArgument): + ... + +def minAndraFunktion(ettArgument): + ... +``` + +**Rätt:** +```python +def min_första_funktion(ett_argument): + ... + +def min_andra_funktion(ett_argument): + ... +``` diff --git a/resources/vanliga_fel/labb_4_vanliga_fel.md b/resources/vanliga_fel/labb_4_vanliga_fel.md new file mode 100644 index 00000000..7c10d6f3 --- /dev/null +++ b/resources/vanliga_fel/labb_4_vanliga_fel.md @@ -0,0 +1,90 @@ +Laboration 4 - Vanliga Fel +=========================== + +Efter att ha kollat igenom era inlämningar i labb 4 har vi nedan sammanställt en lista över diverse olika fel som återkommer. + +Uppdelning i funktioner/metoder +----------------------- +Vi har kommit en bit in i kursen nu, och det börjar bli dags att vi blir duktiga på att dela upp programmet i lämpliga funktioner. En bra tumregel att ha i åtanke är att det ska finnas en funktion för varje sak som dit programm *gör*. Namnet på funktionen bör därmed rimligen beskriva vad det är funktionen gör. + +Antag nu att vi ska skriva ett program som gör följande: +1. Låter användaren välja hur många tal som ska läggas till i en lista. +2. Beräkna talens aritmetiska medelvärde +3. Beräkna talens varians +4. Beräkna talens standardavvikelse +5. Jämföra variansen och standardavvikelsen genom att printa ut det största talet. + +Vad som ofta händer är att programmet ser ut som nedan: + +```python +def main(): + n = int(input("Choose an amount of numbers to examine: ")) # Step 1 done here + + nums = [] + for i in range(n): + nums.append(float(input("Choose number " + str(i + 1) + ": "))) + numsSum = 0 + for number in nums: + numsSum += number + mean = (1/n)*numsSum # Step 2 done here + + squareDevFromAvg = 0 + for number in nums: + squareDevFromAvg += (number - mean)**2 + variance = (1/(n - 1))*squareDevFromAvg # Step 3 done here + + standardDev = sqrt(variance) # Step 4 done here + + if standardDev > Variance: + print("The standard deviation: " + str(standardDev) + ", is larger than the variance") + elif standardDev > Variance: + print("The variance: " + str(variance) + ", is larger than the standard deviation") + else standardDev > Variance: + print("The standard deviation: " + str(standardDev) + ", is equal to the variance") + # Step 5 done here +main() +``` + +Nu kanske du undrar vad som är fel med det som står ovan. Jag gick ju igenom samtliga steg, och allt jag gjorde låg inom en funktion. Jo, men problemet är att massvis med olika saker ligger i *samma* funktion. Ett avsevärt lämpligare sätt att hantera problemet hade varit att definiera funktioner för de flesta steg i funktionen ovan. + +```python +def createNumList(amtOfNums): + nums = [] + for i in range(amtOfNums): + nums.append(float(input("Choose number " + str(i + 1) + ": "))) + return nums + +def calcArithmeticMean(numList): + numsSum = 0 + for number in nums: + numsSum += number + mean = (1/n)*numsSum + return mean + +def calcVariance(numList): + mean = calcArithmeticMean(numList) + squareDevFromMean = 0 + for number in nums: + squareDevFromAvg += (number - mean)**2 + variance = (1/(n - 1))*squareDevFromMean + +def compareVarianceToStandardDev(variance, standardDev): + if standardDev > Variance: + print("The standard deviation: " + str(standardDev) + ", is larger than the variance") + elif standardDev > Variance: + print("The variance: " + str(variance) + ", is larger than the standard deviation") + else standardDev > Variance: + print("The standard deviation: " + str(standardDev) + ", is equal to the variance") + +def main(): + n = int(input("Choose an amount of numbers to examine: ")) # There's no need for a new function for this step ;) + nums = createNumList(n) + mean = calcArithmeticMean(nums) + variance = calcVariance(nums) + standardDev = sqrt(variance) # Since the standard deviation is the square root of the variance this may still be okay. + compareVarianceToStandardDev(variance, standardDev) + +main() +``` + +Notera hur mycket lättare det blir att följa vad det är som händer i vårt huvudprogram ovan. Om vi skulle vilja ändra i vårt huvudprogram blir detta också avsevärt lättare när vi delat upp det i funktioner som ovan.