Rekursiva funktioner Algoritmer och datastrukturer Obligatorisk Laboration nr 5



Relevanta dokument
Tentamen OOP

Programmering A. Johan Eliasson

Tentamen Programmeringsteknik II och NV2 (alla varianter) Skriv bara på framsidan av varje papper.

Föreläsning 6: Introduktion av listor

Objektorienterad programmering D2

Objektsamlingar i Java

Arv och polymorfism i Java

Rekursion. Att tänka rekursivt Att programmera rekursivt i Java Exempel. Programmeringsmetodik -Java 254

Vem är vem på kursen. Objektorienterad programvaruutveckling GU (DIT011) Kursbok Cay Horstmann: Big Java 3rd edition.

Algoritmanalys. Genomsnittligen behövs n/2 jämförelser vilket är proportionellt mot n, vi säger att vi har en O(n) algoritm.

Grundläggande programmering med C# 7,5 högskolepoäng

TENTAMEN PROGRAMMERINGSMETODIK MOMENT 2 - JAVA, 4P

TENTAMEN: Algoritmer och datastrukturer. Läs detta! Uppgifterna är inte avsiktligt ordnade efter svårighetsgrad.

Arv: Fordonsexempel. Arv. Arv: fordonsexempel (forts) Arv: Ett exempel. En klassdefinition class A extends B {... }

Föreläsning 1 & 2 INTRODUKTION

Uppgift 1 (Oläsliga krypterade meddelanden)

Sätt att skriva ut binärträd

DUGGA: Objektorienterade applikationer. Läs detta! Uppgifterna är inte avsiktligt ordnade efter svårighetsgrad.

Programmeringsteknik med C och Matlab

Rekursion och induktion för algoritmkonstruktion

Examination i. PROGRAMMERINGSTEKNIK F1/TM1 TIN212 (Dugga) Dag: Onsdag Datum: Tid: (OBS 3 tim) Rum: V

Det finns en referensbok (Java) hos tentavakten som du får gå fram och läsa men inte ta tillbaka till bänken.

Programmering för språkteknologer II, HT2014. Rum

TENTAMEN: Algoritmer och datastrukturer. Läs detta! Uppgifterna är inte avsiktligt ordnade efter svårighetsgrad.

Tentamen, Algoritmer och datastrukturer

Objektinteraktion. Objektorienterad programmering Laboration 2. Syfte Att konstruera ett litet objektorienterat program med flera samverkande objekt.

Programmering med Java. Grunderna. Programspråket Java. Programmering med Java. Källkodsexempel. Java API-exempel In- och utmatning.

Tentamen. 2D4135 vt 2005 Objektorienterad programmering, design och analys med Java Lördagen den 28 maj 2005 kl

SMD 134 Objektorienterad programmering

Tentamen för kursen Objektorienterad programvaruutveckling GU (DIT010)

Dugga Datastrukturer (DAT036)

SCB :-0. Uno Holmer, Chalmers, höger 2 Ex. Induktiv definition av lista. // Basfall

Föreläsning 2 Objektorienterad programmering DD1332. Typomvandling

Introduktion till arv

OOP Objekt-orienterad programmering

F8 - Arv. ID1004 Objektorienterad programmering Fredrik Kilander

Föreläsning 13. Rekursion

Föreläsning 10. ADT:er och datastrukturer

Föreläsning 7. Träd och binära sökträd

725G61 - Laboration 7 Implementation av ett API. Johan Falkenjack

CHALMERS TENTAMEN. 2018/2019, lp 1 DAT050. Uno Holmer

Programmering A C# VT Ett kompendie över Programmering A (50p) i c# Stefan Fredriksson

Generiska klasser och funktioner

Dagens föreläsning. Repetition. Repetition - Programmering i C. Repetition - Vad C består av. Repetition Ett första C-program

Övningar Dag 2 En första klass

Tentamen i Objektorienterad programmering

Tentaupplägg denna gång

Tentamen Datastrukturer (DAT036)

Träd, binära träd och sökträd. Koffman & Wolfgang kapitel 6, avsnitt 1 4

Laboration 1: Figurer i hierarki

Kompilering och exekvering. Föreläsning 1 Objektorienterad programmering DD1332. En kompilerbar och körbar java-kod. Kompilering och exekvering

Tentamen TEN1 HI

Tentamen i Grundläggande Programvaruutveckling, TDA548

Idag. Javas datatyper, arrayer, referenssemantik. Arv, polymorfi, typregler, typkonvertering. Tänker inte säga nåt om det som är likadant som i C.

Objektorienterad programmering i Java

