Nada KTH 2003 okt 23 Tentamen Programmeringsparadigm 2D1350 Skrivtid 5 h 8-13 Antalet uppgifter : 1 (allmänt)+ 4 (Haskell) + 4 (Prolog) = 9 10p +(14p + 12p +10p+ 14p) + (8p +12p + 12p +8p) = 10p + 50p + 40 p = 100p Lärare, jourhavande lärare : Leif Kusoffsky ------------------------------------------------------------------------------------------------------------------ Tillåtna hjälpmedel: Fokker : Functional programming Brna : Prolog Programming ----------------------------------------------------------------------------------------------------------------- Del : Paradigm allmänt. 1. a) Kan man programmera icke-objekt-orienterat i Java, dvs som i ett klassikt imperativt språk? 1) Nej, går ej att skriva program som är i stort ekvivalenta med t ex Pascal-program. X) Ja, om klasserna enbart har variabler och funktioner deklarerade utan static. 2) Ja, i stort sett om funktioner är deklarerade som static. b) Om man programmerar objekt-orienterat i Java 1) har aldrig subklasser egna olika implementaioner av metoder definierade i en superklass. X) har ibland subklasser egna olika implementaioner av metoder definierade i en superklass. 2) har alltid subklasser egna olika implementaioner av metoder definierade i en superklass. c) Vid ett anrop x.f(..) i Java kan 1) x vara en variabel som innehåller en primitiv typ. X) olika metoder f anropas vid körningen, beroende på vilket sots objekt x refererar. 2) f(..) ej vare en metod med returtypen void. d) Vid anrop av klassmetoder X.f(..) i Java 1) måste X vara namnet på en objektreferens. X) kan X vara namnet på en klass. 2) klassmetoder kan ej anropas med denna syntax. e) Vid ett anrop av X.f(..) i ett icke-objektinriktat språk 1) måste X vara namnet på en objektreferens. X) kan X vara namnet på något i språket som används för modularisering (t ex funktionpaket). 2) Sådana uttryck finns inte i något icke-objektinriktat språk. f) I OO-design bör man enligt mångas åsikt i början av programutvecklingen fråga sig 1) MED VAD, dvs vilka sorts föremål i användarens värld skall jag modellera? X) VAD, dvs vilka funktioner vill användaren att programmet ska ha? 2) HUR, dvs hur skriver jag funktionerna som användaren vill att programmet skall ha? g) Vilka av följande begrepp brukar förknippas med moderna (icke-oo) imperativ språk? "loopar" (dvs snurror, slingor), arv, pekare, rekursion, dynamisk bindnig, unifiering. h) Gruppera i paradigmen imperativa, objektorienterade, funktionella och logiska: Haskell, C, Prolog, C++, Eiffel, Java, Pascal, Basic, Fortran, assemler, Smalltalk, Simula. (10p).
Del : Funktionell programmering. I alla deluppgifterna, använd Haskell och skriv typen för de identifierare du definierar. 2. Skriv i i Haskell en funktion swaplist som skiftar komponeterna i alla par i en lista. De par där båda komponeterna är lika skall ej finnas med i resultatlistan. Exempel : Main> swaplist [(5,4),(15,14),(2,2),(14,14),(35,34)] [(4,5),(14,15),(34,35)] a) Skriv en lösning som vare sig använder högre ordningens funktioner, ackumulering i parameter, eller listomfattning. b) Skriv en lösning som använder ackumulering i parameter. c) Skriv i i Haskell en funktion swap som skiftar komponeterna i ett par. d) Skriv i i Haskell en funktion pneq som kontrollerar att komponeterna i ett par är olika. e) Skriv en lösning för swaplist som använder map, filter, swap och pneq. f) Skriv en lösning för swaplist som använder listomfattning. g) Skriv en lösning för swaplist som använder map, filter och lamda-uttryck (anonyma funktioner) i stället för swap och pneq. (14p) 3. Implementera i Haskell en DT (datatyp) Square för schackrutor i en modul Square. Datatypen skall ha de funktioner som framgår av signaturdiagrammet nedan. Bool diag1, diag2 Square show String == /= betweensquare diag1 fromsquare tosquare returnerar om tosquare är snett ett steg uppåt eller nedåt, vänster eller höger, från fromsquare. Funktionen diag2 returnerar analogt för två steg. Funktionen betweensquare returnerar mellanliggande ruta om diag2 fromsquare tosquare är True, annars error med lämpligt felmedellande. fromsquare betweensquare tosquare diag2 fromsquare tosquare är true Funktionerna kan användas för dragen i ett damliknade spel, diag1 när man går till tomma rutor, diag2 när man "hoppar" över en enda motståndarpjäs. (12p)
4. Implementera i Haskel en DT (datatyp i en modul) Piece för att representera pjäserna i ett damliknade spel. Det finns bara en sorts pjäs, fast en uppsättning vita och en uppsättning svarta. Modulen implementerar två datatyper: Colour som indikerar om en pjäs är vit (WhiteC) eller svart (BlackC). Piece som är en pjäs/tom ruta. T ex är Pi WhiteC en vit pjäs, NoPiece är en tom ruta. Datatypen skall också ha funktionen othercolour som framgår av signaturdiagrammet: othercolour WhiteC blir BlackC, othercolour BlackC blir WhiteC. (10p) othercolour Colour WhiteC BlackC Pi Piece NoPiece 5. Implementera i Haskel en DT (datatyp i en modul) Board för att representera damspel. Modulen implementerar en datatyp Board. Definiera typen som data Board = Board [(Square, Piece)] deriving Show Skulle man kunna använda newtype istället för data? Konsekvenser? Skulle man kunna använda type istället för data? Konsekvenser? Ett värde med typen Board innehåller en lista med 64 element. Varje element är ett par. Paren består av en ruta (Square) och schackpjäsen (Piece) på den rutan. Tomma rutor har "pjäsen" NoPiece. Datatypen skall också ha ytterligare två funktioner, som framgår av signaturdiagrammet: Piece (,) [] Board Board show String Square 2 3 2 4 Bool 1 pieceat legalmove Piece 1 Funktionen pieceat returnerar pjäsen på en viss ruta i ett damspel. Funktionen legalmove returnerar om en ("riktig") pjäsen på en viss ruta i ett damspel får flytta till en annan ruta. Det är tillåtet att flytta diagonalt ett steg till en tom ruta, och att flytta diagonalt tvårutor till en tom ruta om mellanliggande ruta innehåller en motståndarpjäs. (14p)
Del : Logikprogrammering. 6. Skriv ett program i Prolog för select(x,harxs,ettmindrexs) med betydelsen att listan EttMindreXs är resultat av att en förekomst av X har tagits bort från HarXs. (8p) 7. Skriv i Prolog ett generate-and-test-program som löser följande problem: I en kappsegling deltar 9 båtar. Volo placerade sig mellan Maybee och Bonnie. Maybee var just före Sylvia. Spray var första båt efter Bigfoot. Dristigheten placerade sig mellan Patricia och Necesse. Spray kom precis innan Necesse. Bigfoot kom precis mitt i resultatlistan Hur ser resultatlistan ut? (12p) Tips: Man kan ordna båtarna i resultatordning. Med "A mellan B och C" menas att båtarna har följden BAC eller CAB. 8. Skriv i Prolog ett program som löser följande problem: Vilka färdvägar (rutter) finns det mellan två orter. De orter som är aktuella finns i nedanstående avståndstabell. För full poäng ska man även få reda på den totala avståndet för rutten och vilka mellanliggande orter som passeras. Vidare skall för full poäng en förbindelse mellan två orter bara användas en gång. (12p) dist([d(stockholm, orebro, 197), % Färdigt faktum i Prolog, får användas d(stockholm, jonkoping, 335), % i lösningen norrtalje d(orebro, goteborg, 283), orebro d(jonkoping, goteborg, 149), 283 197 75 d(orebro,jonkoping, 200), 200 stockholm d(stockholm, norrtalje, 75)]). goteborg 149 335 jonkoping Exempel på körningar:?- route(goteborg, stockholm, D, Vs). D = 480, Vs = [orebro]? ; D = 484, Vs = [jonkoping]? ; no Tips och kommentarer: För full poäng skall man kunna använda avståndstabellen "åt båda hållen". Vidare är det bra om man kan undvika att få lösningar som?- route(goteborg, stockholm, D, Vs). D = 818, Vs = [orebro,jonkoping]? dvs om det i tabellen finns en direkt förbindelse mellan två orter nöjer sig programmet med detta och söker ej omvägar. Ett sätt att bara använda en förbindelse mellan två orter en gång är att "nästa gång använda en avståndstabell med förbindelsen bortagen".
9. a) Om Prolog misslyckas med att unifiera argumenten i ett delmål f(..) med huvudet (konklusionen) i den första av flera klausuler som definierar predikatet f så 1) svarar Prolog yes. X) svarar Prolog no. 2) försöker Prolog unifiera argumenten med huvudet i den andra klausulen för predikatet f. b) Om ett Haskell-system, t ex hugs, misslyckas med att passa ("matcha") argumenten i ett anrop f.. med vänsterledet i den första av flera ekvationer som definierar funktionen f så 1) svarar hugs med Program error. X) returneras False. 2) försöker hugs "matcha" argumenten med vänsterledet i den andra ekvationen för funktionen f. c) Om Prolog misslyckas med att satisfiera ett delmål g i en konjunktion av delmål.., h(..), g(..), f(x) så 1) försöker Prolog på nytt att få delmål h att lyckas. X) svarar Prolog no. 2) svarar Prolog yes. d) Om ett Haskell-system, t ex hugs, vid en körning får resultatet False vid beräkningen av funktionanropet g(x)i detta uttryck med funktionanrop h(x) && g(x) && f(x) så 1) anropas h(x) på nytt. X) blir hela uttrycket True om uttrycket f(x), som beräknas, blir True. 2) blir hela uttrycket False 8p)
Uppmaning: Svara gärna på kursenkäten, som du kan komma åt från kursidan! Förfrågan: Kan du tänka dig att vara labbassistent nästa år under läsperiod 1 i kursen programmeringsparadigm i D2? Kryssa gärna i ett eller båda alternativen. (Naturligtvis ej bindande) O I Haskelldelen av kursen O I Prologdelen av kursen Hur kan jag kontakta dig (tex e-pos, tel ): Om du kryssat, bifoga denna sida med svaren på din tentamen!
Förslag till svar tenta programmeringsparadigm 2003 okt 23. < 50 U Gjort steg 9 i shacket <65 3 <80 4 <100 5 Ej steg 9 <75 3 <90 4 <100 5 Del paradigmer allmänt. 2 X X X X 1 loopar, pekare, rekursion OO : C++ Eiffel Java Smalltalk Simula Funktionellt : Haskell Logik : Prolog Imperativa: Övriga Del funktionell programmering. swaplist :: Eq a => [(a, a)] -> [(a, a)] -- 2 swaplist [] = [] -- a swaplist ((a, b) : abps) a == b = swaplist abps otherwise = (b, a):swaplist abps swaplist list = sl list [] -- b where sl :: Eq a => [(a, a)] -> [(a, a)] -> [(a, a)] sl [] acc = acc sl ((a, b) : abps) acc a == b = sl abps acc otherwise = sl abps (acc ++ [(b, a)]) swap :: (a, b) -> (b, a) -- c swap (a, b) = (b, a) pneq :: Eq a => (a, a) -> Bool -- d pneq (a,b) = a /= b swaplist :: Eq a => [(a, a)] -> [(a, a)] -- e swaplist list = map swap (filter pneq) list) swaplist list = [ (b, a) (a,b) <-list, pneq (a,b)] -- f swaplist list = map (\(a, b) -> (b, a)) (filter (\(a, b) -> a /= b) list) module Square where -- 3 data Square = Sq Int Int deriving (Show, Eq) --fixar show (==) (/=) Saknas - 2p -- g diag1, diag2 :: Square -> Square ->Bool -- predicates for geometrical relations diag1 (Sq i1 j1) (Sq i2 j2) = (abs (i1-i2) == 1 ) && (abs (j1-j2) == 1) diag2 (Sq i1 j1) (Sq i2 j2) = (abs (i1-i2) == 1 ) && (abs (j1-j2) == 1) betweensquare (Sq i1 j1) (Sq i2 j2) diag2 (Sq i1 j1) (Sq i2 j2) = Sq ((i1 + i2) div 2) ((j1 + j2) div 2) otherwise = error "wrong squares in betweensquare" module Piece where -- 4 data Colour = WhiteC BlackC deriving (Show, Eq) data Piece = Pi Colour NoPiece deriving (Show, Eq) othercolour :: Colour -> Colour othercolour WhiteC = BlackC othercolour BlackC = WhiteC
module Board (Board(..) where -- 5 import Piece import Square newtype Board = Board [(Square, Piece)] -- newtype ok pga en konstr. snabbare deriving Show -- type Board = [(Square, Piece)] skulle gå, ändringar krävs, -- ingen ny typ. Dock fortfarande ADT med rätt export -- legalmove ; checks if move in draughts (checkers) is ok. om Piece samnas - 1p legalmove :: Piece -> Square {-from -} -> Square {-to -} -> Board -> Bool legalmove (Pi colour) fromsquare tosquare board = ((diag1 fromsquare tosquare ) && (pieceat tosquare board == NoPiece )) ((diag2 fromsquare tosquare ) && (pieceat tosquare board == NoPiece) && (pieceat (betweensquare fromsquare tosquare) board == Pi (othercolour colour) )) legalmove NoPiece _ = False -- saknas - 1p pieceat :: Square -> Board ->Piece -- Glömma Board nedan / i andra lösn, - 2p pieceat sq (Board ch) = onlyone [icm (isq, icm) <- ch, isq == sq] onlyone :: [Piece] -> Piece onlyone (cm:[]) = cm onlyone _ = error "error in onlyone, pieceat" Del logik programmering. select(x, [X Xs], Xs). % 6 select(x, [Y Ys], [Y Zs]) :- select(x, Ys, Zs). % Ls is a result list of 9 boats in a race % 7 race(ls) :- Ls = [_, _,_,_, bigfoot, spray, _, _, _], follows(maybee, sylvia, Ls), follows(spray, necesse, Ls), between(necesse, dristigheten, patricia, Ls), between(maybee, volo, bonnie, Ls). follows(x,y,[x,y _]). follows(x,y,[_ Zs]):- follows(x,y,zs). between(x,y,z,[x, Y, Z _]). between(x,y,z,[z, Y, X _]). between(x,y,z, [_ Us]) :- between(x,y,z, Us). /* Körning:?- race(rs). Rs = [bonnie,volo,maybee,sylvia,bigfoot,spray,necesse,dristigheten,patricia]? ; no */ sel(d(a,b,d), Ds, Ds1) :- select(d(a,b,d), Ds, Ds1). %8 sel(d(a,b,d), Ds, Ds1) :- select(d(b,a,d), Ds, Ds1). % Rättad sist % De som redan distance(a, B, D, Ds, []) :- sel(d(a,b,d), Ds, _ ),!. % har en säker 5 distance(a, B, D, Ds, [V Vs]) :- % har jag sel(d(a,v,d1), Ds, Ds1 ), % poängsatt distance(v, B, D2, Ds1, Vs), D is D1+D2. % ungefärligt route(a, B, D, Vs) :- dist(ds), distance(a, B, D, Ds, Vs). 2 2 1 2 %9