Nada Tentamensdag 2004 aug 23 Tentamen Programmeringsparadigm Skrivtid 5 h Antalet uppgifter : 1 (allmänt)+ 4 (Haskell) + 4 (Prolog) = 10p +(5p + 20p +5p+ 20p) + (10p +12p + 8p +10p) = 10p + 50p + 40 p = 100p Lärare, jourhavande lärare : Leif Kusoffsky ------------------------------------------------------------------------------------------------------------------ Tillåtna hjälpmedel: Fokker : Functional programming Brna : Prolog Programming ----------------------------------------------------------------------------------------------------------------- Del : Paradigmer allmänt. 1. Beskriv olika programeringsparadigm och vad som utmärker dem. Ge exempel på olika programmeringsspråk i de olika paradigmen. 10 p) Del : Funktionell programmering. I alla deluppgifterna, använd Haskell och skriv typen för de identifierare du definierar. 2. Skriv en funktionen engletter som avgör om det är sant eller osant om ett tecken finns i det engelska alfabetet, dvs i intervallet från a till z eller A till Z. Ange även funktionens typ. 5p) 3. Definiera en funktion sumbiggerthan :: Int -> [(Int, Int)] -> [Int] sumbiggerthan k list adderar komponenterna i paren i list och retunerar en lista med de summor som är större än k. Exempelvis: sumbiggerthan 5 [(1, 2),(3, 4),(5, 6)] blir [7, 11] eftersom 3+4 > 5 och 5+6 > 5 a) Skriv funktionen utan att använda några högre ordningens funktioner eller listomfattning. (och inte som i uppgift d) b) Skriv funktionen med map och filter. c) Skriv funktionen med listomfattning. d) Skriv funktionen med hjälpfunktion med "accumulering i parameter". 20p) 4. Vad menas med λ-uttryck i Haskell? När har man glädje av sådana? Ge exempel! 5p)
5 a) Skriv i Haskell en DT (datatyp) Vector2 (vektorer i planet) med följande operationer: Vector2, -- datatyp för vektorer i planet Vector2, -- Double-> Double->Vector2 Konstuktorfunktion för vektor read, -- String -> Vector2 inläsning på formen Vector2 1.0 2.0 read1, -- (Double, Double) -> Vector2 -- för inläsning på formen read1 (1.0, 2.0) show, -- Vector2 -> String utskrift på formen Vector2 1.0 2.0 show1, -- Vector2 -> (Double, Double) för utskrift på formen (1.0, 2.0) (==), -- Vector2 -> Vector2 -> Bool lika med (/=), -- Vector2 -> Vector2 -> Bool ej lika med add, -- Vector2 -> Vector2 -> Vector2 vektoradditon sub, -- Vector2 -> Vector2 -> Vector2 vektorsubtraktion neg, -- Vector2 -> Vector2 negering lengthv2, -- Vector2 -> Double vektorlängd ( absolutbelopp) o, -- Vector2 -> Vector2 -> Double skalärprodukt Exempel på körningar : Vector2> Vector2 1 (-3)/= Vector2 4 4 True Vector2> Vector2 1 (-3)+ Vector2 4 2 Vector2 5.0 (-1.0) Vector2> Vector2 1 (-3) add Vector2 4 2 Vector2 5.0 (-1.0) Vector2> show1 (read1 (1, -3) + read1 (4, 2)) (5.0,-1.0) Vector2> read1 (1, -2) o read1 (-3, 4) -11.0 b) Komplettera din definition i a) så att man kan använda följande operatorer och funktion i typklassen Num (detta är ganska svårt, talade om detta iföreläsning 7) -- Tillägsuppgift (+), -- överlagrad operator för add (-), -- överlagrad operator för sub (*), -- ska ge error negate -- överlagrad funktion för neg -- övriga funktioner i Num ger error Typklassen Num är definierad så här i "Prelude" : class (Eq a, Show a) => Num a where (+), (-), (*) :: a -> a -> a negate :: a -> a abs, signum :: a -> a frominteger :: Integer -> a fromint :: Int -> a -- Min comp def: All, -- except negate or (-) -- Def imp se prelude c) I uppgift b), varför kan vi inte låta (*) stå för skalärprodukten och abs för lengthv2? 20p)
Del : Logikprogrammering. 6. a) Skriv ett program för member(element,list) med betydelsen Element är ett element i listan List. b) Skriv ett program i Prolog för append(xs,ys,xsys) med betydelsen att listan XsYs är listan Xs sammanslagen med Ys. c) Använda append/3 för att skriva en definition i Prolog för member(element,list) (10p) 7. Skriv i Prolog ett generate-and-test-program som löser följande problem: I tv-programmet Anti-Bachelor kan Maria välja mellan Per, Tage och Lars. De har olika yrken, olika längd och olika hårfärger; en är blond, en är rödhårig och en är mörk. Den blonda ynglingen är längst och är ekonom. Lars är kortare än den som är rödhårig. Per är civilingenjör. Maria väljer bort den som är längst och väljer bort den som är kortast. Vem väljer Maria och vilket yrke har han? 12p) 8. a) När det gäller Prolog-program kan man tala om en logisk läsning och en procedurell läsning. 1) Alla Prolog-program har en procedurell läsning. X) Alla Prolog-program har en logisk läsning. 2) Enbart Prolog-program som innehåller! har en logisk läsning. b) Prologs semantik ( procedurell läsning) kan beskrivas med Byrds boxmodel. 1) Kommer vi till en box via Redo-porten kommer vi alltid att lämna boxen via Fail-porten. X) Kommer vi till en box via Redo-porten kommer vi alltid att lämna boxen via Call-porten. 2) Kommer vi till en box via Redo-porten kommer vi att lämna boxen via Fail-porten eller via Exit-porten c) I den logiska läningen av Prolog-program 1) betyder ; logiskt och X) betyder, logiskt och 2) betyder, logiskt eller d) I den logiska läningen av Prolog-program 1) Har klausul-ordningen i ett predikat betydelse. X) Har mål-ordningen i ett högerled i en klausul betydelse. 2) Har vare sig klausul-ordningen eller mål-ordningen någon betydelse. 8p)
9 När man kör i Prolog-fönstret i emacs, vad skulle följande körningar (unifieringar) ge för resultat (Lyckas unifieringarna? Vilka substitutioner görs i så fall?)?- x=y.?- X=Y.?- x=y.?- X=y.?- X=Y, Y=z.?- a(b,c) = d(e,f).?- a(b,c) = a(e,f).?- a(b, b) = a(c, C).?- a(b, b) = a(c, c).?- a(b,b) = A(B,b). 10p)
Svar tentamen programeringsparadigm 2003- augusti. Del paradigmer allmänt. Imperativ : Sekvens av kommandon (satser/order/instuktioner) som datorn utför i tidsordning. Ordningen kan brytas med aternativkommandon (if / case /switch osv ) och med slingkommandon ( Loopar / for / while / repeat- until osv) och i vissa språk med goto. Assemleringspråk, Fortran, Basic, Pascal... osv. Det finns hur många som helst. Moderna imperativa språk möjliggör definiton av egna sammansatta typer; poster (records) och arrayer. OO : Imperativ + klassbegrepp, dvs posterna kan innehålla funktioner. Instanser av olika klasser kallas objekt, och anrop av funktionerna sker via objekten. Detta innebär att objekt som är av av olika "sort" (tillhör olika klasser) "gör saker på sitt sätt". Dessutom kan klasserna inordnas i ett arvsträd (eller arvsordning). Språk: Eifel, Simula, Java, C++ m.fl. Funktionella språk. Programmering genom att definiera funktioner, "huvudprogram", "fuktioner", "subrutiner", metoder" ersätts av funktioner. Kärnan är matematikens lamda-kalkyl. Funktioner är värden, funktioner kan ha funktioner som argument och/eller resultat ("Högre ordningens funktioner"). Inga sidoeffekter, dvs en viss kod betyder alltid samma sak oberoende av exekveringsomgivning och oberoende av när den exekveras. Funktionsargument "mönsterpassas" ofta på parametrarna i funktionsdefiionerna, vilket är bekvämt. Språk: Haskell, ~ Lisp, ml. Lamda-uttryck finns också i Python och Python kan därför användas funktionellt. Logik språk. Kärnan är en delmängd av logiken. Programmering genom att skriva logiska påståenden, dels fakta, dels påståenden (klausuler, satser) av typ detta gäller ("klausulhuvud",) om detta gäller ("klausulkropp"). Klausulkroppar består ofta av flera termer med "logiska och" som operator."logiska eller" skrivs i regel som flera klausuler och som tillsammans bildar ett predikat. Både klausulhuvud och klausulkropp kan innehålla logiska variabler, och ett logikspråk försöker genom ("dubbelsidig") mönsterpassning (unifiering) klura ut om påståenden är sanna eller om logiska variabler förekommer vad som krävs av de logika variablerna för att påstenden ska vara sanna. Språk: Prolog och moderna utvidgningar av Prolog. Del funktionell programmering. engletter :: Char -> Bool -- 2 engletter c = (( a <= c) && (c <= z )) (( A <= c) && (c <= Z )) sumbiggerthan _ [] = [] -- 3 a sumbiggerthan k ((i, j):ijs) i+j > k = (i+j) : sumbiggerthan i ijs otherwise =sumbiggerthan i ijs sumbiggerthan k list = filter p (map f list) -- b where f (i, j) = i+j p m = m > k sumbiggerthan k list = [ i+j (i,j) <- list, i+j > k ] -- c sumbiggerthan k list = sbtacc k list [] -- d sbtacc :: Int -> [(Int, Int)] -> [Int] -> [Int] sbtacc _ [] acc = acc
sbtacc k ((i, j):ijs) acc i*j > k = sbtacc k ijs (acc++[i+j]) otherwise = sbtacc k ijs acc -- 4 module Vector2 ( -- 5 a) Vector2, -- datatyp för vektorer i planet Vector2, -- Double-> Double->Vector2 Konstuktorfunktion för vektor read, -- String -> Vector2 inläsning på formen Vector2 1.0 2.0 read1, -- (Double, Double) -> Vector2 -- för inläsning på formen read1 (1.0, 2.0) show, -- Vector2 -> String utskrift på formen Vector2 1.0 2.0 show1, -- Vector2 -> (Double, Double) för utskrift på formen (1.0, 2.0) (==), -- Vector2 -> Vector2 -> Bool lika med (/=), -- Vector2 -> Vector2 -> Bool ej lika med add, -- Vector2 -> Vector2 -> Vector2 vektoradditon sub, -- Vector2 -> Vector2 -> Vector2 vektorsubtraktion neg, -- Vector2 -> Vector2 negering lengthv2, -- Vector2 -> Double vektorlängd ( absolutbelopp) o, -- Vector2 -> Vector2 -> Double skalärprodukt -- Tillägsuppgift (+), -- överlagrad operator för add (-), -- överlagrad operator för sub (*), -- ska ge error negate -- överlagrad funktion för negate ) where data Vector2 = Vector2 Double Double deriving (Eq, Show, Read) add :: Vector2 -> Vector2 ->Vector2 add (Vector2 x1 y1) (Vector2 x2 y2) = Vector2 (x1+x2) (y1+y2) sub:: Vector2 -> Vector2 ->Vector2 sub v1 v2 = add v1 (neg v2) neg :: Vector2 -> Vector2 neg (Vector2 x y) = Vector2 (-x) (-y) lengthv2 :: Vector2 -> Double lengthv2 (Vector2 x y) = sqrt (x*x + y*y) read1 :: (Double, Double) -> Vector2 read1 (x, y) = Vector2 x y show1 :: Vector2 -> (Double, Double) show1 (Vector2 x y) = (x, y) o :: Vector2 -> Vector2 -> Double o (Vector2 x1 y1) (Vector2 x2 y2) = (x1*x2 + y1*y2) instance Num Vector2 where (+) = add (*) = error "No * on vectors" negate = neg abs = error "abs" frominteger i = error "frominteger" Typerna stämmer ej. Del logik programmering. -- 5 b -- 5 c
member(x, [X _]). member(x, [_ Ys]) :- member(x, Ys) % 6 a append([], Ys, Ys). % b append([x Xs], Ys, [X Zs]) :- append(xs, Ys, Zs). member(x, Ys) :- append(_, [X _], Ys). % c % Ps is a sequence of men in length order. % A man is g(<name>, <hair coulor>,<profession>). p(ps, N, Y) :- Ps = [g(_, blond, ekonom), g(n,_,y), _], % tallest first member(g(per, _, civing), Ps), member(g(lars, _, _), Ps), member(g(tage, _, _), Ps), member(g(_,dark, _), Ps), member(g(_, red, _), Ps), after(g(_, red, _), g(lars, _, _), Ps). after(x, Y, [X, Y, _]). after(x, Y, [X, _, Y]). after(x, Y, [_, X, Y]). /* Körning :?- p(ps, N, Y). N = per, Y = civing, Ps = [g(tage,blond,ekonom),g(per,red,civing),g(lars,dark,_a)]? ; no?- */ 8a) 1 8b) 2 8c) x 8d) 2 % 8?- x=y. no % 9?- X=Y. Y = X? ; no?- x=y. Y = x? ; no?- X=y. X = y? ; no?- X=Y, Y=z. X = z, Y = z? ; no?- a(b,c) = d(e,f). no?- a(b,c) = a(e,f). C = f, E = B? ; no?- a(b, b) = a(c, C). B = b, C = b? ; no?- a(b, b) = a(c, c). no?- a(b,b) = A(B,b). {SYNTAX ERROR: **operator expected...**