Initial commit
This commit is contained in:
52
oppgavetekster/oving5/BinaryComputingIterator.md
Normal file
52
oppgavetekster/oving5/BinaryComputingIterator.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# Interface - BinaryComputingIterator
|
||||
|
||||
Denne oppgaven handler om en meta-iterator som kombinerer par av verdier fra to iteratorer til en ny iterator-sekvens ved hjelp av en gitt binær operasjon.
|
||||
|
||||
Meta-iteratorer er iteratorer som bruker andre iteratorer som datakilder. Se lysark om teknikken: [Forelesningslysark om meta-iteratorer](https://docs.google.com/file/d/0B9IltfWcNirndERTb1RnTGM3YWs/preview)
|
||||
|
||||
Du skal lage en ny klasse `BinaryComputingIterator`, som er en *implementasjon* av det innebygde `Iterator<Double>`-grensesnittet. Konstruktøren til `BinaryComputingIterator` skal ta inn to iteratorer og en binær operator, samt to valgfrie standardverdier. Når `next()`-metoden til `BinaryComputingIterator` blir kalt, skal en verdi hentes fra hver av de to iteratorene, den binære operasjonen utføres på disse to verdiene og resultatet returneres. Den binære operasjonen skal spesifiseres ved hjelp av det innebygde `BinaryOperator<Double>`-grensesnittet, som har en `apply`-metode som lar en beregne resultatet av den binære operasjonen. Hvordan en kan opprette funksjonelle grensesnitt kan du lese mer om på [wikisiden om dette](https://www.ntnu.no/wiki/display/tdt4100/Lambda-uttrykk+og+funksjonelle+grensesnitt+i+Java+8).
|
||||
|
||||
## BinaryComputingIterator
|
||||
|
||||
Klassen skal ha to konstruktører, en med og en uten standardverdier.
|
||||
|
||||
- `BinaryComputingIterator(Iterator<Double> iterator1, Iterator<Double> iterator2, BinaryOperator<Double> operator)`
|
||||
- `BinaryComputingIterator(Iterator<Double> iterator1, Iterator<Double> iterator2, Double default1, Double default2, BinaryOperator<Double> operator)`
|
||||
|
||||
hvor `iterator1` og `iterator2` er iteratorene som blir kombinert av `BinaryComputingIterator`, og `default1` og `default2` er standardverdier for de respektive iteratorene. Klassen må ha følgende metoder, begge spesifisert av `Iterator<Double>`-grensesnittet: Hvordan en lager en `BinaryOperator` klasse kan du se mer om lenger ned i oppgaveteksten.
|
||||
|
||||
- `boolean hasNext()` - returnerer true dersom det kan beregnes flere verdier, altså hvis begge iteratorene enten har flere verdier eller har en tilhørende standardverdi. Men merk at hasNext() returnerer uansett false, hvis begge iteratorene er tomme.
|
||||
- `Double next()` - returnerer resultatet av å bruke binæroperasjonen operator på de neste verdiene fra sub-iteratorene, og bruker standardverdier dersom en av iteratorene ikke har flere verdier.
|
||||
|
||||
Husk at ved hjelp av Java 8-syntaks kan en implementasjon av BinaryOperator skrives som `(num1, num2) -> <uttrykk>`, der `<uttrykk>` er et Java-uttrykk som brukes `num1` og `num2`. Hvis BinaryComputerIterator henter verdier fra to iteratorer med hhv. verdiene 1, 2, 3 og 3, 4, 5 og den binære operatoren er (num1, num2) -> num1 + num2, så skal sekvensen en får ut være 4, 6, 8.
|
||||
|
||||
For å håndtere tilfellet hvor den ene iteratoren gir ut flere verdier enn den andre, så skal det være mulig å gi standardverdier hhv. `default1` og `default2` for `iterator1` og `iterator2`, som vil bli brukt for å fylle inn manglende verdier. Hvis `BinaryComputerIterator` henter verdier fra to iteratorer med hhv. verdiene 6, 3, 0 og 3, 4 og den binære operatoren er `(num1, num2) -> num1 - num2` og `default2` er 2, så skal sekvensen en får ut være 3, -1, -2.
|
||||
|
||||
### Eksempel
|
||||
|
||||
`BinaryOperator`-implementasjoner kan lett skrive ved hjelp av Java 8 sin funksjonsnotasjon. Dersom man for eksempel vil bruke en addisjonsoperator kan det se slik ut:
|
||||
|
||||
```java
|
||||
Iterator<Double> iterator1 = Arrays.asList(2.0, 3.0).iterator();
|
||||
Iterator<Double> iterator2 = Arrays.asList(5.0).iterator();
|
||||
|
||||
BinaryOperator<Double> addition = (a, b) -> a + b;
|
||||
|
||||
// Opprett en ny BinaryComputingIterator som tar inn iterator1 og iterator2 og utfører addisjon på verdiene.
|
||||
BinaryComputingIterator binaryIterator = new BinaryComputingIterator(iterator1, iterator2, null, 10.0, addition);
|
||||
|
||||
binaryIterator.next(); // 7.0
|
||||
binaryIterator.hasNext() // true
|
||||
binaryIterator.next() // 13.0
|
||||
binaryIterator.hasNext() // false
|
||||
```
|
||||
|
||||
Testkode for BinaryComputingIterator er her: [interfaces/BinaryComputingIteratorTest.java](../../src/test/java/interfaces/BinaryComputingIteratorTest.java).
|
||||
|
||||
**Hjelp / mistanke om bugs**
|
||||
|
||||
Ved spørsmål eller behov for hjelp konsulter studassen din i saltiden hans / hennes. Du kan også oppsøke andre studasser på sal eller legge ut et innlegg på Piazza.
|
||||
|
||||
**Godkjenning**
|
||||
|
||||
Last opp **kildekode** på Blackboard innen den angitte innleveringsfristen. Innlevert kode skal demonstreres for stud.ass innen én uke etter innleveringsfrist. Se for øvrig Blackboard-sidene for informasjon rundt organisering av øvingsopplegget og det tilhørende øvingsreglementet.
|
||||
39
oppgavetekster/oving5/CardComparison.md
Normal file
39
oppgavetekster/oving5/CardComparison.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Interface - CardComparison-oppgave
|
||||
Denne oppgaven hander om to måter å håndtere sortering av `Card`-objekter, med grensesnittene `Comparable` og `Comparator`, som er innebygd i Java
|
||||
(java.util.Comparable, java.util.Comparator).
|
||||
|
||||
Vi tar i denne oppgaven utgangspunkt i en `Card`-klassen fra [Innkapsling - Card-oppgave](../oving3/Card.md).
|
||||
Et `Card`-objekt har en kortfarge (av typen *char*) og verdi (*int*), og sortering gjøres på disse verdiene, ved at en først sorterer på
|
||||
kortfarge og så på verdi. Siden Java har sortering innebygget, så trenger vi ikke bry oss om selve sorteringsalgoritmen,
|
||||
men fokuserer her på logikken for *sammenligning* av `Card`-objekter.
|
||||
|
||||
#### Del 1
|
||||
La `Card`-klassen implementere `Comparable` med følgende sammenligningslogikk
|
||||
|
||||
* `compareTo`-metoden skal sammenligne et kort med et annet, slik at spar vurderes som høyere enn hjerter, hjerter høyere enn ruter
|
||||
og ruter høyere enn kløver. Ved lik kortfarge skal verdien brukes, altså 1 (ess) er mindre enn 2 er mindre enn 3 osv. til og med 11 (knekt),
|
||||
12 (dame) og 13 (konge).
|
||||
|
||||
Skriv testkode som sorterer kort i en liste vha. `Collections.sort` og `Comparable-logikken`, så dere ser at det virker som forventet.
|
||||
|
||||
#### Del 2
|
||||
For å kunne sortere `Card`-objekter med annen logikk, så kan en bruke grensesnittet `Comparator`, som er et objekt som kan sammenligne
|
||||
objekter parvise. Implementer en `Comparator` (dvs. lag en klasse som *implements* `Comparator`) kalt `CardComparator`, som kan
|
||||
konfigureres (stilles inn) til å sortere med ess som høyeste kort og med en bestemt kortfarge som trumf, altså en kortfarge som regnes
|
||||
som høyere enn de andre.
|
||||
|
||||
* `CardComparator` må ha en konstruktør som tar inn en *boolean* og en *char*. *boolean*-argumentet sier om ess skal regnes som størst (`true`)
|
||||
eller minst (`false`) og *char*-argumentet angir hvilke kortfarge som er trumf. F.eks. skal et `CardComparator`-objekt laget med
|
||||
`new CardComparator(true, ' ')` rangere ess høyere enn konge og bruke standard rangering av kortfarger
|
||||
(siden trumf-argumentet ikke er en av kortfargene), og et `CardComparator`-objekt laget med `new CardComparator(false, 'C')`
|
||||
rangerer ess lavest og kløver ('C' = clubs) høyest av kortfargene (de andre kortfargene har standard rangering med spar over
|
||||
hjerter over ruter).
|
||||
|
||||
Skriv testkode som sorterer kort i en liste vha. `Collections.sort` og `Comparator-logikken`, så dere ser at det virker som forventet.
|
||||
|
||||
Testkode for del 1 og del 2 finner du her: [interfaces/CardComparatorTest.java](../../src/test/java/interfaces/CardComparatorTest.java).
|
||||
|
||||
#### Ekstraoppgave
|
||||
Utvid `CardComparator` slik at den kan konfigureres med en annen rangering av kortfargene, f.eks. slik at kløver er høyere enn ruter.
|
||||
Merk at denne fortsatt skal overstyres av evt. trumf. Nytten er altså at en kan endre rangeringsrekkefølgen på alle på én gang.
|
||||
|
||||
33
oppgavetekster/oving5/CardContainer.md
Normal file
33
oppgavetekster/oving5/CardContainer.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Interface - CardContainer-oppgave
|
||||
Denne oppgaven handler om å lage et felles grensesnitt for `CardDeck`- og `CardHand`-klassene, laget i oppgavene
|
||||
[Innkapsling - Card-oppgave](../oving3/Card.md) og
|
||||
[Objektstrukturer - Card-oppgave del 2](../oving5/Card.md).
|
||||
Her skal du lage og implementere et grensenitt kalt `CardContainer`, som spesifiserer metoder for lesing av samlinger av Card-objekter.
|
||||
|
||||
#### Del 1 - CardContainer interface
|
||||
|
||||
Definer et `CardContainer`-grensesnitt, med metodene som er felles for `CardHand` og `CardDeck`:
|
||||
|
||||
* `getCardCount()` - returnerer antall kort som dette objektet inneholder
|
||||
* `getCard(int n)` - returnerer kort nr. `n` i dette objektet
|
||||
|
||||
Gjør nødvendig endringer i `CardHand`- og `CardDeck`-klassene for å implementere `CardContainer`-grensesnittet.
|
||||
|
||||
#### Del 2 - Iterator for CardContainer
|
||||
|
||||
Lag en klasse kalt `CardContainerIterator`, som er en [Iterator](https://www.ntnu.no/wiki/display/tdt4100/Iterasjon+med+Iterator+og+Iterable)
|
||||
for alle klasser som implementerer `CardContainer`-grensesnittet. `CardContainerIterator` må ha en konstruktør som tar inn en instans av
|
||||
(en klasse som implementerer) `CardContainer`.
|
||||
|
||||
*Hint*: Merk at `CardContainerIterator` ikke vet om `CardContainer`-objektet er et `CardDeck`-objekt, et `CardHand`-objekt eller et annet
|
||||
objekt som implementerer `CardContainer`. Den har derfor ikke tilgang til de interne listene i `CardHand` og `CardDeck`.
|
||||
Hvilke metoder må alle klasser som implementerer `CardContainer` ha, og hvordan kan disse metodene brukes for å lage en
|
||||
[Iterator](https://www.ntnu.no/wiki/display/tdt4100/Iterasjon+med+Iterator+og+Iterable)?
|
||||
|
||||
Testkode for oppgaven finner du her: [interfaces/CardDeckTest.java](../../src/test/java/interfaces/CardDeckTest.java), [interfaces/CardHandTest.java](../../src/test/java/interfaces/CardHandTest.java) og [interfaces/CardContainerIteratorTest.java](../../src/test/java/interfaces/CardContainerIteratorTest.java).
|
||||
|
||||
#### Ekstraoppgave
|
||||
|
||||
La `CardContainer`-grensesnittet utvide (`extends`) `Iterable<Card>` og la `iterator()`-metoden som dermed kreves, returnere en korrekt
|
||||
konfigurert instans av `CardContainerIterator`.
|
||||
|
||||
19
oppgavetekster/oving5/CardPredicate.md
Normal file
19
oppgavetekster/oving5/CardPredicate.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# Interface - CardPredicate-oppgave
|
||||
Denne oppgaven hander om hvordan en kan bruke det funksjonelle `Predicate<T>`-grensesnittet, sammen med `CardDeck`-klassen.
|
||||
Vi tar i denne oppgaven utgangspunkt i `CardDeck`-klassen fra [Innkapsling - Card-oppgave](../oving3/Card.md).
|
||||
Et `CardDeck`-objekt har en liste med `Card`-objekter. `Card` har en kortfarge (av typen *char*) og verdi (*int*), og vi ønsker å lage metoder
|
||||
i `CardDeck` som søker opp `Card`-objekter som tilfredsstiller visse kriterier, f.eks. sjekker om spar dame finnes, teller antall hjerter eller
|
||||
henter ut alle ess. For å representere selve kriteriet brukes `Predicate<T>`-grensesnittet, som handler om å teste/sjekke om et objekt
|
||||
tilfredsstiller visse kriterium.
|
||||
|
||||
**Implementer** følgende metoder i `CardDeck`-klassen:
|
||||
|
||||
* `boolean hasCard(Predicate<Card> predicate)` - Skal returnere `true` dersom det finnes et kort som tilfredsstiller `predicate`, `false` ellers.
|
||||
* `int getCardCount(Predicate<Card> predicate)` - Skal returnere hvor mange kort som tilfredsstiller `predicate`.
|
||||
* `List<Card> getCards(Predicate<Card> predicate)` - Skal returnere en liste med de kortene som tilfredsstiller `predicate`.
|
||||
|
||||
Lag også din egen main-metode hvor du prøver hver av de tre metodene over. Du skal altså sjekke om spar dame finnes, telle antall hjerter og
|
||||
hente ut alle ess.
|
||||
|
||||
Hvordan en kan opprette funksjonelle grensesnitt kan du se på [wikisiden](https://www.ntnu.no/wiki/display/tdt4100/Lambda-uttrykk+og+funksjonelle+grensesnitt+i+Java+8) om dette.
|
||||
|
||||
35
oppgavetekster/oving5/Named.md
Normal file
35
oppgavetekster/oving5/Named.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Interface - Named-oppgave
|
||||
|
||||
Denne oppgaven handler om et grensnitt (interface) for person-navn og hvordan slike implementeres og sorteres med grensesnittet `Comparator`.
|
||||
|
||||
I denne oppgaven tar vi utgangspunkt i at en person har et navn (`String`) bestående av fornavn ("given name") og etternavn ("family name") som sammen gir personens fulle navn ("full name").
|
||||
|
||||
## Del 1
|
||||
|
||||
Definer et grensesnitt `Named` med følgende metoder:
|
||||
|
||||
- `setGivenName(String)` og `String getGivenName()` for å sette og hente fornavn
|
||||
- `setFamilyName(String)` og `String getFamilyName()` for å sette og hente etternavn
|
||||
- `setFullName(String)` og `String getFullName()` for å sette og hente personens hele navn. Argumentet til set-metoden skal være fornavn og etternavn skilt med mellomrom. Tilsvarende skal get-metoden returnere fornavn og etternavn skilt med mellomrom.
|
||||
|
||||
## Del 2
|
||||
|
||||
Lag klassene `Person1` og `Person2` som begge implementerer grensesnittet `Named`. `Person1`-klassen skal ha felter for for- og etternavn (altså `givenName` og `familyName`) og en konstruktør som tar inn to tilsvarende argumenter. `Person2` skal ha ett felt for fullt navn (`fullName`) og en konstruktør som tar inn det fulle navnet. Begge skal imidlertid implementere samme logikk, dvs. ha get- og set-metoder for fornavn, etternavn og fullt navn. Man kan anta at brukeren oppretter `Person1` og `Person2`-objekter med gyldige navn, altså trenger man ikke å implementere valideringsmetoder.
|
||||
|
||||
## Del 3
|
||||
|
||||
For å kunne sammenligne `Named`-objekter, f. eks. for å sortere en kontaktliste, kan du lage en klasse kalt `NamedComparator`, som implementerer grensesnittet [Comparator](https://www.ntnu.no/wiki/display/tdt4100/Sortering+med+Comparable+og+Comparator). `NamedComparator`-objektet skal brukes for å sammenligne navn parvis: Først på etternavn og deretter på fornavn om etternavnene er like. Dette kan gjøres ved å la `NamedComparator`-klassen implementere metoden `int compare(Named named1, Named named2)` med følgende logikk:
|
||||
|
||||
- Dersom etternavnene er ulike skal metoden
|
||||
- returnere et negativt heltall om det første etternavnet er alfabetisk ordnet før det andre,
|
||||
- eller et positivt heltall i motsatt tilfelle.
|
||||
- Dersom etternavnene er like skal metoden gjøre det samme på fornavnene. Dersom også fornavnene er like skal metoden returnere 0.
|
||||
|
||||
Skriv testkode som bruker `Collections.sort`-metoden på en `ArrayList<Named>`, for å teste om `NamedComparator`-klassen har implementert [Comparator](https://www.ntnu.no/wiki/display/tdt4100/Sortering+med+Comparable+og+Comparator) riktig.
|
||||
|
||||
Hint: For å sammenlikne to `String`-objekter kan man bruke `String`-klassens innebygde `Comparable`-metode `int compareTo(String streng2)`. Denne metoden sammenlikner en `String` med en annen alfabetisk.
|
||||
|
||||
Testkode for oppgavene finner du her:
|
||||
- [interfaces/NamedComparatorTest.java](../../src/test/java/interfaces/NamedComparatorTest.java),
|
||||
- [interfaces/Person1Test](../../src/test/java/interfaces/Person1Test.java),
|
||||
- [interfaces/Person2Test](../../src/test/java/interfaces/Person2Test.java).
|
||||
47
oppgavetekster/oving5/README.md
Normal file
47
oppgavetekster/oving5/README.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# Øving 5: Grensesnitt
|
||||
|
||||
**Øvingsmål**
|
||||
* Lære hva grensesnitt er og hvordan disse defineres
|
||||
* Lære hvordan man implementerer et grensesnitt
|
||||
* Kjenne til grunnleggende funksjonelle grensesnitt
|
||||
|
||||
**Øvingskrav**
|
||||
* Kunne lage grensesnitt og implementere disse med andre klasser
|
||||
* Kunne bruke grensesnittene Comparable<T> og Comparator<T>
|
||||
* Kunne bruke grensesnittene Iterable<T> og Iterator<T>
|
||||
|
||||
## Dette må du gjøre
|
||||
### Del 1: Programmering
|
||||
Gjør **minst to** av oppgavene under. Oppgavene (unntatt Twitter) skal lagres i `ovinger/src/main/java/interfaces`.
|
||||
Filer til Twitter-oppgaven skal lagres i `ovinger/src/main/java/interfaces.twitter`.
|
||||
|
||||
* [CardContainer](./CardContainer.md)
|
||||
* [CardComparison](./CardComparison.md)
|
||||
* [CardPredicate](./CardPredicate.md)
|
||||
* [Twitter](./Twitter.md)
|
||||
* [Named](./Named.md)
|
||||
* [BinaryComputingIterator](./BinaryComputingIterator.md)
|
||||
* [StringGrid](./StringGrid.md)
|
||||
* [RPNKalkulator med funksjonelle grensesnitt](./RPNCalc.md)
|
||||
|
||||
Disse oppgavene har noe ulik vanskelighetsgrad og omfang, og trolig stigende (i.e. CardContainer den enkleste og StringGrid den vanskeligste).
|
||||
Alle er høyst eksamensrelevante og det anbefales følgelig å ta en titt på alle sammen.
|
||||
|
||||
### Del 2: Debugging
|
||||
Gjør følgende oppgave om debugging og vis frem løsningen til studass på sal:
|
||||
|
||||
* [StringMergingIterator](./StringMergingIterator.md)
|
||||
|
||||
### Del 3: Sekvensdiagram
|
||||
Lag et [sekvensdiagram](https://www.ntnu.no/wiki/display/tdt4100/Sekvensdiagrammer) som viser samhandlingen mellom et
|
||||
`StringMergingIterator`-objekt og dens argumenter. Dvs. lag et [sekvensdiagram](https://www.ntnu.no/wiki/display/tdt4100/Sekvensdiagrammer)
|
||||
som viser hvordan `StringMergingIterator` gjennom metodekall fletter verdiene fra de to gitte iteratorene (som blir tatt inn som argumentene til
|
||||
`StringMergingIterator`-objektet).
|
||||
|
||||
### Hjelp / mistanke om bugs
|
||||
|
||||
Ved spørsmål eller behov for hjelp konsulter studassen din i saltiden hans / hennes. Du kan også oppsøke andre studasser på sal eller legge ut et innlegg på [Piazza](https://piazza.com/).
|
||||
|
||||
### Godkjenning
|
||||
|
||||
Last opp kildekode på Blackboard innen den angitte innleveringsfristen. Innlevert kode skal demonstreres for en læringsassistent innen én uke etter innleveringsfrist. Se for øvrig Blackboard-sidene for informasjon rundt organisering av øvingsopplegget og det tilhørende øvingsreglementet.
|
||||
31
oppgavetekster/oving5/RPNCalc.md
Normal file
31
oppgavetekster/oving5/RPNCalc.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Interface - RPNKalkulator med funksjonelle grensesnitt
|
||||
|
||||
Denne oppgaven handler om å gjøre det enklere å utvide en kalkulator ved å bruke det innebygde funksjonelle grensesnittet `BinaryOperator<T>`, sammen med **RPNCalc**-klassen.
|
||||
|
||||
Vi tar i denne oppgaven utgangspunkt i **RPNCalc**-klassen fra [Innkapsling - RPN-kalkulator](../oving3/RPN.md)-oppgave. Et **RPNCalc**-objekt består av en stack med tall, metoder for å håndtere stacken, og `performOperation(char)` metoden, som utfører en operasjon gitt av parameteret. For eksempel vil kallet `performOperation('*')` fjerne de to øverste tallene fra stacken, multiplisere dem, og pushe resultatet på toppen av stacken. Om operasjonene hardkodes i metoden, vil det være vanskelig å endre hva kalkulatoren kan gjøre under kjøring. Denne oppgaven går derfor ut på å gjøre det mulig å legge til og fjerne operasjoner fra kalkulatoren. Operasjoner på en og to flyttall kan representeres ved bruk av henholdsvis `UnaryOperator<Double>`- og `BinaryOperator<Double>`-grensesnittene, og operasjoner uten operander (f.eks. pi) kan representeres ved bruk av `Supplier<Double>`.
|
||||
|
||||
Implementer følgende metoder i **RPNCalc**-klassen:
|
||||
|
||||
- `boolean addOperator(char, BinaryOperator<Double>)` - Legg til en operator som virker på to tall (f.eks +) hvis operatoren ikke allerede er lagt til. Returner true hvis den nye operatoren blir lagt til
|
||||
- `void removeOperator(char)` - Fjern operatoren med tegn operatorSign
|
||||
|
||||
Du må også oppdatere `performOperation(char)` til å bruke operatorene som legges til via metodene over. Om man prøver å kalle `performOperation` med en operator som ikke er lagt til skal det utløses et `UnsupportedOperationException`-unntak.
|
||||
|
||||
## Ekstraoppgave
|
||||
|
||||
Utvid programmet til å kunne ta inn operatorer som tar inn et parameter (`UnaryOperator<Double>`, f.eks. `|` (absoluttverdi)) og ingen parametre (`Supplier<Double>`, f.eks. `p` (pi)). Husk at du må håndtere forsøk på å legge til samme operator i flere kategorier (f.eks. om man prøver å legge til `+` som både **UnaryOperator** og **BinaryOperator** må det håndteres på en god måte).
|
||||
|
||||
Dette vil innebære å legge til metodene
|
||||
|
||||
- `boolean addOperator(char, UnaryOperator<Double>)`
|
||||
- `boolean addOperator(char, Supplier<Double>)`
|
||||
|
||||
som fungerer på samme måte som `addOperator(char, BinaryOperator<Double>)`, samt å oppdatere resten av koden til å fungere med de forskjellige operatortypene.
|
||||
|
||||
**Hjelp / mistanke om bugs**
|
||||
|
||||
Ved spørsmål eller behov for hjelp konsulter studassen din i saltiden hans / hennes. Du kan også oppsøke andre studasser på sal eller legge ut et innlegg på Piazza.
|
||||
|
||||
**Godkjenning**
|
||||
|
||||
Last opp **kildekode** på Blackboard innen den angitte innleveringsfristen. Innlevert kode skal demonstreres for stud.ass innen én uke etter innleveringsfrist. Se for øvrig Blackboard-sidene for informasjon rundt organisering av øvingsopplegget og det tilhørende øvingsreglementet.
|
||||
64
oppgavetekster/oving5/StringGrid.md
Normal file
64
oppgavetekster/oving5/StringGrid.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# Interface - StringGrid-oppgave
|
||||
|
||||
Denne oppgaven handler om et grensnitt (interface) for rutenett som holder strenger (StringGrid), hvordan slike implementeres og hvordan en kan iterere gjennom et slikt rutenett ved hjelp av en [Iterator](https://www.ntnu.no/wiki/display/tdt4100/Iterasjon+med+Iterator+og+Iterable).
|
||||
|
||||
I denne oppgaven tar vi utgangspunkt i et **StringGrid**-grensesnitt som definerer metodene til et rutenett som holder strenger. Et rutenett er firkantet og består av et antall rader og kolonner. Det skal være mulig å spørre rutenettet hvilken streng som er på angitt rad og kolonne i tillegg til å endre strengen på angitt rad og kolonne. Denne oppførselen er oppsummert i det definerte **StringGrid**-grensesnittet under:
|
||||
|
||||
```java
|
||||
package interfaces;
|
||||
|
||||
/*
|
||||
An interface with methods for managing the content of a String grid.
|
||||
The grid has a number of rows (the grid's height) and columns (the grid's width).
|
||||
In each cell in the grid there is a String that can be set with the setElement method and read with the getElement method.
|
||||
*/
|
||||
public interface StringGrid {
|
||||
|
||||
// Returns the number of rows in this StringGrid
|
||||
public int getRowCount();
|
||||
// Returns the number of columns in this StringGrid
|
||||
public int getColumnCount();
|
||||
|
||||
// Returns the String at the given row and column. Throws an IllegalArgumentException if the row or column is out of range
|
||||
public String getElement(int row, int column);
|
||||
// Sets the String at the given row and column. Throws an IllegalArgumentException if the row or column is out of range
|
||||
public void setElement(int row, int column, String element);
|
||||
}
|
||||
```
|
||||
|
||||
Alle klasser som implementerer **StringGrid**-grensesnittet må støtte de fire definerte metodene.
|
||||
|
||||
## Del 1 - StringGrid-grensesnitt og implementerende StringGridImpl-klasse
|
||||
|
||||
Lag en **StringGridImpl**-klasse som implementerer **StringGrid**-grensesnittet definert over. Merk at grensesnitt ikke kan brukes til å spesifisere konstruktører, så du må selv definere en eller flere egnede konstruktører. Det er imidlertid nødvendig å implementere en konstruktør som tilsvarer den JUnit-testen forventer:
|
||||
|
||||
- `StringGridImpl(int rows, int columnCount)` - konstruktør som tar inn antall rader som `rows` og antall kolonner som `columnCount`.
|
||||
|
||||
Du står fritt til å velge hvordan metodene definert av grensesnittet skal implementeres så lenge de tilfredsstiller den definerte oppførselen. Hint: Bruk en enkel `ArrayList<String>` eller en dobbel `ArrayList<ArrayList<String>>` (se wiki-siden om [todimensjonale matriser](https://www.ntnu.no/wiki/display/tdt4100/Todimensjonale+matriser)).
|
||||
|
||||
## Del 2 - StringGridIterator-klasse
|
||||
|
||||
Det er hensiktmessig å kunne iterere over alle elementene i et rutenett som implementerer grensesnittet **StringGrid**, f.eks. når en bygger en streng i en **toString()**-metode eller skal sjekke om et spill har blitt avsluttet / vunnet. I denne deloppgaven skal du lage en slik [Iterator](https://www.ntnu.no/wiki/display/tdt4100/Iterasjon+med+Iterator+og+Iterable)-implementasjon, kalt **StringGridIterator**. Denne klassen må implementere grensesnittet `Iterator<String>`, siden **StringGrid** inneholder **String**-objekter. I tillegg til metodene som er definert i **Iterator**-grensesnittet, må **StringGridIterator** ha en konstruktør som tar imot hvilken **StringGrid** det skal itereres over og i hvilken rekkefølge elementene skal returneres i. Disse verdiene må huskes, så koden i **Iterator**-metodene kan brukes dem til å styre iterasjonen. **StringGridIterator**-klassen må altså støtte følgende konstruktør / metoder:
|
||||
|
||||
- `StringGridIterator(StringGrid, boolean)` - konstruktør som tar inn **StringGrid**-objektet som **StringGridIterator**-klassen skal iterere over i tillegg til en logisk verdi som angir om iterasjonen skal være bortover først (`rowMajor=true`) eller nedover først (`rowMajor=false`).
|
||||
- `boolean hasNext()` - returnerer true så lenge det er flere **String**-objekter igjen i **StringGrid**-objektet som ikke ennå er blitt iterert over (mao. sjekk om du har kommet til siste rute i rutenettet).
|
||||
- `String next()` - returnerer det neste **String**-objektet i rutenettet. Hvilken **String** som er den neste, avhenger av hvordan rutenettet skal itereres (mao. om `rowMajor=true` eller `rowMajor=false`).
|
||||
- `void remove()` - denne metoden skal bare utløse et unntak av typen `UnsupportedOperationException` siden det ikke skal være mulig å fjerne `String`-objekter fra rutenettet.
|
||||
|
||||
## Del 3 - Iterable-grensesnittet
|
||||
|
||||
Endre **StringGrid**-grensesnittet slik at det utvider (med extends) [**Iterable<String>**](https://www.ntnu.no/wiki/display/tdt4100/Iterasjon+med+Iterator+og+Iterable). Dette skal gjøre det mulig å skrive for-setningen under, for å gå gjennom alle elementene i rutenettet.
|
||||
|
||||
```java
|
||||
StringGrid stringGrid = ... // her initialiseres stringGrid
|
||||
// gå gjennom alle elementene i stringGrid
|
||||
for (String s: stringGrid) {
|
||||
// gjør noe med s her
|
||||
}
|
||||
```
|
||||
|
||||
Rekkefølgen som en slik for-setningen går gjennom elementene på, skal være hele første rad, så hele andre rad osv. til og med siste rad.
|
||||
|
||||
Hva slags følger får det for **StringGridImpl**? Gjør nødvendige endringer i den også, og test at det virker!
|
||||
|
||||
Testkode for del 1 og del 2 finner du her: [interfaces/StringGridTest.java](../../src/test/java/interfaces/StringGridTest.java).
|
||||
20
oppgavetekster/oving5/StringMergingIterator.md
Normal file
20
oppgavetekster/oving5/StringMergingIterator.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# Debugging - StringMergingIterator-oppgave
|
||||
|
||||
Oppgaven handler om feilsøking ("debugging") av en Iterator-implementasjon ved bruk av [**debuggeren**](https://www.ntnu.no/wiki/display/tdt4100/Bruk+av+debuggeren+i+Eclipse) i Eclipse.
|
||||
|
||||
Les først denne artikkelen om bruk av debugger i Eclipse om du ikke er kjent med dette: [Bruk av debuggeren i Eclipse](https://www.ntnu.no/wiki/display/tdt4100/Bruk+av+debuggeren+i+Eclipse)
|
||||
|
||||
Klassen **StringMergingIterator** implementerer grensesnittet [**Iterator<String>**](https://www.ntnu.no/wiki/display/tdt4100/Iterasjon+med+Iterator+og+Iterable), og leverer annenhver verdi fra to andre iteratorer av typen **Iterator<String>**. Denne iteratoren fletter altså verdiene fra to andre gitte iteratorer, og er altså en meta-iterator. Meta-iteratorer er iteratorer som bruker andre iteratorer som datakilder. Se lysark om teknikken: [Forelesningslysark om meta-iteratorer](https://docs.google.com/file/d/0B9IltfWcNirndERTb1RnTGM3YWs/preview)
|
||||
|
||||
**StringMergingIterator** har følgende konstruktør:
|
||||
|
||||
- `StringMergingIterator(Iterator<String> first, Iterator<String> second)`
|
||||
|
||||
Siden klassen implementerer **Iterator<String>** har den også følgende metoder:
|
||||
|
||||
- `boolean hasNext()` - returnerer `true` dersom iteratoren har flere verdier, `false` dersom det ikke er flere verdier.
|
||||
- `String next()` - returnerer den neste verdien fra iteratoren, eller utløser et `NoSuchElementException` dersom iteratoren er tom.
|
||||
|
||||
I denne oppgaven blir en implementasjon av **StringMergingIterator** sammen med et testprogram utdelt, men i implementasjonen av klassen har vi plantet en eller flere feil. Målet for oppgaven er å finne feilene i implementasjonen ved hjelp av [debuggeren](https://www.ntnu.no/wiki/display/tdt4100/Bruk+av+debuggeren+i+Eclipse) i Eclipse. Kjør programklassen **StringMergingIteratorProgram** i debug-modus, og bruk dette til å finne ut hvor **StringMergeIterator** gjør feil. Dersom programklassen lykkes med å få en flettet strøm med verdier har du funnet alle feilene.
|
||||
|
||||
Merk at du *ikke* skal gjøre noen endringer **StringMergingIteratorProgram**, men bruke dette programmet til å teste logikken i **StringMergingIterator**.
|
||||
53
oppgavetekster/oving5/Twitter.md
Normal file
53
oppgavetekster/oving5/Twitter.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# Interface - Sortering av TwitterAccount-objekter ved bruk av Comparator
|
||||
Denne oppgaven handler om sortering av `TwitterAccount`-objekter, ved bruk av grensesnittet `Comparator`. Oppgaven illustrerer
|
||||
hvordan man kan sortere objekter av samme klasse på ulike måter, ved hjelp av ulike implementasjoner av `Comparator`.
|
||||
|
||||
Vi tar i denne oppgaven utgangspunkt i `TwitterAccount`- og `Tweet`-klassen fra [Objektstrukturer - Twitter-oppgave](../oving5/Twitter.md).
|
||||
Et `TwitterAccount`-objekt har et brukernavn, en liste over andre brukere som følges, en liste over brukere som følger denne brukeren
|
||||
(dette `TwitterAccount`-objektet), og en liste med tweets. Vi ønsker å kunne sortere `TwitterAccount`-objekter på tre ulike parametre:
|
||||
|
||||
1. Brukernavn
|
||||
1. Antall følgere
|
||||
1. Antall tweets
|
||||
|
||||
#### Del 1
|
||||
I denne delen av oppgaven skal du lage tre ulike implementasjoner av `Comparator`-grensesnittet. `Comparator`-grensesnittet inneholder
|
||||
én metode `compare(Object o1, Object o2)`. Implementasjonen av denne metoden skal returnere:
|
||||
|
||||
* et negativt tall dersom objektet o1 skal komme før objektet o2 i en sortert rekkefølge
|
||||
* et positivt tall dersom objektet o1 skal komme etter objektet o2 i en sortert rekkefølge
|
||||
* 0 om det er likegyldig hvilken rekkefølge objektene har (dvs. de er like hverandre for den parameteren/de paremetrene de sorteres på)
|
||||
|
||||
De tre klassene du skal lage er som følger:
|
||||
|
||||
* `UserNameComparator`: sammenligner `TwitterAccount`-objektene på brukernavn, slik at brukeren “Apekatten” vil komme før
|
||||
“Bjørnen” som igjen vil komme før “Cameleonen” (dvs. leksikalsk rekkefølge - tenk rekkefølgene brukernavnene ville stått i et
|
||||
leksikon eller en ordbok)
|
||||
* `FollowersCountComparator`: sammenligner `TwitterAccount`-objektene på antall følgere, slik at brukeren med flest følgere havner først.
|
||||
* `TweetsCountComparator`: sammenligner `TwitterAccount`-objektene på antall tweets, slik at brukeren med flest tweets havner først.
|
||||
|
||||
Alle klassene skal implementere `Comparator<TwitterAccount>`.
|
||||
|
||||
#### Del 2
|
||||
I denne delen av oppgaven skal du legge til en funksjon i `TwitterAccount`-klassen som lar deg hente ut en sortert versjon av følgerene
|
||||
til dette (this) `TwitterAccount`-objektet. Funksjonen du skal implementere er som følger:
|
||||
|
||||
* `getFollowers(Comparator<TwitterAccount>)` - skal returnere en sortert kopi av følgere-listen til dette `TwitterAccount`-objektet.
|
||||
Objektene skal sorteres ved å bruke det `Comparator`-objektet som tas inn som parameter. Dersom parameteren er `null` skal du returnere
|
||||
den orginale (usorterte) versjonen av følgere-listen. Du skal ikke skrive din egen sorteringsalgoritme, men bruke
|
||||
`Collections.sort`-funksjonen fra `java.utils`-biblioteket. Merk at den opprinnelige følgere-listen skal være uforandret etter at
|
||||
denne funksjonen har blitt kjørt.
|
||||
|
||||
Testkode for oppgaven finner du her:
|
||||
- [interfaces/twitter/TwitterAccountTest.java](../../src/test/java/interfaces/twitter/TwitterAccountTest.java)
|
||||
- [interfaces/twitter/FollowersCountComparatorTest.java](../../src/test/java/interfaces/twitter/FollowersCountComparatorTest.java)
|
||||
- [interfaces/twitter/TweetsCountComparatorTest.java](../../src/test/java/interfaces/twitter/TweetsCountComparatorTest.java)
|
||||
- [interfaces/twitter/UserNameComparatorTest.java](../../src/test/java/interfaces/twitter/UserNameComparatorTest.java)
|
||||
|
||||
#### Ekstraoppgave
|
||||
Lag en klasse `TwitterAccountComparator` som implementerer `Comparator<TwitterAccount>` og sammenligner `TwitterAccount`-objekter på
|
||||
følgende måte:
|
||||
|
||||
* `TwitterAccount`-objektet med flest følgere skal komme først.
|
||||
* Dersom to `TwitterAccount`-objekter har like mange følgere skal det `TwitterAccount`-objektet med flest tweets komme først.
|
||||
* Dersom to `TwitterAccount`-objekter har like mange følgere og tweets skal `TwitterAccount`-objektene sammenlignes på brukernavn.
|
||||
Reference in New Issue
Block a user