6 Rekursion. 6.1 Rekursionens fyra principer. 6.2 Några vanliga användningsområden för rekursion. Problem löses genom:

Föreläsning 5-6 Innehåll. Exempel på program med objekt. Exempel: kvadratobjekt. Objekt. Skapa och använda objekt Skriva egna klasser

Föreläsning 5-6 Innehåll

Idag. statiska metoder och variabler. private/public/protected. final, abstrakta klasser, gränssnitt, delegering. wrapper classes

Föreläsning 7 Innehåll. Rekursion. Rekursiv problemlösning. Rekursiv problemlösning Mönster för rekursiv algoritm. Rekursion. Rekursivt tänkande:

EDAA20 Föreläsning Klassen ArrayList. Viktiga operationer på ArrayList. Generisk klass

Föreläsning 3.1: Datastrukturer, en översikt

Bygga hus med LECA-stenar

Classes och Interfaces, Objects och References, Initialization

Tentaupplägg denna gång

Chapter 3: Using Classes and Objects

Tentamen, EDA501 Programmering M L TM W K V

Tentamen. Grundläggande programmering i Java A 5p, DTAA

a), c), e) och g) är olikheter. Av dem har c) och g) sanningsvärdet 1.

Det är principer och idéer som är viktiga. Skriv så att du övertygar rättaren att du har förstått dessa även om detaljer kan vara felaktiga.

Lösningsförslag, tentamen FYTA11 Javaprogrammering

Objektinteraktion. Objektorienterad programmering Laboration 2. Syfte Att konstruera ett litet objektorienterat program med flera samverkande objekt.

Påminnelse: en datatyp för bilder. Programmering. En datatyp för bilder. Spegelbild. hh.se/db2004

ITK:P1 Föreläsning 1. Programmering. Programmeringsspråket Java. Stark typning Explicit typning Strukturerat Hög säkerhet

2D1311 Programmeringsteknik för Bio1 och Bio2, vt 2003 Fiktivt prov På flervalsfrågorna är endast ett svar rätt om inget annat anges i frågan! Det rik

Länkade listor och automatisk testning

UML. Översikt UML. Relationer mellan klasser. A är ett aggregerat av B:n. Kontor aggregat av Enheter. 12 olika diagramtyper, bl.a.

Kopiering av objekt i Java

Lösningsförslag till tentamen i EDA011/EDA017 Programmeringsteknik för F, E, I, π och N 27 maj 2008

Metodanrop - primitiva typer. Föreläsning 4. Metodanrop - referenstyper. Metodanrop - primitiva typer

Textsträngar från/till skärm eller fil

Institutionen för TENTAMEN CTH HT-15 Datavetenskap TDA540. Tentamen för TDA540 Objektorienterad programmering

Introduktion till Datalogi DD1339. Föreläsning 2 22 sept 2014

Tentamen DE12, IMIT12, SYST12, ITEK11 (även öppen för övriga)

Tänk på följande: Det finns en referensbok (Java) hos tentavakten som du får gå fram och läsa men inte ta tillbaka till bänken.

Tentamen i Grundläggande Programvaruutveckling, TDA548

Uppgift 1 ( Betyg 3 uppgift )

Tentamen Programmeringsteknik II Skrivtid: Hjälpmedel: Java-bok (vilken som helst) Skriv läsligt! Använd inte rödpenna!

Programmera i C Varför programmera i C när det finns språk som Simula och Pascal??

Föreläsning 5 (6) Metoder. Metoder Deklarera. Metoder. Parametrar Returvärden Överlagring Konstruktorer Statiska metoder tostring() metoden javadoc

Tentamen Programmeringsteknik II Inledning. Anmälningskod:

OOP Objekt-orienterad programmering

Exempel på användning av arv: Geometriska figurer

