KTH, Nada, Erik Forslin 2D1343, LÖSNING TILL TENTAMEN I DATALOGI FÖR ELEKTRO Lördagen den 8 mars 2003 kl 14 19 Maxpoäng tenta+bonus = 50+7. Betygsgränser: 25 poäng ger trea, 35 ger fyra, 45 ger femma. Otydliga/svårlästa redogörelser medför poängavdrag. Resultatet senast 29 mars på Nadas anslagstavla. Hjälpmedel: Weiss eller annan algoritmbok. (5p) 1. Internationell kvinnokontroll Här kommer en skiss... Varje medlem har en apparat som bestämmer positionen (t ex en GPS). Denna apparat är kopplad till en liten dator med ett program som med jämna mellanrum plockar ut positionen (en liten textsträng) med jämna mellanrum och skickar medlemmens namn och position till föreningens webbserver (antingen via SMS till dator som vidarebefordrar meddelandet enligt HTTP till föreningens webbserrver eller via telefonuppkoppling till internet och ett direktriktat HTTPmeddelande till föreningens webbserver). På föreningens webbserver uppdaterar varje meddelande en databas eller textfil som sedan minutvis formateras om till HTML (alternativt har webbservern ett litet skript/program som genererar den webbsida som ska visas varje gång någon laddar sidan via Internet). Hemsidan laddas som vanligt med en webbläsare som pratar HTTP. (4p) (5p) 2. Herr Melin bland katterna Basfall: om trädet är tomt (ingen medlem/rot finns) så finns det inga män (d v s 0män). Rekursionsfall/allmänt fall: antalet män i trädet är summan av antalet män i varje delträd plus 1 om rotmedlemmen är en man alternativt 0 om rotmedlemmen är en kvinna. 3. Toppkvinnor på hög Låt lådan och de två kvinnornas famnar utgöra stackarna L, K1 respektive K2. Från början finns alla kort i L. 1. Plocka ett första kort från L och placera i K1. Notera området. 2. Plocka ett kort i taget från L och placera det i K1 (om området är detsamma som första kortet) respektive K2 (då området inte stämde). Fortsätt till dess inga kort finns kvar i L. 3. Lasta över alla kort från K1 till L. 4. Upprepa punkt 1 och 2, men låt nu korten med samma område som första kortet hamna direkt i L och övriga hos den tomhänta kvinnan. 5. Upprepa föregående punkt till dess inga kort finns kvar att plocka.
4. Kvinnoordning Damerna först sorterar t ex en vektor m a p två kategorier ( damer eller herrar ). Princip: 1. Bestäm vilket intervall som ska motsvara damer, t ex alla medlemmar med skonummer upp t o m 39 (eller vad du nu önskar sortera m a p). 2. Låt ett vänsterindex löpa från vänster till höger och stanna på det element som inte motsvarar en dam. Låt ett högerindex löpa från höger till vänster och stanna på det element som motsvarar en dam. Låt elementen vid vänster och höger index byta plats. 3. Upprepa föregående punkt till dess vänster och höger index har passerat varandra. Då antalet jämförelser som görs är proportionell mot antalet element (en genomgång görs), så är komplexiteten O(N). Fördelar: snabb sortering, inget extra minne krävs. Nackdel: kan bara sortera två kategorier. Distributionsräkning är en allmän form av damerna först. Skillnaden är att algoritmen håller reda på fler än två kategorier. Princip: 1. Bestäm vilka kategorier som ska finnas, t ex en per skonummer. Ordna en vektor med tal (kategorivektor) lika stor som antalet kategorier. 2. Gå igenom alla element för att räkna hur många element som finns av varje kategori. 3. Skapa en stor vektor med plats för alla element. Räkna om talen i kategorivektorn till index i den stora vektorn. Kategorivektorn innehåller efter detta indexet för nästa lediga plats i respektive kategori. 4. Gå igenom och placera alla element i tur och ordning på den plats som enligt elementets kategori anges i kategorivektorn. Öka för varje element indexet i kategorivektorn för den kategori elementet tillhörde. Då algoritmen går igenom alla element två gånger blir komplexiteten även här O(N). Fördelar: snabb sortering, kan sortera flera kategorier. Nackdelar: sorteringen måste baseras på något som kan diskretiseras (d v s det måste finnas ett fixt antal kategorier), mycket minne krävs för destinationsvektorn om inplaceringen ska förbli snabb. Quicksort fungerar enligt principen att först välja ett pivot som sedan används genom damerna först-sortering. Efter damerna först sorteras respektive del (damerna och herrarna) var för sig med quicksort (d v s rekursivt). Om mängden som ska sorteras bara innehåller ett element är sorteringen färdig utan rekursiva anrop. Pivotet ska helst utgöras av medianelementet i den mängd som ska sorteras (detta för att vi vill dela upp mängden på hälften). Då medianen är jobbig att räkna ut används ofta en median av tre element ur mängden, t ex första, mittersta och sista. Quicksort gör vid bra val av pivot log 2 N st damerna förstsorteringar av storleksordningnen N, d v s komplexititen blir O(Nlog 2 N). Faktorn log 2 N kommer av antalet delningar som måste göras. Se exemplet.
(8p) Exempel med talföljden 47310526: 4 7 3 1 0 5 2 6 (4 är pivot) 2 3 1 0 4 5 7 6 (efter damerna först) 2 3 1 0 5 7 6 (2 och 6 är pivot) 0 1 2 3 5 6 7 (efter damerna först) 0 1 3 5 7 (0 är pivot) 0 1 (efter damerna först) 1 5. Jämnåriga specialkvinnor Använd bästa först-sökning med priokö. Prioritera på lägsta sammanlagda ålderskillnaden utefter en gren fram till en framassocierad kvinna. För att kunna återskapa kedjan när en lösning hittats och för att kunna räkna fram nya prioritetsvärden/sammanlagda åldersskillnader krävs att varje nod i priokön, förutom information om kvinnan, håller reda på föregående nod/kvinna och framräknat priovärde. För att undvika cykler (som alltid ger en längre kedja med lägre prioritet) kan vi undvika att lägga in nya noder/kvinnor som har dykt upp tidigare och där den tidigare kedjan hade en lägre åldersskillnad. Till detta kan en hashtabell användas. Algoritm: 1. Skapa ursprungsnod med ursprungsskvinnan, ingen föregående kvinna samt priovärdet noll. 2. Placera ursprungsnoden i priokön. 3. Plocka ut en nod ur kön. 4. Kontrollera om den utplockade noden/kvinnan motsvarar det sökta intresset. I så fall har vi hittat en lösning och kan skriva ut hela kedjan (eftersom varje nod hade information om föregående nod). Avbryt. 5. Utnyttja det befintliga programmet för att få fram en lista på de kvinnor som är associerade med kvinnan i den utplockade noden. 6. Räkna ut priovärden och skapa noder för respektive framassocierad kvinna. Priovärdet blir den utplockade nodens värde plus (absoluta) ålderskillnaden mellan den framassocierade kvinnan och den utplockade nodens kvinna. 7. Slå upp respektive kvinna i en hashtabell och se efter om kedjan till den framassocierade kvinnan är bättre än noden/kvinnan i hashtabellen. Om så är fallet plockas noden/kvinnan ut ur hashtabellen för att ersättas av den nya, bättre noden/kvinnan. Lägg samtidigt in noden/kvinnan i kön. 8. Upprepa från steg 3 till dess kön är tom (eller lösning hittats enligt steg 4). Världens alla kvinnor rör sig om några miljarder. Det värsta som kan hända är att det inte finns någon lösning till problemet, dvs det finns grupper av kvinnor som aldrig kan associeras med varandra och alla kvinnor med intresset vi söker befinner sig i en annan grupp än den vi utgår ifrån. I detta fall kommer hashtabellen i vår algoritm kräva mycket utrymme (då den för varje kvinna måste hålla reda på hennes namn och priovärdet). Algoritmen kommer dock att fungera, om än troligen mycket långsammare än om en lösning finns. En annan aspekt är hur
mycket utrymme som kön tar upp. När kön är som störst finns i samma kvinna i kön flera gånger eftersom en sämre kedja till en kvinna inte försvinner ur kön när en bättre kedja hittas. Algoritmen fungerar alltså, men kräver mest utrymme och tid då det inte finns någon kedja att visa! 6. Kvinna sökes Binärsökning görs antingen i en sorterad vektor eller genom ett balanserat binärt sökträd. Algoritmen går ut på att i varje steg kasta bort den hälft man med säkerhet vet inte innehåller det sökta. Detta kan göras tack vare att elementen är ordnade i vektorn eller i det binära trädet. Steg i algoritmen (med vektor): 1. Jämför det sökta med elmentet i vektorns mitt. Är det rätt är vi färdiga, är det fel utnyttjas jämförelsen för att avgöra vilken av vektorns halva som ska utgöra en ny vektor i nästa steg. 2. Upprepa föregående steg till dess det sökta hittats eller till dess att vektorn bara innehåller ett element som visar sig vara fel, d v s att det sökta inte fanns i vektorn. (6p) Vid sökning bland N element görs log 2 N halveringar, vilket ger komplexiteten O(log 2 N). I värsta fallet avgörs sökningen vid den log 2 N:te jämförelsen. I normalfallet/medelfallet hittas det sökta ett steg tidigare, i detta fall vid log 2 8000 1 12 jämförelser. Hashning bygger på att ett element läggs in på ett speciellt index i en hashtabell/vektor. Indexet räknas fram genom att först använda en hashfunktion för att omvandla söknyckeln till ett (oftast stort) tal. Detta tal anpassas sedan för att hamna inom hashvektorns gränser (genom en moduloberäkning). Om söknyckeln är en sträng är en vanlig hashfunktion att vikta och summera varje teckenvärde i strängen. Det är dock viktigt att komma ihåg att två olika söksträngar kan ge upphov till samma tal (och därmed hamna på samma index en krock uppstår). Vid hashning ska elementen spridas ut så mycket som möjligt i vektorn så att krockarna minskar. Detta åstadkommer man genom att ha en bra hashfunktion, en storlek på vektorn som motsvarar ett primtal och genom att ha fler platser än antalet element som ska lagras ( extra luft ). Då krockar trots allt förekommer kan man istället för enstaka element lagra en krocklista på varje plats i vektorn. Vid en sökning räknas indexet fram och en linjärsökning görs i listan efter det sökta elementet. Då krocklistorna är väldigt korta innebär detta oftast en jämförelse. För att vara på säkra sidan säger man att det tar drygt en jämförelse. Komplexiteten blir således O(1), d v s i samtliga fall alltså drygt en jämförelse. 7. Kvinnor i balans Det effektivaste sättet innebär att varje namn läggs in i trädet i den ordning de dyker upp. Problemet är att trädet då måste byggas upp från vänster till höger (inorder) för att bli balanserat. Idé: utnyttja kunskapen om hur många namn som ska lagras och definiera en algoritm byggträd som bygger upp ett träd givet antalet namn som det finns att ta av. om byggträd(4711) matas med 4711 namn i bokstavsordning ska alltså resultatet bli ett balanserat träd. Rekursiv algoritm: byggträd(n)
Om n är noll returneras ett tomt träd (ingen namninläsning sker). Om n är större än noll skapas en binärnod och följande inläsningar sker: 1. byggträd(n/2), vilket ger binärnodens vänstra delträd, 2. inläsning av ett namn, vilket lagras i binärnoden, 3. byggträd(n n/2 1), vilket ger binärnodens högra delträd. binärnoden utgör roten i det träd som returneras. Komplexiteten för denna algoritm blir O(N) med hjälp av följande resonemang: För varje namn som läses lagras precis ett namn i trädet utan att för den delen behöva leta sig ned till rätt plats i trädet. (3p) 8. 8 mars, 3/8 eller 8/3? Fördelar med ett abstrakt datum: Användaren respektive konstruktören får en enklare tillvaro genom att var och en kan fokusera på sin del. Olika användare kan inte komma åt den interna representationen och kan därigenom inte missbruka eller göra fel på grund av olika tolkningssätt. Konstruktören kan förbättra representationen utan att användarna behöver anpassa sitt användningssätt. Konstruktören kan bygga ut datatypen med fler finnesser utan att påverka den befintlig användningen. Exempel på metoder: public static Date createusdate(string misorder) public static Date createeudate(string inorder) public String asinus() public String asineu() public boolean before(date other) public boolean after(date other)