Laboration 5 Mängder Syfte Lära dig analysera större och mer komplicerade problem och formulera lösningar innan du implementerar. Lära dig kombinera på ett lämpligt sätt de begrepp och metoder som du har hittills lärt dig i kursen, såsom rekursion, dataabstraktion, listhantering, etc. för att lösa svårare problem. Innan du börjar med denna labb bör du läsa igenom avsnitt Example: Representing sets i Abelson & Sussman. Där går man igenom en hel del av det du behöver för den här labben. Uppgift 1 Skriv konstruktorer, selektorer och predikat för hantering av mängder. Mängderna ska representeras m.h.a. listor. En mängd är antingen tom eller så innehåller den minst ett element. Som element räknas tal, symboler och andra mängder ( delmängder ). Du får själv avgöra vilka konstruktorer, selektorer, predikat och annat som du kommer att behöva för att implementera funktionerna i de kommande uppgifterna men tänk efter noga. Du ska i fortsättningen bara använda dig av de funktioner du definierar här för att manipulera mängderna. Fr.o.m. nu är car, cdr, cons, list, map och andra fördefinierade funktioner som arbetar direkt med listor nästan bannlysta. Abstraktion är ordet för stunden... Då mängder och listor inte är samma sak finns det en del detaljer att ta hänsyn till. En av de viktigare detaljerna är att mängderna inte innehåller dubletter. Det underlättar om man från början inte tar hänsyn till detta utan testar med mängder som inte innehåller dubletter. Då kan man till att börja med låta konstruktorn för mängder helt enkelt returnera en lista. Men senare i labben har man verktygen för att göra en avancerad konstruktor. Exempel: Antag att du skapat konstruktorer, selektorer samt predikat för mängder. Då kan man t.ex. göra så här (här elimineras dubletter): > (define myset (make-set (a (a b b (c b) 3) 5 5 (e s) (s e s)))) > myset (a (a b (c b) 3) 5 (e s)) > (set? myset) > (empty? myset)
2 Datalogi, grk 1 Laboration 5 > (first myset) a > (rest myset) ((a b (c b) 3) 5 (e s)) > (insert (f b) myset) ((f b) a (a b (c b) 3) 5 (e s)) > (the-empty-set) () Mängden myset består av fyra element. Det första och det tredje elementet är symboler medan det andra och det fjärde elementet är mängder. Det andra elementet består i sin tur av fyra element, en mängd och tre symboler. Observera att ordningen hos elementen inte spelar någon roll: (make-set (2 1 3 2)) t.ex. kan returnera (2 1 3), (1 3 2), eller någon annan permutation. Du får själv avgöra vad svaret ska vara. Uppgift 2 Skriv ett predikat member? som ger om ett element finns i en mängd och annars. ett predikat same? som jämför två mängder och ger om de innehåller samma element, oavsett ordning, och annars. Tips Två mängder M 1 och M 2 är lika om M 1 = {x} M 11, x M 2 och M 11 = M 2 {x} Detta innebär att en procedur, delete, som tar bort ett element ur en mängd är bra att ha. Eftersom ett element kan vara en mängd så kan proceduren delete använda same?. Faktiskt kan member?, same? och delete allihop använda varandra. Då du skriver en av dem kan du tänka dig att de andra redan finns och fungerar (kallas ibland för wishful-thinking ). Ytterligare en funktion som kan vara bra att ha är same-elem? som jämför två element och ger om de är lika och annars. Denna procedur bör använda sig av same? för att jämföra element som är mängder. Observera att du inte kan provköra någon av dessa funktioner fullt ut förrän du skrivit allihop eftersom de använder varandra. Detta innebär att du måste tänka till innan du skriver dem för att få det rätt. Ett tips är att skriva upp ett antal exempel på ett papper och analysera dessa noga innan du börjar hacka. Innan du kan få exemplen nedan att fungera måste du dessutom skriva om mängdkonstruktorn make-set så att mängderna inte kan innehålla dubletter. Det gör man med samma teknik som den som föreslagits för member, same? och delete. Så för att allt ska fungera som avsett måste make-set ändras. Följande exempel skall fungera, observera dock att det inte är någon garanti för att allt är korrekt gjort: >(member? (make-set (1 2)) (make-set (1 2 3))) >(member? 1 (make-set (1 2 3))) >(member? (make-set ((x) 2)) (make-set (4 2 (x))))
Laboration 5 Datalogi, grk 1 3 >(member? (the-empty-set) (make-set (a b c))) >(member? (make-set (1)) (the-empty-set)) >(member? (make-set (1 2)) (make-set ((1 2) 3))) >(member? (make-set (1 (b))) (make-set (3 2 ((b) 1)))) >(member? (make-set (1 2)) (make-set (y (2 1)))) >(same? (make-set (1 2 a)) (make-set (2 a 1))) >(same? (the-empty-set) (the-empty-set)) >(same? (make-set ((1 2) 2 3)) (make-set (2 3 (2 1)))) >(same? (make-set ((2 3) a b)) (make-set (2 3 (a b)))) >(same? (make-set (2 (b (z)) 4)) (make-set (3 5 (z) (x)))) >(same? 1 1) odefinierat - 1 är ingen mängd. >(same? (the-empty-set) a) odefinierat - a är ingen mängd. >(same? a (make-set (b 1))) odefinierat - a är ingen mängd. Uppgift 3 Skriv funktioner för att skapa en ny mängd som är snittet mellan två mängder. M 1 M 2 = {e e M 1 e M 2} skapa en ny mängd som är differensen mellan två mängder. M 1 M 2 = {e e M 1 e M 2} skapa en ny mängd som är unionen av två mängder. M 1 M 2 = {e e M 1 e M2} Exempel: > (intersec (make-set (1 (2 (1)) 3 (1 2))) (make-set (((1) 2) 3 4 (2 3)))) (3 (2 (1))) > (diff (make-set (1 (2 3) b)) (make-set (b 1))) ((2 3)) > (union (make-set (2 3)) (make-set ((a b)))) (2 3 (a b)) > (union (make-set (1 2 (x (y 3) 4)))
4 Datalogi, grk 1 Laboration 5 (make-set (b 1 (a (r))))) (1 2 (x (y 3) 4) b (a (r)))
Laboration 5 Datalogi, grk 1 5 Uppgift 4 Skriv en funktion som returnerar den kartesiska produkten av två mängder. M 1 M 2 = {e x, y(e = (x, y) x M 1 y M 2)} Den kartesiska produkten mellan mängderna A och B är alltså en lista där elementen är par, vilka sätts samman på följande vis: varje element ur A kombineras med varje element ur B. Med andra ord: om A = {a, b, c} och B = {d, e} så gäller att A B = {(a, d), (a, e), (b, d), (b, e), (c, d), (c, e)} Observera att den kartesiska produkten returnerar en lista av par. {a, b} {a, b} = {(a, a), (a, b), (b, a), (b, b)} där alla fyra par är distinkta, d.v.s. skilda från varandra i matematisk mening. Det här är en funktion där map eller do-to-each passar utmärkt använd gärna någon av dem. Exempel (om operationen kartesisk produkt kallas cart-product): > (cart-product (make-set (a b c)) (make-set (1 2))) ((a. 1) (a. 2) (b. 1) (b. 2) (c. 1) (c. 2)) Frivillig uppgift Det är bra om det går att definiera ett universum och i så fall kan du implementera operationen komplement. För att få godkänt på den här labben ska du ha skrivit konstruktorer, selektorer och predikat för mängder samt använt dig av dem för att lösa uppgifterna. Du ska ha skrivit funktionerna member?, same?, union, diff, intersec och cart-prod. De ska fungera enligt de givna specifikationerna. Glöm inte att kommentera alla funktioner noggrant. Du ska som vanligt kunna förklara hur funktionerna fungerar och kunna svara på frågor från handledaren.