Skip to content

Add oving 5 #6

Merged
merged 1 commit into from
Feb 9, 2026
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions oppgavetekster/oving5/BinaryComputingIterator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# 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.

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)`. Ingen av argumentene kan være `null`.
- `BinaryComputingIterator(Iterator<Double> iterator1, Iterator<Double> iterator2, Double default1, Double default2, BinaryOperator<Double> operator)`.

Her er `iterator1` og `iterator2` 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 = List.of(2.0, 3.0).iterator();
Iterator<Double> iterator2 = List.of(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: [oving5/BinaryComputingIteratorTest.java](../../src/test/java/oving5/BinaryComputingIteratorTest.java).
38 changes: 38 additions & 0 deletions oppgavetekster/oving5/CardComparison.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# 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 `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 sorteringsmetoder innebygd trenger vi ikke bry oss om selve sorteringsalgoritmen. Vi fokuserer her på logikken for *sammenligning* av `Card`-objekter, altså hvilke `Card` som skal komme før/etter andre.

Dersom du ikke har gjort `Card`-oppgaven allerede, bør du gjøre denne først. Hvis du ikke har gjort det, kan du kopiere koden fra [løsningsforslaget](https://git.ntnu.no/tdt4100/tdt4100-lf-25/blob/main/src/main/java/oving3/card/Card.java), som kommer til å være tilgjengelig etter siste demonstrasjonsfrist for øving 3.

Filen i denne oppgaven skal ligge i [`oving5/card`](../../src/main/java/oving5/card).

## Del 1

La `Card`-klassen implementere `Comparable` med følgende sammenligningslogikk

- `compareTo`-metoden skal sammenligne et kort med et annet, slik at:
- Spar kommer etter hjerter.
- Hjerter kommer etter ruter.
- Ruter kommer etter kløver.
- Ved lik kortfarge skal verdien brukes i stigende rekkefølge, altså $1$ (ess) kommer før $2$, kommer før $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, og verifiser at sammenligningslogikken er riktig implementert.

*Hint:* Returner `-1` for å sette kortet `this` før kortet som blir gitt inn, `0` dersom de er like, og `1` dersom `this` skal komme etter det gitte kortet.

## 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`. Det første argumentet sier om ess skal regnes som størst (`true`) eller minst (`false`), mens det andre 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`, og verifiser at sammenligningslogikken er riktig implementert.

Testkode for del 1 og del 2 finner du her: [oving5/card/CardComparatorTest.java](../../src/test/java/oving5/card/CardComparatorTest.java).

## Valgfri 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.
30 changes: 30 additions & 0 deletions oppgavetekster/oving5/CardContainer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# 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](../oving4/Card.md). Her skal du lage og implementere et grensenitt kalt `CardContainer`, som spesifiserer metoder for lesing av samlinger av Card-objekter.

Dersom du ikke har gjort `Card`-oppgaven allerede, bør du gjøre denne først. Hvis du ikke har gjort det, kan du kopiere koden fra [løsningsforslaget](https://git.ntnu.no/tdt4100/tdt4100-lf-25/blob/main/src/main/java/oving4/card), som kommer til å være tilgjengelig etter siste demonstrasjonsfrist for øving 4.

Filene i denne oppgaven skal ligge i [`oving5/card`](../../src/main/java/oving5/card).

## Del 1 - CardContainer interface

Definer et `CardContainer`-grensesnitt, med metodene som er felles for `CardHand` og `CardDeck`:

- `int getCardCount()` - returnerer antall kort som dette objektet inneholder.
- `Card 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`. Du kan gjøre dette ved å ta inn et argument av typen `CardContainer`, altså `CardContainerIterator(CardContainer 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: [oving5/card/CardContainerIteratorTest.java](../../src/test/java/oving5/card/CardContainerIteratorTest.java).

## Del 3 - Iterable

La `CardContainer`-grensesnittet utvide (`extends`) `Iterable<Card>` og la `iterator()`-metoden som dermed kreves, returnere en korrekt konfigurert instans av `CardContainerIterator`.

Testkode for oppgaven finner du her: [oving5/card/CardDeckTest.java](../../src/test/java/oving5/card/CardDeckTest.java) og [oving5/card/CardHandTest.java](../../src/test/java/oving5/card/CardHandTest.java).
19 changes: 19 additions & 0 deletions oppgavetekster/oving5/CardPredicate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Interface - CardPredicate-oppgave

Denne oppgaven handler 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>`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/function/Predicate.html)-grensesnittet, som handler om å teste/sjekke om et objekt tilfredsstiller visse kriterium.

Dersom du ikke har gjort `Card`-oppgaven allerede, bør du gjøre denne først. Hvis du ikke har gjort det, kan du kopiere koden fra [løsningsforslaget](https://git.ntnu.no/tdt4100/tdt4100-lf-25/blob/main/src/main/java/oving3/card/Card.java), som kommer til å være tilgjengelig etter siste demonstrasjonsfrist for øving 3.

Filen i denne oppgaven skal ligge i [`oving5/card`](../../src/main/java/oving5/card).

**Implementer** følgende metoder i `CardDeck`-klassen:

- `List<Card> getCards(Predicate<Card> predicate)` - Skal returnere en liste med de kortene som tilfredsstiller `predicate`. Argumentet kan ikke være `null` for noen av metodene.
- `int getCardCount(Predicate<Card> predicate)` - Skal returnere hvor mange kort som tilfredsstiller `predicate`.
- `boolean hasCard(Predicate<Card> predicate)` - Skal returnere `true` dersom det finnes et kort som tilfredsstiller `predicate`, `false` ellers.

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.

Testkode for oppgaven finner du her: [oving5/card/CardPredicateTest.java](../../src/test/java/oving5/card/CardPredicateTest.java).

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.
38 changes: 38 additions & 0 deletions oppgavetekster/oving5/Named.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# 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").

Filene i denne oppgaven skal ligge i [`oving5/named`](../../src/main/java/oving5/named).

## Del 1

Definer et grensesnitt `Named` med følgende metoder:

- `void setGivenName(String)` og `String getGivenName()` for å sette og hente fornavn.
- `void setFamilyName(String)` og `String getFamilyName()` for å sette og hente etternavn.
- `void 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 om sammenligning av strenger](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html#compareTo(java.lang.String)).

Testkode for oppgavene finner du her:

- [oving5/named/NamedComparatorTest.java](../../src/test/java/oving5/named/NamedComparatorTest.java),
- [oving5/named/Person1Test.java](../../src/test/java/oving5/named/Person1Test.java),
- [oving5/named/Person2Test.java](../../src/test/java/oving5/named/Person2Test.java).
49 changes: 49 additions & 0 deletions oppgavetekster/oving5/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Ø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, for å få 2 poeng må det gjøres **minst fire** av oppgavene under, og minst en av dem må være markert som vanskelig. Oppgavene skal lagres i [`src/main/java/oving5`](../../src/main/java/oving5).

- [TicketControl](./TicketControl.md) (Lett)
- [CardContainer](./CardContainer.md) (Lett)
- [CardPredicate](./CardPredicate.md) (Lett)
- [CardComparison](./CardComparison.md) (Medium)
- [Twitter](./Twitter.md) (Medium)
- [Named](./Named.md) (Medium)
- [BinaryComputingIterator](./BinaryComputingIterator.md) (Vanskelig)
- [StringGrid](./StringGrid.md) (Vanskelig)
- [RPNKalkulator med funksjonelle grensesnitt](./RPNCalc.md) (Vanskelig)

Alle oppgavene er høyst eksamensrelevante. Vi har imidlertid valgt å trappe ned kravene for `Iterator`, så spesielt `StringGrid` går dypere i temaet enn dere kan forvente å se på eksamen.

### 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). Du trenger ikke å levere inn diagrammet på Blackboard.

### 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/ntnu.no/spring2025/tdt4100).

### 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.
Loading