Algoritmer och datastrukturer Frivilliga bonusuppgifter

Relevanta dokument
Inlämningsuppgift MiniPlotter

Automatateori (2) Idag: Sammanhangsfria språk. Dessa kan uttryckas med Grammatik PDA

Föreläsning 7: Syntaxanalys

Föreläsning 3. Stack

Kompilatorer och interpretatorer

Linjärt minne. Sammanhängande minne är ej flexibelt. Effektivt

DD1361 Programmeringsparadigm. Formella Språk & Syntaxanalys. Per Austrin

Klassdeklaration. Metoddeklaration. Parameteröverföring

Tentamen, Algoritmer och datastrukturer

F3: Recursive descent, tokenisering, avbildningar och undantag. Carl Nettelblad

Datastrukturer i kursen. Föreläsning 8 Innehåll. Träd rekursiv definition. Träd

Definition. Mängden av reguljära uttryck på alfabetet Σ definieras av. om α och β är reguljära uttryck så är (α β) ett reguljärt uttryck

TENTAMEN I PROGRAMSPRÅK -- DVG C kl. 08:15-13:15

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

Föreläsning 3. Stack

Obligatorisk uppgift: Numerisk kalkylator

Reguljära uttryck Grammatiker Rekursiv nedåkning Allmänna kontextfria grammatiker. Syntaxanalys. Douglas Wikström KTH Stockholm

Föreläsning 9 Innehåll

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

Sätt att skriva ut binärträd

Alfabeten, strängar och språk. String

DD1361 Programmeringsparadigm. Formella Språk & Syntaxanalys. Per Austrin

Inlämningsuppgiften. Föreläsning 9 Innehåll. Träd. Datastrukturer i kursen

Obligatorisk uppgift 5

ADT Kö. Seminarium 4 Köer och Stackar Innehåll. Operationer. ADT Stack. Definition. Definition

Programmering A. Johan Eliasson

Kungl. Tekn. Högskolan Förel 1, bild 1 Föreläsning 1: Introduktion ffl Kursinnehåll ffl Javarepetition ffl Referenser ffl Nyckelordet static ffl Klass

Kompilatorer och interpretatorer

Idag: Reguljära språk Beskrivs av Reguljära uttryck DFA Grammatik

Tentamen i. TDDC67 Funktionell programmering och Lisp

Parsning. TDP007 Konstruktion av datorspråk Föreläsning 6. Peter Dalenius Institutionen för datavetenskap

Anmälningskod: Lägg uppgifterna i ordning. Skriv uppgiftsnummer (gäller B-delen) och din kod överst i högra hörnet på alla papper

Rekursion och induktion för algoritmkonstruktion

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

TENTAMEN: Algoritmer och datastrukturer. Läs detta!

Obligatorisk uppgift 5: Symbolisk kalkylator

Rekursion och induktion för algoritmkonstruktion

DAI2 (TIDAL) + I2 (TKIEK)

Föreläsning 7: Syntaxanalys

Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson

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

Grammatik. BNF-grammatik

Programmering II (ID1019) :00-11:00

Den som bara har en hammare tror att alla problem är spikar

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

Parameteröverföring. Exempel. Exempel. Metodkropp

Tentamen i Grundläggande programmering STS, åk 1 lördag

public boolean containskey(string key) { return search(key, head)!= null; }

Föreläsning 13. Träd

Introduktion till programmering SMD180. Föreläsning 4: Villkor och rekursion

TENTAMEN: Objektorienterad programmering. Läs detta! Skriv din tentamenskod på varje blad (så att vi inte slarvar bort dem).

kind spelling Scanning

kl Tentaupplägg

Grundläggande datalogi - Övning 9

Föreläsning 3 Innehåll. Generiska klasser. Icke-generisk lista ArrayList, skiss av implementering. Icke-generisk lista Risk för fel

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

PROMETHEUS. Ett typat, objektorienterat programmeringsspråk av Tim Andersson.

TDDC74 Programmering: Abstraktion och modellering Tentamen, onsdag 9 juni 2016, kl 14 18

Backcode. Jonathan Crusoe TDP019 Projekt: Datorspråk Linköpings universitet

Tentamen. DD2385 Programutvecklingsteknik vt 2013 Onsdagen den 22 maj 2013 kl Hjälpmedel: penna, suddgummi, linjal

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