if (n==null) { return null; } else { return new Node(n.data, copy(n.next));

1 Aylas bil har gått kilometer. Hur långt har den (2) gått när hon har kört en kilometer till?

public static void mystery(int n) { if (n > 0){ mystery(n-1); System.out.print(n * 4); mystery(n-1); } }

F2 Datatyper och variabler. ID1004 Objektorienterad programmering Fredrik Kilander

Objektorienterad Programkonstruktion, DD1346 FACIT. Tentamen , kl

Tentamen för TDA540 Objektorienterad Programmering. Institutionen för Datavetenskap CTH HT-17, TDA540. Dag: , Tid:

2I1049 Föreläsning 5. Objektorientering. Objektorientering. Klasserna ordnas i en hierarki som motsvarar deras inbördes ordning

Transkript:

1 (10) Syfte Att ge träning i problemlösning med rekursion. Rekursiva funktioner Algoritmer och datastrukturer Obligatorisk nr 5 Mål Den som självständigt av egen kraft löst uppgifterna i denna laboration bör ha uppnått en god förmåga att konstruera rekursiva algoritmer. Litteratur Weiss kap. 7, Wikipedia. Nyckelord: Fraktal, Koch snowflake, Mandelbrot, Polygon, Sierpinski. Programkod Givna kodavsnitt finns på kursens hemsida. Genomförande och redovisning Uppgifterna är obligatoriska. Redovisning sker i grupper om två personer inte färre, inte fler. Varje grupp skall självständigt utarbeta sin egen lösning. Samarbete mellan grupperna om övergripande principer är tillåtet, men inte plagiering. Gå till kurshemsidan och vidare till er->hur man använder Fire-systemet. Om du inte registrerat labbgrupp i Fire än: Gör laboration 0.0 innan du fortsätter! Redovisa filerna LinearRecursion.java, Mobile.java, ConcaveKoch.java, Penta.java, Sierpinski.java, samt README.txt med allmänna kommentarer om lösningen. Andra halvan av Redovisningsproceduren beskriver hur du postar materialet i Fire. Senaste redovisningsdag, se Fire. Allmänt Alla funktioner skall vara rekursiva! Lämplig arbetsgång: 1. Bestäm vad funktionen skall göra i basfallet. 2. Rekursionssteget a) Formulera ett rekursionsantagande skriv ner det! b) Konstruera lösningen med hjälp av resultatet(n) från de(t) rekursiva anropet(n) med stöd av rekursionsantagandet. Uppgifterna är inte ordnade i svårighetsgrad. Ett problem som är lätt för dig kan vara svårt för någon annan och vice versa. Kör inte fast på någon uppgift. Om du inte kommer på lösningen inom rimlig tid så gå hellre vidare och återvänd till problemet senare. Förmågan att tänka rekursivt måste du träna upp själv. Det är som med höjdhopp, du kan kanske hoppa en aning högre genom att titta på en duktig höjdhoppare, men det räcker inte högt.

2 (10) A. Linjär rekursion över heltal och listor m.m. Metodstubbar och testfall finns i filen LinearRecursion.java. Uppgift A.1 Skriv en rekursiv funktion som läser en indatarad tecken för tecken och skriver ut raden baklänges. Funktionen skall ha signaturen public static void reverseinput() och den får endast deklarera en lokal variabel av typen char för att lagra tecken. Använd (char)system.in.read() för inläsningen. När sista tecknet i raden lästs returnerar read radslutstecknet \n. Ex. Indataraden rekursion return skall ge utskriften noisruker Skulle du mot förmodan få utskriften noitareti har du gjort fel. Tips: Rita en liten figur över en indatarad. Hur skall rekursionsantagandet se ut? Formulera det med stöd av figuren. Vilka tecken kan du anta att det rekursiva anropet tar hand om? Vad skall du göra med resten? - tar det stopp så prova nästa uppgift så länge! Uppgift A.2 Konstruera en rekursiv funktion som utför multiplikation av två heltal genom upprepad addition genom att utnyttja de aritmetiska sambanden 0 n = 0 (m + 1) n = n + (m n) ( m) n = (m n) funktionen skall ha signaturen public static int multiply(int m,int n) och den får använda operatorerna ==, <, <=, >, >=, + och -, men givetvis inte. Uppgift A.3 Konstruera en rekursiv funktion som returnerar antalet decimala siffror i ett ickenegativt heltal. Funktionen skall ha signaturen public static int countdigits(int n) och den får endast använda operatorerna + och / (heltalsdivision). Glöm inte att 0 är ett ensiffrigt tal!

