Kodprov 2018-08-30
Table of Contents
1 Instruktioner
Öppna en terminal och kör följande kommandon:
cd
(detta tar dig till din hemkatalog)mkdir kodprov
180830
cd kodprov
180830
curl http://wrigstad.com/ioopm/
mandel.zip
-o k.zip
unzip k.zip
Nu har du fått ett antal filer och kataloger:
uppgift1
– katalog med alla filer för uppgift 1
uppgift2
– katalog med alla filer för uppgift 2
Makefile
– en makefil för att lämna in kodprovet
1.1 Inlämning och rättning
Inlämning går till så här: ställ dig i katalogen
kodprov
180830
.
Om du har tappat bort dig i filsystemet kan du skriva cd; cd
kodprov
180830
. Nu kan du skriva make handin
för att lämna in
kodprovet. När du kör detta kommando skapas en zip-fil med de
filer som du har uppmanats att ändra i (inga andra), och denna fil
sparas sedan på en plats där vi kan rätta provet. Vid behov kan du köra make handin
flera gånger – endast den sista inlämningen räknas.
Den automatiska rättningen kommer att gå till så att vi kör dina inlämningar mot omfattande testfall. Du har fått ut mindre omfattande testfall eller motsvarande i detta prov som du kan använda som ett stöd för att göra en korrekt lösning. Experiment med att lämna ut mer omfattande tester har visat sig skapa mer stress än hjälp (tänk fler testfall som fallerar)1.
Om du har löst uppgifterna på rätt sätt och testfallen som du får ut passerar är du förhoppningsvis godkänd.
1.2 Allmänna förhållningsregler
- Samma regler som för en salstenta gäller: inga mobiltelefoner, inga SMS, inga samtal med någon förutom vakterna oavsett medium.
- Du måste kunna legitimera dig.
- Du får inte på något sätt titta på eller använda gammal kod som du har skrivit.
- Du får inte gå ut på nätet.
- Du får inte använda någon annan dokumentation än man-sidor och böcker.
- Det är tillåtet att ha en bok på en läsplatta, eller skärmen på en bärbar dator. Inga andra program får köra på dessa maskiner, och du får inte använda dem till något annat än att läsa kurslitteratur.
- Du måste skriva all kod själv, förutom den kod som är given.
- Du får använda vilken editor som helst som finns installerad på institutionens datorer, men om 50 personer använder Eclipse samtidigt så riskerar vi att sänka servrarna.
Vi kommer att använda en blandning av automatiska tester och granskning vid rättning. Du kan inte förutsätta att den kod du skriver enbart kommer att användas för det driver-program som används för testning här. Om du t.ex. implementerar en länkad lista av strängar kan testningen ske med hjälp av ett helt annat driver-program än det som delades ut på kodprovet.
I mån av tid har vi ofta tillämpat ett system där vi ger rest för mindre fel. Det är oklart om detta system tillämpas för detta kodprov men det betyder att det är värt att lämna in partiella lösningar, t.ex. en lösning som har något mindre fel.
Lycka till!
2 C-uppgift
2.1 En cirkulärlänkad lista
Denna uppgift går ut på att implementera en cirkulärlänkad, dubbellänkad lista.
En dubbellänkad lista är en lista där varje nod har en pekare, inte bara till sitt nästa element, utan också till sitt föregående. En sådan lista är lämplig att använda när man vill kunna traversera listan i “båda riktningar”.
En cirkulärlänkad lista är en lista som inte termineras genom
att den sista länkens next
-pekare pekar på NULL
, utan där den
sista länken pekar på den första länken. Följande loop skulle
i en cirkulärlänkad lista, alltså inte terminera:
while (cursor) { printf("%d", cursor->element); // Skriv ut elementet cursor = cursor->next; // Gå vidare till nästa element }
while%20%28cursor%29%0A%20%20%7B%0A%20%20%20%20printf%28%22%25d%22%2C%20cursor-%3Eelement%29%3B%20%2F%2F%20Skriv%20ut%20elementet%0A%20%20%20%20cursor%20%3D%20cursor-%3Enext%3B%20%2F%2F%20G%C3%A5%20vidare%20till%20n%C3%A4sta%20element%0A%20%20%7D%0A
En lista som är både dubbellänkad och cirkulärlänkad går alltså
att traversera åt båda hållen och termineras icke av NULL
i
någondera riktning. För enkelhets skull kommer listans element att
vara heltal.
Din uppgift är att skriva färdigt programmet list.c
så att det
implementerar alla funktionerna i list.h
och passerar testerna i
driver.c
. Vad du måste göra är klart markerat med ///TODO
i
list.c
.
#ifndef __kodprov__ #define __kodprov__ #include <stdbool.h> typedef struct list list_t; /// Skapar en tom lista list_t *ioopm_list_create(); /// Tar bort en lista ur minnet void ioopm_list_destroy(list_t *list); /// Stoppar in ett element FÖRST i listan void ioopm_list_prepend(list_t *list, int element); /// Stoppar in ett element SIST i listan void ioopm_list_append(list_t *list, int element); /// Tar bort elementet på plats index. Negativa /// index räknas bakifrån, dvs. -1 är sista elementet. /// Valida index är [-N,-1] och [0,N) för en lista med N element. /// \returns true om elementet togs bort. bool ioopm_list_remove(list_t *list, int index); /// Returnerar elementet på plats index. Negativa /// index räknas bakifrån, dvs. -1 är sista elementet. /// Valida index är [-N,-1] och [0,N) för en lista med N element. /// \returns en pekare till int:en i listan -- NULL om den inte fanns int *ioopm_list_get(list_t *list, int index); /// Kontrollerar om en lista innehåller ett viss element /// \returns true om elementet finns i listan. bool ioopm_list_contains(list_t *list, int element); /// OBS! Implementeras i O(n) tid, inte O(1). /// \returns antalet element i listan. int ioopm_list_size(list_t *list); #endif
%23ifndef%20__kodprov__%0A%23define%20__kodprov__%0A%0A%23include%20%3Cstdbool.h%3E%0A%0Atypedef%20struct%20list%20list_t%3B%0A%0A%2F%2F%2F%20Skapar%20en%20tom%20lista%20%0Alist_t%20%2Aioopm_list_create%28%29%3B%20%0A%0A%2F%2F%2F%20Tar%20bort%20en%20lista%20ur%20minnet%0Avoid%20ioopm_list_destroy%28list_t%20%2Alist%29%3B%20%0A%0A%2F%2F%2F%20Stoppar%20in%20ett%20element%20F%C3%96RST%20i%20listan%0Avoid%20ioopm_list_prepend%28list_t%20%2Alist%2C%20int%20element%29%3B%0A%0A%2F%2F%2F%20Stoppar%20in%20ett%20element%20SIST%20i%20listan%0Avoid%20ioopm_list_append%28list_t%20%2Alist%2C%20int%20element%29%3B%0A%0A%2F%2F%2F%20Tar%20bort%20elementet%20p%C3%A5%20plats%20index.%20Negativa%0A%2F%2F%2F%20index%20r%C3%A4knas%20bakifr%C3%A5n%2C%20dvs.%20-1%20%C3%A4r%20sista%20elementet.%0A%2F%2F%2F%20Valida%20index%20%C3%A4r%20%5B-N%2C-1%5D%20och%20%5B0%2CN%29%20f%C3%B6r%20en%20lista%20med%20N%20element.%0A%2F%2F%2F%20%5Creturns%20true%20om%20elementet%20togs%20bort.%0Abool%20ioopm_list_remove%28list_t%20%2Alist%2C%20int%20index%29%3B%20%0A%0A%2F%2F%2F%20Returnerar%20elementet%20p%C3%A5%20plats%20index.%20Negativa%0A%2F%2F%2F%20index%20r%C3%A4knas%20bakifr%C3%A5n%2C%20dvs.%20-1%20%C3%A4r%20sista%20elementet.%0A%2F%2F%2F%20Valida%20index%20%C3%A4r%20%5B-N%2C-1%5D%20och%20%5B0%2CN%29%20f%C3%B6r%20en%20lista%20med%20N%20element.%0A%2F%2F%2F%20%5Creturns%20en%20pekare%20till%20int%3Aen%20i%20listan%20--%20NULL%20om%20den%20inte%20fanns%0Aint%20%2Aioopm_list_get%28list_t%20%2Alist%2C%20int%20index%29%3B%20%0A%0A%2F%2F%2F%20Kontrollerar%20om%20en%20lista%20inneh%C3%A5ller%20ett%20viss%20element%0A%2F%2F%2F%20%5Creturns%20true%20om%20elementet%20finns%20i%20listan.%0Abool%20ioopm_list_contains%28list_t%20%2Alist%2C%20int%20element%29%3B%20%0A%0A%2F%2F%2F%20OBS%21%20Implementeras%20i%20O%28n%29%20tid%2C%20inte%20O%281%29.%20%0A%2F%2F%2F%20%5Creturns%20antalet%20element%20i%20listan.%20%0Aint%20ioopm_list_size%28list_t%20%2Alist%29%3B%20%0A%23endif%0A
2.1.1 Tips 1: sentinel i listan
Om du implementerar din länkade lista så att den alltid har en
nod, som är tom – en såkallad sentinel – som första-nod,
förenklar du implementationen avsevärt (eftersom du inte behöver
göra några NULL
-test för en tom lista). Då kan prepend E
implementeras som “stoppa E efter första-noden” och append E som
“stoppa E före första-noden”. Sentinel-noden går inte att ta bort,
utan försvinner först vid destroy.
2.1.2 Tips 2: rita!
Detta är verkligen en uppgift där det lönar sig att rita upp vad som händer!
2.1.3 Icke-funktionella krav
- Insättning med append och prepend skall ske i \(O(1)\) (uppnås i och med att det är en länkad lista och inte en arraylista).
- Iteration baklänges och framlänges skall vara lika effektiva och ske i \(O(n)\) där \(n\) är antalet element (uppnås om listan är dubbelänkad).
- Interna pekare mellan noder i listan får inte vara
NULL
(uppnås om listan är cirkulärlänkad). ioopm_list_size()
skall implementeras genom att samtliga länkar räknas. Det skall alltså inte sparas en storlek på listan någonstans somioopm_list_size()
returnerar.- Ditt program får inte läcka minne. Efter att
ioopm_list_destroy()
har körts på en lista skall listan vara helt borttagen ur minnet. Vidare skallioopm_list_remove()
städa bort noder ur minnet löpande.
2.1.4 Testa din lösning (funktionella tester)
Du kan kompilera din lösning mot driver.c
som utför enklare
operationer på listan och rapporterar eventuella funna fel. Detta
gör du med hjälp av den medföljande makefilen enligt följande:
make test
- kompilerar driver.c och list.c till a.out och kör
make memtest
- som make test, men kör i valgrind för att hitta läckage
Du får inte ändra i någon annan fil än list.c
eftersom det är
den enda fil som lämnas in.
3 Java-uppgift
Uppgiften går ut på att implementera en mängd (eng. set) av
godtyckliga element som alla implementerar interfacet CompareTo
,
t.ex. \(\{1, 3, 5, 8\}\) eller \(\{\) “abba”, “cat empire”, “donovan”
\(\}\). Man kan lägga till element i mängden (upp till en viss
storlek) och fråga mängden om ett visst element är medlem i den
eller inte.
OBS! Skriv all kod i filen Set.java
som du måste skapa själv.
3.1 Tillstånd
For enkelhets skull skall alla element i mängden att lagras i en
array (kallad elements
) vars storlek är fix – dvs. när man
skapar en mängd bestäms hur många element den maximalt kan rymma.
Elementen i arrayen skall vara ordnade dvs. följande skall alltid
gälla för i >= 0
och i+1 < elements.length
:
T a = elements[i]; T b = elements[i+1]; a.compareTo(b) < 0; /// är alltid sant
T%20a%20%3D%20elements%5Bi%5D%3B%0AT%20b%20%3D%20elements%5Bi%2B1%5D%3B%0Aa.compareTo%28b%29%20%3C%200%3B%20%2F%2F%2F%20%C3%A4r%20alltid%20sant%20%0A
Eftersom det är lite meckigt att skapa en array av generisk typ i Java ger jag ut den koden här:
T[] elements = (T[]) new Comparable[maxCapacity];
T%5B%5D%20elements%20%3D%20%28T%5B%5D%29%20new%20Comparable%5BmaxCapacity%5D%3B%0A
Detta leder dock till klagomål från kompilatorn: Note: Set.java uses unchecked or unsafe operations. Det är OK.
Det går förstås också bra – eller bättre! – att ha en array av Comparable[]
.
Klassen Set
är deklarerad enligt följande:
public class Set<T extends Comparable<T>>
public%20class%20Set%3CT%20extends%20Comparable%3CT%3E%3E%0A
dvs. typen Set<Foo>
betyder en mängd av element av typen Foo
sådana att Foo instanceof Comparable<Foo>
alltid gäller.
Interfacet CompareTo
definierar en metod, int compareTo(T o)
sådan att:
a.compareTo(b)
returnerar ett negativt tal oma
kommer föreb
i den ordning som implementerasa.compareTo(b)
returnerar 0 oma
ochb
är likaa.compareTo(b)
returnerar ett positivt tal oma
kommer efterb
i den ordning som implementeras
(Alltså ekvivalent med t.ex. hur strcmp()
fungerar i C.)
Eftersom Foo instanceof Comparable<Foo>
alltid gäller så kan
instanser av Foo
endast jämföras med andra instanser av Foo
med hjälp av compareTo()
.
Du behöver alltså minst en array och en maxkapacitet.
3.2 Beteende
Mängden skall stödja följande operationer:
- Konstruktor som tar som argument maximalt antal element
- Konstruktor som inte tar några argument utan delegerar till den första konstruktorn med 16 som maximalt antal element
public boolean add(T elem)
som lägger tillelem
i mängden om utrymme finns ochelem
inte redan är medlem. Huruvida ett element är medlem eller inte avgörs med hjälp avcompareTo()
.private int indexOf(T elem)
som returnerar platsen i arrayen därelem
finns, alternativt borde ha funnits om elementet fanns med. För att kunna skilja mellan finns och borde ha funnits använder vi negativa index för det senare, och eftersom0
är varken positivt eller negativt ökar vi negativa index med 1. Alltså:-5
betyder att “om det sökta elementet hade funnits i arrayen skulle det ha funnits på index 4” medan4
betyder att “det sökta elementet finns på plats 4”. På samma sätt betyder-1
“skulle ha funnits först i arayen”, och0
“finns först i arrayen”.public boolean contains(T elem)
som returnerartrue
omelem
finns i mängden, annarsfalse
.int size()
som returnerar antalet element i mängden, initialt 0.- En jämförelsemetod (vanlig
equals()
).a.equals(b)
skall returneratrue
oma
ochb
är alias, eller oma
ochb
innehåller identiska objekt. Observera att det inte går att göra en typsäker version av denna metod! Kompilatorn kommer att klaga på Note: Set.java uses unchecked or unsafe operations.. Bry dig inte om detta. - Plus alla andra privata metoder som du kan tänkas behöva.
3.3 Icke-funktionella krav
- Enda sättet ändra i mängden skall vara genom
add()
. - Ett försök att skapa en mängd med negativ maxkapacitet, eller
anropa
add()
ellercontains()
mednull
skall kasta undantagetIllegalArgumentException
. (Detta är ett standard-exception som finns.) - Vid överskridande av maxkapaciteten skall ett
SetFullException
kastas. (OBS! Detta måste du själv skriva! Gör det iSet.java
och “fort” – annars kan inte ensDriver.java
kompilera.) Observera att anrop tilladd()
med element som redan är medlemmar i mängden inte växer mängden! - Du skall använda dig av
indexOf()
i implementationen avadd()
för att ta reda på om det nya elementet redan finns och om inte – var det skall placeras.
3.4 Testning
Du kan testa din inlämning med hjälp av make
. Då körs programmet
i Driver.java
som skapar några mängder och utför några få
operationer på dem. Vid eventuella fel skrivs ett meddelande ut.
make test
kör alla test utan att avbryta vid fel.
make test-hard
kör alla test och avbryter vid fel.
Questions about stuff on these pages? Use our Piazza forum.
Want to report a bug? Please place an issue here. Pull requests are graciously accepted (hint, hint).
Nerd fact: These pages are generated using org-mode in Emacs, a modified ReadTheOrg template, and a bunch of scripts.
Ended up here randomly? These are the pages for a one-semester course at 67% speed on imperative and object-oriented programming at the department of Information Technology at Uppsala University, ran by Tobias Wrigstad.