Föreläsning 9 Innehåll

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

OMTENTAMEN I PROGRAMSPRÅK -- DVG C kl. 08:15-13: 15

Algoritmanalys. Inledning. Informationsteknologi Malin Källén, Tom Smedsaas 1 september 2016

Programmeringsmetodik DV1 Programkonstruktion 1. Moment 4 Om rekursion. PK1&PM1 HT-06 moment 4 Sida 1 Uppdaterad

C++ Funktioner 1. int summa( int a, int b) //funktionshuvud { return a+b; //funktionskropp } Värmdö Gymnasium Programmering B ++ Datainstitutionen

Grafik, grafiska användargränssnitt och rörliga bilder

F4. programmeringsteknik och Matlab

Lösningsförslag till exempeltenta 2

BEGREPP HITTILLS FÖRELÄSNING 2 SAMMANSATTA UTTRYCK - SCHEME DATORSPRÅK

Instruktioner - Datortentamen TDDD73 Funktionell och imperativ programmering i Python

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

Tentamen Datastrukturer (DAT036)

PROGRAMMERING-Java Omtentamina

TENTAMEN: Algoritmer och datastrukturer. Läs detta!

Tentamen i Grundläggande programmering STS, åk 1 fredag

Introduktion till algoritmer - Lektion 4 Matematikgymnasiet, Läsåret Lektion 4

Tentamen i Algoritmer & Datastrukturer i Java

Tentamen ID1004 Objektorienterad programmering October 29, 2013

Summera godtyckligt antal tal. Programkonstruktion. Moment 4 Om rekursion. Fullständigt resonemang för summeringen. Analys av summeringsproblemet

Procedurer och villkor. Rekursiva procedurer. Exempel: n-fakultet

TENTAMEN PROGRAMMERINGSMETODIK MOMENT 2 - JAVA, 4P

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

Procedurer och villkor

Obligatorisk uppgift: Symbolisk kalkylator

LÖSNINGSFÖRSLAG Programmeringsteknik För Ing. - Java, 5p

Föreläsning 8 - del 2: Objektorienterad programmering - avancerat

Uppgiften är att beskriva en kvadrat i ett Java program. En första version av programmet skulle kunna se ut så här:

Två fall: q Tom sekvens: () q Sekvens av element: (a b c) ; (sum-rec '(2 4 6)) = 12. q Första elementet uppfyller vissa villkor: (2 a b c)

Datalogi I, grundkurs med Java 10p, 2D4112, Fiktiv tentamen, svar och lösningar och extra kommentarer till vissa uppgifter 1a) Dividera förs

Anmälningskod: Lägg uppgifterna i ordning. Skriv uppgiftsnummer (gäller B-delen) och din kod överst i högra hörnet på alla papper

Uppgift 1a (Aktiekurser utan poster)

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

Programmering C: Tentamen of 5 Prioritet och associativitet hos operatorerna i C De viktigaste operatorerna: Prioritet Kategori Operator

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

Tentamen i Introduktion till programmering

Klassen BST som definierar binära sökträd med tal som nycklar och enda data. Varje nyckel är unik dvs förekommer endast en

Kontextfria grammatiker

TENTAMEN: Algoritmer och datastrukturer. Läs detta!

Transkript:

1 (7) Algoritmer och datastrukturer Frivilliga bonusuppgifter Syfte Att ge ytterligare programmeringsträning i allmänhet, och i problemlösning med rekursion i synnerhet. Uppgifterna ger också några inblickar i syntax för programmeringsspråk. Mål Ett bra tentamensresultat. Genomförande och redovisning Uppgifterna löses och redovisas individuellt. Samarbete är ej tillåtet! Lösningar som förefaller vara kopierade beaktas ej. Vid oklarheter kan kontrollfrågor ställas. Kursledaren och assistenterna får givetvis tillfrågas om något är oklart. Du får utnyttja dina bonuspoäng vid ett av de tre tentamenstillfällena för årets kurs i juni, augusti eller oktober. Lösningarna lämnas in i form av pappersutskrift vid tentamenstillfället. Häfta ihop bladen, inga plastpärmar! Märk lösningarna med din tentamenskod (ej namn) och lämna dem till skrivningsvakten. Skicka inga lösningar med e-post! Lösningar rättas endast om bonuspoäng bedöms kunna bidra till högre skrivningsbetyg. Bonuspoäng adderas till skrivningspoängsumman innan skrivningsbetyget sätts. Bonuspoäng kan aldrig överstiga 1/6-del av poänggränsen för ett betyg, d.v.s. max 4 poäng för betyget 3 (gräns 24p), max 6 poäng för betyget 4 (gräns 36p) och max 8 poäng för betyget 5 (gräns 48p). Poängtalen som står efter uppgifterna avser maximala poäng för lösningar av god kvalitet. Litteratur För del B: Weiss kap. 11.2. Programkod Givna kodavsnitt finns på kursens hemsida under laborationsfliken i filen bonus.zip. Allmänt Alla funktioner skall vara rekursiva! (med några triviala undantag)