3 (10) Listor Listorna i de följande exemplen saknar huvudnoder eftersom dessa oftast är överflödiga vid rekursiv listhantering. En tom lista representeras alltså med null. För enkelhets skull arbetar vi med heltalslistor. public class ListNode { public int element; public ListNode next; public ListNode(int element,listnode next) { this.element = element; this.next = next; // Lägg till ett nytt element i början av l 1 public static ListNode cons(int element,listnode l) { return new ListNode(element,l); Exempel: ListNode l = cons(1,cons(2,cons(3,null))); Exempel: Följande rekursiva metod beräknar längden hos en lista: public static int length(listnode l) { if ( l == null ) return 0; else return 1 + length(l.next); Uppgift A.4 Konstruera en rekursiv funktion som returnerar en kopia av en lista. Funktionen skall ha signaturen public static ListNode copy(listnode l) och den skall returnera en ny likadan lista med samma innehåll som l. Tips: Använd cons. Uppgift A.5 Konstruera en rekursiv funktion som givet två listor returnerar en ny lista som innehåller båda listornas element. Funktionen skall ha signaturen public static ListNode append(listnode l1,listnode l2) Till exempel skall append(cons(1,cons(2,cons(3,null))), cons(4,cons(5,null))) returnera en lista med likadant innehåll som cons(1,cons(2,cons(3,cons(4,cons(5,null))))) Tips: Definiera funktionen med rekursion över den första listan och utnyttja funktionen copy i den förra uppgiften på lämpligt sätt. 1 En motsvarighet till denna funktion finns i språket LISP. Cons är en förkortning av construct.

4 (10) B. Förgreningsrekursion över träd (se förel. 10) Mobile.java Klassdefinitionen för Mobile finns på nästa sida. Studera, provkör och experimentera med programmet, ändra vikterna lite och kontrollera att balansfunktionen ger önskat resultat. Uppgift B.1 Lägg till en rekursiv metod i mobilklassen som returnerar mobilens höjd (= antal nivåer). Antag att höjden för en enkel mobil är 1. Testa på representativa fall! public int getheight() Uppgift B.2 Avlöva en mobil Lägg till en rekursiv metod som skriver ut mobilens löv. T.ex. skall mobilen m skrivas ut som 1 2 3. Utskriften skall alltså bortse från mobilens struktur och skriva ut den tillplattad. Vad behöver ändras för att istället få löven utskrivna i omvänd ordning? public void flatten() m 10 2 1 6 4 2 3 Gör sedan en funktion lik föregående men som dessutom visar strukturen med parenteser så att M skrivs ut som [(1),10,[(2),6,(3),4],2]. Utskriftsformatet för en enkel mobil är alltså ( vikt ), och för en sammansatt [ mobil, längd, mobil, längd ]. public void prettyprint() Uppgift B.3 Spegla en mobil Lägg till en rekursiv metod som gör om ett mobilobjekt till sin spegelbild. public void mirror() Efter anropet m.mirror() skall m ha formen: 2 10 4 6 1 1 3 Likhet och kloning i Java Leta upp klassen Object i Java API och studera metoderna equals och clone, speciellt vilka krav de skall uppfylla när de överskuggas i subklasser. Observera att parametertypen (högeroperanden) hos equals alltid skall vara Object vid överskuggning. Exempel på equals-överskuggningar finns i OH från F2. Uppgift B.4 När är två mobiler lika? Lägg till metoden equals i mobilklassen. Tänk först igenom vad likhet mellan mobiler bör innebära. Tips: Undvik liksom i isbalanced att jämföra flyttal med ==. public boolean equals(object rhs) 2

5 (10) Uppgift B.5 Kloning av mobiler Lägg till en rekursiv metod som returnerar en unik kopia av ett mobilobjekt: public Mobile clone() Om man definierar Mobile m = new Mobile(...); så skall m.equals(m.clone()) vara sant, men m och klonen vara två unika objekt, d.v.s. m!= m.clone(). Kontrollera att dina metoder uppfyller detta! public class Mobile { private enum MobileType {SIMPLE,COMPOSITE private MobileType type; private float weight; // Simple private float leftlength, rightlength; // Composite private Mobile left, right; // Simple case public Mobile(float weight) {... // Composite case public Mobile( Mobile left, float leftlength, Mobile right, float rightlength ) {... // Return the total mass of the mobile public float getweight() {... // Return the maximum height of the mobile public int getheight() {... // Print the leaves of the mobile public void flatten() {... // Print a structured view of the mobile public void prettyprint() {... // Determine if this mobile is balanced public boolean isbalanced() {... // Change this mobile to its mirror image public void mirror() {... public boolean equals(object rhs) {... // Return a clone of this mobile public Mobile clone() {... // Determine if this mobile is simple private boolean issimple() {...

6 (10) C. Fraktaler En fraktal kurva har egenskapen att förstorade detaljer uppvisar samma struktur som helheten. Exempel på sådana objekt är snöflingekurvor, t.ex. Koch-flingor (efter upphovsmannen Helge von Koch). Kochs kurva ser ut på följande sätt, de inringade delarna är sinsemellan likformiga. Fraktala kurvor kan definieras iterativt eller rekursivt. I fallet ovan har fyra iterationer använts. När antalet iterationer går mot oändligheten så kommer de inringande områdena efter omskalning till samma storlek visa sig ha exakt samma form. 2 Koch-flingan är uppbyggd av tre likadana fraktaler ordnade i en liksidig triangel, flingans stomme. För att definiera en sådan fraktal rekursivt konstruerar man först en generator som beskriver fraktalens grundform, oftast ett antal sammanhängande linjesegment. Därefter definieras fraktalen rekursivt enligt följande mall: 1. En fraktal av grad 0 är en rät linje. 2. En fraktal av grad N fås genom att ersätta varje linjesegment i en fraktal av grad N-1 med en skalad version av generatorn. Generatorn för Koch-fraktalen ser ut så här: 120 60 120 2 Faktum är att kurvan är oändlig men omsluter trots det en ändlig yta.

7 (10) De fyra linjesegmenten är lika långa och utgör en tredjedel av hela generatorns bredd. Generatorn har alltså form men ingen specifik storlek, den skalas till samma storlek som linjesegmentet den ersätter i punkt 2 ovan. Följande figur visar Koch-fraktaler av grad 0, 1 och 2. Sköldpaddsgrafik Fraktala kurvor ritas enklast med sköldpaddsgrafik, som kan liknas vid att styra en sköldpaddas väg genom sanden. Sköldpaddan kan vrida sig i en viss riktning och gå en viss sträcka i aktuell riktning. När den går lämnar den ett spår (en linje) efter sig. Sköldpaddsgrafik lämpar sig väl för fraktalritning eftersom man slipper att räkna med koordinater. Här följer en enkel javaklass (utan detaljer): public class Turtle { // draw a line in the current direction, distance long public void walk(double distance) // jump distance long in the current direction without drawing public void jump(double distance) // jump to point p public void jumpto(point p) // turn the drawing direction angle degrees public void turn(double angle) // change the drawing direction to absolute angle public void turnto(double angle) Vi kommer att definiera fraktala snöflingor som klasser. Den abstrakta klassen public abstract class Flake { protected Turtle turtle = null; // initiated in subclasses public abstract void draw(turtle turtle, int level, double size); blir utgångspunkt för ett antal fraktalklasser. Här är Kochflingans klass: public class ConvexKoch extends Flake { public void draw(turtle turtle, int n, double size) { this.turtle = turtle; turtle.turnto(0.0); // Draw a triangular structure of three fractals turtle.turn(-60.0); drawside(n,size); turtle.turn(120.0); drawside(n,size); turtle.turn(120.0); drawside(n,size); forts.

8 (10) private void drawside(int n,double size) { if ( n == 0 ) turtle.walk(size); // dra en rät linje else { double l = size/3.0; drawside(n-1,l); turtle.turn(-60.0); drawside(n-1,l); turtle.turn(120); drawside(n-1,l); turtle.turn(-60); drawside(n-1,l); I mappen fraktaler finns färdiga klasser och ett GUI som kan användas som testbänk för olika fraktalklasser. Uppgifterna är nu att konstruera ett par andra fraktaler med utgångspunkt från exemplen ovan. När du definierat en ny subklass till Flake så är det bara att addera ett objekt av den till mappen i klassen FlakeDB:s konstruktor, så dyker det automatiskt upp en ny inmatningsruta för fraktalens grad i GUI:t. Den färdiga koden innehåller Koch-flingan ovan, samt Benoit Mandelbrots PS-kurva, en lite mer komplicerad kurva med fraktal dimension 2, vilket innebär att den fyller hela ytan när antalet iterationer går mot oändligheten (testa med N = 5). Här efter 3 iterationer: (Om du råkar skriva in för stora tal tar beräkningen för lång tid. Gå då tillbaks till verktyget och avbryt exekveringen, det kan tyvärr inte göras i nuvarande version av GUI:t)

9 (10) Uppgift C.1 Konkav Koch-flinga Definiera klassen ConcaveKoch. De tre första iterationerna ser ut så här: Tips: Denna flinga har samma stomme och generator som Koch-flingan vi sett tidigare. Det är faktiskt bara en liten detalj som skiljer. Uppgift C.2 Penta Flingans fem första iterationer: Stommen är en liksidig pentagon. Identifiera generatorn genom att studera figurerna och definiera klassen Penta! Tips: Denna kurva korsar sig själv vilket bidrar till att göra bilderna ovan lite mer svårtolkade än vanligt. Uppgift C.3 Sierpinskitriangel Fraktalens fyra första iterationer: Generatorn är här inte en linje utan en liksidig triangel. I varje steg ersätts generatorn med tre förminskade versioner av generatorn. Definiera klassen Sierpinski!

10 (10) Penta efter fyra iterationer