2 (7) Uppgift 1 Växla pengar Skriv en rekursiv funktion som returnerar hur många olika sätt det finns att växla ett belopp i hela kronor givet en uppsättning mynt- och sedelvalörer. int[] sekvalues = { 1, 5, 10, 20, 50, 100, 500, 1000 ; // parameters // amount the amount to be changed // val the different values arranged in ascending order // n the number of different values public static int change( int amount, int[] val, int n ); Exempel: Beloppet 12 kronor kan växlas på fyra olika sätt: 12x1kr, 10kr+2x1kr, 2x5kr+2x1kr, 5kr+7x1kr. Så change(12,sekvalues,sekvalues.length) skall returnera 4. (2 p) Uppgift 2 Permutationer a) Konstruera en funktion som skriver ut alla permutationer av en sträng. T.ex. skall anropet permutations( abc ); ge utskriften abc acb bac bca cab cba Ledning: Permutationerna av strängen S fås genom att för varje tecken c i S addera c till varje permutation av S där S fås genom att ta bort c ur S. Ex. addera a till varje permutation av bc, b till varje permutation av ac, och c till varje permutation av ab. Skriv en rekursiv hjälpfunktion som bygger upp en permutation i en extra ackumulerande parameter (för exempel på tekniken se fibiter i den första föreläsningen om rekursion). Funktionen får innehålla en loop. Anropa hjälpfunktionen från permutations. (2 p) b) Ange en lämplig tidsfunktion för permutations(s), T(n), där n är strängen s:s längd. Sätt upp rekurensekvationer för T(n) och lös dem. Redovisa härledningen och lösningen på formen T(n) = O(f(n)). (1 p)

3 (7) Syntax och grammatiker Inledning Övningen ger förhoppningsvis lite insikt i rekursiv parsning och evaluering av aritmetiska uttryck - hur enkelt det kan bli om man utgår från en formell grammatisk definition av språket som skall analyseras och bygger lämpliga datastrukturer för att representera uttrycken. Nedan följer en kort orientering om beskrivning av syntax för programmeringsspråk med formell grammatik. Grammatik för programmeringsspråk Formell syntax För alla språk finns syntaxregler som definierar vilka textsträngar som är grammatiskt korrekta fraser i språket. För programmeringsspråk, som är en typ av formella språk, brukar man definiera grammatiken i s.k. BNF, eller Backus-Naur Form, efter upphovsmännen John Backus och Peter Naur. En BNF-grammatik består av en samling produktionsregler. Några operatorer som används i BNF är ::=,,, <symbol>. Här följer ett exempel på en BNF-grammatik som beskriver en meny på ett sätt som du kanske inte sett förut. 1 En förklaring följer efter exemplet. <middag> ::= <förrätt> <huvudrätt> <dessert> <förrätt> ::= <soppa> <sallad> <soppa> ::= <kycklingsoppa> <rödbetssoppa> <sallad> ::= <Waldorfsallad> <västkustsallad> <huvudrätt> ::= <vegetariskt> <kött> <marint> <fågel> <vegetariskt> ::= <böngryta> <linsbiffar> <marint> ::= <fisk> <skaldjur> <fisk> ::= <havsfisk> <gös> <abborre> <havsfisk> ::= <lax> <hälleflundra> <pigghaj> <skaldjur> ::= <hummer> <krabba> <havskräftor> <räkor> <kött > ::= <oxfilé> <lammstek> <mungo> <fågel> ::= <fasan> <gås> <kalkon> <dessert> ::= <ostbricka> <äpplekaka> <frukt> <glass> <frukt> ::= <päronpåhallspegel> <mango> <glass> ::= <hallonsorbet> <storstrut> Produktionsreglerna i BNF har formen <symbol> ::= produktion. Sekvens och val kan användas i reglernas högerled när man vill uttrycka att det som produceras består av en följd av något, eller ett val mellan flera alternativ. Den första regeln ovan kan utläsas en middag består av en förrätt, följt av en huvudrätt, följt av en dessert. Den andra: en förrätt består antingen av en soppa eller av en sallad. Ordningen mellan reglerna spelar ingen roll, men man brukar sätta upp de övergripande reglerna först. En av symbolerna utgör grammatikens startsymbol (middag ovan). Reglerna i en BNF-grammatik definierar två huvudtyper av syntaktiska kategorier: 1 Oklart om restaurangen har en eller två stjärnor i Guiden.

4 (7) Terminaler o Terminaler är grammatikens grundsymboler - dess basfall. Terminaler är sig själva och refererar inte vidare till andra begrepp i grammatiken. De förekommer därför inte till vänster om ::=. o Ex. <abborre>, <fasan>. Icketerminaler o Icketerminaler är symboler till vänster om ::= som definieras genom att referera till terminaler, andra icketerminaler, eller rekursivt till sig själva. o Ex. <huvudrätt> ::=, <fisk> ::= Val Val mellan olika alternativ i produktionerna uttrycks med operatorn. Ett av alternativen måste väljas. Iteration Iteration uttrycks genom rekursiva regler, direkt eller indirekt. Vill man t.ex. formulera begreppet en sekvens av ett eller flera x skriver man <x-sekvens> ::= x x <x-sekvens> vilket utläses: En x-sekvens består av ett x eller ett x följt av en x-sekvens. Ex. x, xx, xxx, osv. För begreppet en sekvens av noll eller flera y behövs symbolen (epsilon) och vi skriver <y-sekvens> ::= y <y-sekvens> vilket utläses: En y-sekvens är antingen tom eller så är den ett y följt av en y-sekvens. Ex.,y, yy, yyy, osv. I rekursiva regler av typen ovan är det som står till vänster om rekursionens basfall. Ex. Vad är det för fel på denna regel? <dessert> ::= <glass> <dessert> 2 Syntes och analys En grammatik kan användas på två sätt: o För att producera korrekta fraser i språket. (Att komponera en måltid från menyn.) o För att analysera om en sträng är en korrekt fras i språket. Detta kallas parsning. (Att undersöka om något som serveras av restaurangen finns på menyn, eller om man råkat ut för här är vårt kylskåp.) Exempel: Aritmetiska uttryck Syntaxen för aritmetiska uttryck med konstanter och parenteser kan definieras med en enkel BNF-grammatik. I detta exempel skriver vi av praktiska skäl terminalerna inom. <expression> ::= <constant> <binary_expression> ( <expression> ) <binary_expression> ::= ( <expression> <operator> <expression> ) <operator> ::= + - * / % ^ <constant> ::= <digit> <digit> <constant> <digit> ::= 0 1 2 3 4 5 6 7 8 9 Exempel på korrekta uttryck: 0, 123, (123), (1+2), ((3-4)^7), ((1+(2))), men inte 1+2, (3-4^7) eller (-(1/2)). Operatorn / är heltalsdivision, % rest vid heltalsdivision och ^ upphöjt till. 2 Den är svår att implementera tyvärr.

5 (7) Parsning av uttryck I Weiss kap. 11.2 beskrivs tabellstyrd parsning med stack. En annan vanlig metod är rekursiv nedstigning (eng. recursive descent). Metoden bygger på att man definierar ömsesidigt rekursiva parsningsfunktioner med utgångspunkt från grammatiken. Vanligen definierar man en sådan funktion för varje icketerminal möjligen med undantag för enklare icketerminaler som kan hanteras på annat sätt (som de tre sista ovan). I vårt exempel skall vi låta parsningsfunktionerna bygga syntaxträd från uttrycken som matas in på tangentbordet. Uttryckets värde kan senare beräknas genom att analysera trädet med en rekursiv evalueringsfunktion. Eftersom detaljer som t.ex. parenteser inte skulle fylla någon funktion i trädet, och således inte finns där, brukar man säga att trädet är uttryckets abstrakta syntax, till skillnad från den konkreta syntaxen som definierades med BNF ovan. Exempel: Konkret syntax (((1+2)^3)-(4*5)) motsvaras av det abstrakta syntaxträdet - ^ * + 3 4 5 1 2 När uttrycket är översatt till abstrakt syntax är det mycket enklare för datorn att räkna ut dess värde än det skulle vara att försöka tolka dess konkreta syntax tecken för tecken. T.ex. får vi fram värdet hos syntaxträdet ovan genom att först rekursivt beräkna delträdens värden. Om dessa blir v 1 resp. v 2 så är har hela trädet värdet v 1 v 2, etc. Ett löv, d.v.s. en konstant har naturligtvis sig självt som värde. Datarepresentation för abstrakta uttrycksträd Följande mer eller mindre fullständiga klassdefinitioner är givna: public interface Expression { int getvalue(); void prettyinfix(); void prettypostfix(); void prettyprefix(); public class ConstantExpression implements Expression { private int value; public ConstantExpression (int value) { this.value = value;

6 (7) public class BinaryExpression implements Expression { private SymbolTypes op; private Expression leftoperand; private Expression rightoperand; public BinaryExpression(Expression left, SymbolTypes op, Expression right) { this.leftoperand = left; this.op = op; this.rightoperand = right; Uppgift 3 Överskugga de tre metoderna som skriver ut uttrycket i infix-, postfix-, resp. prefixform i subklasserna till Expression. Den konkreta syntaxen för de två sista formerna fås genom att byta ut produktionsregeln för binary_expression i grammatiken mot en av: <postfix_binary> ::= ( <expression> <expression> <operator> ) <prefix_binary> ::= ( <operator> <expression> <expression> ) samt motsvarande i högerledet för expression. Exempel: Infixuttrycket (((1+2)^3)-(4*5)) blir som postfix (((1 2 +) 3 ^) (4 5 *) -) och som prefix (- (^ (+ 1 2) 3) (* 4 5)). Prefixformen är alltså inte postfixformens omvändning, vilket man kanske kan tro. Testa på det abstrakta syntaxträdet som finns i huvudprogrammet: Expression testexpr = new BinaryExpression( new BinaryExpression ( new BinaryExpression ( new ConstantExpression(1), SymbolTypes.PLUS, new ConstantExpression (2)), SymbolTypes.EXP, new ConstantExpression (3)), SymbolTypes.MINUS, new BinaryExpression ( new ConstantExpression (4), SymbolTypes.MULT, new ConstantExpression (5))); (1 p) Uppgift 4 Överskugga metoden getvalue i ConstantExpression och i BinaryExpression. Metoden skall returnera uttryckets värde (evaluera uttrycket) om det är definierat. Givetvis är nolldivision odefinierat (gäller både / och %). Testa! (2 p)

7 (7) Uppgift 5 Skriv färdigt klassen Parser. import symbols.*; public class Parser { private SymbolReader symbolreader; public Parser( Reader instream ) { symbolreader = new SymbolReader(inStream); public Expression parse() throws SyntaxError { Symbol s = symbolreader.readnextsymbol(); Funktionen skall läsa symboler från tangentbordet med readnextsymbol och bygga syntaxträd av lämplig typ. En referens till trädet returneras. För inläsning av symboler (språkets ord ) finns klassen SymbolReader som är en anpassad version av Weiss:s Tokenizer-klass från kalkylatorprogrammet i kap. 12.2. Syntaxfel hanteras med public class SyntaxError extends Exception { public SyntaxError(String msg) { super(msg); Följande fel skall rapporteras: SyntaxError: illegal operator encountered SyntaxError: number or '(' expected SyntaxError: ')' expected Skriv ett program som testar parsern och uttrycksevalueringen i B.2. Tips: Definiera ömsesidigt rekursiva parsningsfunktioner för icketerminalerna <expression> och <binary_expression> i grammatiken. Anropa en av dessa från parse. När en parsningsfunktion anropas skall alltid den första symbolen i deluttrycket som skall analyseras vara inläst. Skicka denna som inparameter till funktionen. (3 p)