TDT4165 PROGRAMMING LANGUAGES. Exercise 02 Togvogn-skifting



Like dokumenter
TDT4165 PROGRAMMING LANGUAGES. Exercise 01 Introduksjon til Oz

Norsk informatikkolympiade runde

Bygg et Hus. Steg 1: Prøv selv først. Sjekkliste. Introduksjon. Prøv selv

N-dronningproblemet Obligatorisk oppgave 1 I120, H-2000

TDT Øvingsforelesning 1. Tuesday, August 28, 12

2 Om statiske variable/konstanter og statiske metoder.

Mattespill Nybegynner Python PDF

TDT4102 Prosedyre og Objektorientert programmering Vår 2015

Oppgave: BOW Bowling. Regler for Bowling. norwegian. BOI 2015, dag 1. Tilgjengelig minne: 256 MB

TDT4165 PROGRAMMING LANGUAGES. Exercise 4 RC-kretser

EKSAMEN Løsningsforslag. med forbehold om bugs :-)

Rekursjon og lister. Stephan Oepen & Erik Velldal. 1. februar, Universitetet i Oslo

Tre på rad mot datamaskinen. Steg 1: Vi fortsetter fra forrige gang. Sjekkliste. Introduksjon

Robotinvasjon Introduksjon ComputerCraft PDF

Norsk informatikkolympiade runde. Sponset av. Uke 46, 2017

INF2810: Funksjonell Programmering. Lister og høyereordens prosedyrer

INF2810: Funksjonell Programmering. Lister og høyereordens prosedyrer

Rekursiv programmering

Utførelse av programmer, metoder og synlighet av variabler i JSP

Hei verden Introduksjon Swift PDF

Hendelser Apprentice ComputerCraft PDF

Norsk informatikkolympiade runde

Sist forelesning snakket vi i hovedsak om trær med rot, og om praktisk bruk av slike. rot. barn

Algoritmer og datastrukturer Løsningsforslag

Argumenter fra kommandolinjen

"behrozm" Oppsummering - programskisse for traversering av en graf (dybde først) Forelesning i INF februar 2009

MAT1030 Diskret matematikk

Drosjesentralen. I-120: Obligatorisk oppgave 2, 2000

EKSAMEN. Dato: 18. mai 2017 Eksamenstid: 09:00 13:00

TDT4102 Prosedyreog objektorientert programmering Vår 2016

Enkle generiske klasser i Java

Informasjon Eksamen i IN1000 høsten 2017

Mars Robotene (5. 7. trinn)

Obligatorisk oppgave 2 i INF 4130, høsten 2009

Definisjon av binært søketre

UNIVERSITETET I OSLO

INF2810: Funksjonell Programmering. Lokale variabler. Og trær.

Oppsummering. MAT1030 Diskret matematikk. Oppsummering. Oppsummering. Eksempel

Import av varer fra Excel

UNIVERSITETET I OSLO

Algoritmer og Datastrukturer

TDT4102 Prosedyre og Objektorientert programmering Vår 2014

Installere JBuilder Foundation i Mandrake Linux 10.0

Kondisjonstest. Algoritmer og datastrukturer. Python-oppgaver. Onsdag 6. oktober Her er noen repetisjonsoppgaver i Python.

Fra Kap.10 Binære søketre (BS-tre) Sist oppdatert Definere en abstrakt datastruktur binært søketre. Vise hvordan binær søketre kan brukes

TDT4102 Prosedyre og Objektorientert programmering Vår 2014

Humanware. Trekker Breeze versjon

INF1000 HashMap. Marit Nybakken 2. november 2003

UNIVERSITETET I OSLO

Bygg et Hus. Introduksjon. Steg 1: Prøv selv først. Skrevet av: Geir Arne Hjelle

UNIVERSITETET I OSLO

Løsnings forslag i java In115, Våren 1996

MAT1030 Forelesning 19

Øving 0 - Xcode TDT4102

TDT4110 IT Grunnkurs Høst 2012

Bli Kjent med Datamaskinen Introduksjon ComputerCraft PDF

Skilpadder hele veien ned

Norsk informatikkolympiade runde

Del 2. Anmodning om ditt sertifikat

Norsk informatikkolympiade runde

Løsningsforslag Kontinuasjonseksamen i TDT4110 Informasjonsteknologi - grunnkurs

Stack. En enkel, lineær datastruktur

Bygge en kube. Introduksjon. Steg 1: Lage en ny mod. Skrevet av: Pål G. Solheim

Ny/utsatt EKSAMEN. Dato: 6. januar 2017 Eksamenstid: 09:00 13:00

INF2810: Funksjonell Programmering. Lokale variabler. Og trær.

UNIVERSITETET I OSLO

First edition. Copyright Orion Billing A/S All rights reserved

INF2810: Funksjonell Programmering. Mer om verditilordning og muterbare data.

Oppgaver til kodegenerering etc. INF-5110, 12. mai, 2015

Bygge en kube. Steg 1: Lage en ny mod. Sjekkliste. Introduksjon

Oblig 4 (av 4) INF1000, høsten 2012 Værdata, leveres innen 9. nov. kl

Veileder i bruk av GoodReader

Definisjon: Et sortert tre

INF2810: Funksjonell Programmering. Mer om verditilordning og muterbare data.

MAT1030 Plenumsregning 3

Lagring av EndNote stil fra EndNotes hjemmeside når du bruker Mac

Repetisjon Novice Videregående Python PDF

Backtracking som løsningsmetode

Hva er en algoritme? INF HØSTEN 2006 INF1020. Kursansvarlige Ragnar Normann E-post: Dagens tema

Legg bort skilpaddene dine, i dag skal vi lære hvordan vi kan sende hemmelige beskjeder!

Enarmet banditt Nybegynner Scratch Lærerveiledning

HØGSKOLEN I SØR-TRØNDELAG

Norsk informatikkolympiade runde. Sponset av. Uke 46, 2016

Straffespark Introduksjon Scratch Lærerveiledning

Sprettball Erfaren ComputerCraft PDF

Inf109 Programmering for realister Uke 5. I denne leksjonen skal vi se på hvordan vi kan lage våre egne vinduer og hvordan vi bruker disse.

EKSAMEN med løsningsforslag

Skilpaddefraktaler Erfaren Python PDF

Norsk informatikkolympiade runde. Sponset av. Uke 46, 2015

Algoritmer og datastrukturer Eksamen

INF2220: Forelesning 1. Praktisk informasjon Analyse av algoritmer (kapittel 2) (Binær)trær (kapittel )

Obligatorisk oppgave 4 i INF1010, våren 2014: "Leger og resepter" Versjon 1.1

EKSAMEN. Dato: 28. mai 2018 Eksamenstid: 09:00 13:00

<?php. count tar en array som argument, og returnerer et tall som uttrykker antallet innførsler i arrayen.

TDT4100 Objektorientert programmering

Binære søketrær. En ordnet datastruktur med raske oppslag. Sigmund Hansen

Kap. 4: Ovenfra-ned (top-down) parsering

IN Algoritmer og datastrukturer

En kort innføring i Lotte-Typehushold

Transkript:

TDT4165 PROGRAMMING LANGUAGES Fall 2012 Exercise 02 Togvogn-skifting Problembeskrivelse Du er sjef for å skifte vognene til et tog. Vi antar at hver vogn selv har en motor og at toget ikke har noe lokomotiv. Beskrivelsen av oppgaven din er gitt ved to sekvenser av vogner: sånn toget er før du begynner og sånn du ønsker det skal bli. Din oppgave er å omordne toget ved hjelp av en byttestasjon sånn at du ender opp med det ønskelige toget. Du skal ikke bare gjøre om på rekkefølgen, men gjøre dette ved hjelp av flytt. Byttestasjonen er vist i Figur 1. Den har et hovedspor main og to byttespor tracka og trackb. En situasjon på byttestasjonen er kalt en tilstand. Et flytt beskriver hvordan vogner flytter fra spor til spor. Figur 1: Togets byttestasjon Mål Det endelig målet med denne oppgaven er å finne en kort sekvens av flytt som endrer en sekvens av vogner til på main til en annen konfigurasjon på main. Før vi prøver oss på dette målet skal vi fikse på modelleringen av problemet vårt og utvikle litt hjelp for å behandle lister. Oppgavens mening I denne øvingen skal vi se på mange viktige ting: Hvordan blir et problem modellert i datastrukturer som lister og poster (records)? Hvordan blir lister behandlet? Dette strekker seg fra enkle til mer kompliserte mønstre av rekursjon over lister. I tillegg er det meningen av oppgaven skal få deg godt i gang med Oz og Mozart. Sist, men ikke minst, håper vi at du har det litt moro med å 1

løse denne oppgaven. For å gjøre det litt mer moro har vi lagt med et program du kan bruke for å visualisere hva algoritmen din gjør. Modellering Tog, vogner og tilstander Vogner er framstilt som atomer, og tog på banen er lister av atomer. Et tog har ingen duplikatvogner (det betyr at [a b] er et gyldig tog, mens [a a] ikke er gyldig). En komplett beskrivelse av tilstanden til byttestasjonen består av tre lister: en liste som beskriver main og to lister som beskriver sporene tracka og trackb. En full tilstand er da en post (record) med main, tracka og trackb som feltnavn (features) med de tilsvarende listene som felter (fields). I tillegg skal merkelapp (label) for posten være state. Figur 2: Et eksempel på en tilstand Tilstanden state(main:[a b] tracka:[d] trackb[c]) er vist i Figure 2. Flytt Et flytt har en verdi, lagret som et felt i en tuppel (tuple) med merkelappen tracka eller trackb. (Tupler er det samme som poster, bare uten å spesifisere feltnavn.) Hvert flytt inneholder et tall, som sier hvor mange vogner som blir flyttet. For eksempel: tracka(2), trackb(2) og tracka(~3) er alle flytt. Utføre et flytt gitt en tilstand Flytt beskriver hvordan en tilstand blir endret til en annen tilstand: Om flyttet er tracka(n) og N er større enn null, så blir de N vognene lengst mot høyre flyttet fra main til tracka. Om det er flere enn N voger på main så blir resten igjen. Om flyttet er tracka(n) og N er mindre enn null, så blir de N vognene lengst mot venstre flyttet fra tracka til main. Om det er flere enn N vogner på tracka så blir resten igjen. Flyttet tracka(0) har ingen effekt. Det samme gjelder for trackb(0). 2

Figur 3: Flere flytt utført på tilstander Eksempel Figur 3 viser eksempler på flytt gjort på tilstander. (a) er starttilstanden, (b) etter tracka(1), (c) etter trackb(1) og tilslutt (d) etter tracka(~2). Task 1 Litt listebehandling Før du starter skal du lage noen listebehandlingsrutiner som trengs senere. {Length Xs} returnerer lengden til listen Xs {Take Xs N} returnerer en liste med de N første elementene av listen Xs. Om N er større enn antall elementer i Xs skal hele listen returneres i stedet. {Drop Xs N} returnerer Xs uten de første N elementene. Om N er større enn antall elementer i Xs skal nil returneres. {Append Xs Ys} returnerer en liste med alle elementene i Xs etterfulgt av alle elementene i Ys. {Member Xs Y} returnerer sann om Y finnes i Xs og usann ellers. {Position Xs Y} returnerer posisjonen til det første tilfellet av Y i Xs. Du kan gå ut i fra at Y finnes i listen. Om du gjorde øving 1 kan du simpelthen kopiere løsningen derfra. Du kan også bruke biblioteket til å implementere de oppgitte signaturene, men dette kan være litt knotete, så det er kanskje lærerikt det også. Uansett, legg alle definisjonene i en fil List.oz. Du kan inkludere dem i programmet ditt ved å skrive \insert List.oz før koden som bruker dem. 3

Task 2 Utføre flytt Den første deloppgaven er å skrive en funksjon ApplyMoves som tar inn en starttilstand og en liste av flytt. Den resulterer i en liste med tilstander. Om listen med flytt har N elementer vil den resulterende listen over tilstander ha N+1 elementer. Det første elementet er starttilstanden og det siste er den tilstanden toget endrer opp i. For eksempel: {ApplyMoves state(main:[a b] tracka:nil trackb:nil) [tracka(1) trackb(1) tracka(~1)]} returnerer listen [state(main:[a b] tracka:nil trackb:nil) state(main:[a] tracka:[b] trackb:nil) state(main:nil tracka:[b] trackb:[a]) state(main:[b] tracka:nil trackb:[a])] Vise frem tilstander For å få en forståelse av tilstander kan du bruke det medfølgende visualiseringsprogrammet. For å bruke det må du laste ned Visualizer.zip fra hjemmesiden til faget, og pakke det ut i katalogen der filene dine ligger. Deretter kan du inkludere linjen \insert Visualizer.oz i koden din, og kalle prosedyren Visualize på en liste over tilstander. Du kan prøve å visualisere eksempelet over. Prev og Next knappene gjør det mulig å gå gjennom tilstandene. Struktur Nå kan vi lage ApplyMoves. Angrip oppgaven på denne måten: Utfør hvert flytt rekursivt i rekkefølge. Om det ikke er noen flytt som skal gjøres (tom liste) skal en liste med starttilstanden som eneste element returneres. For hvert flytt skal programmet ditt bestemme ved mønstergjenkjenning hvilket spor som er innblandet. For hvert spor må du finne ut om vognene blir flyttet fra eller til sporet (om N er negativ eller positiv). Å ta vogner fra slutten av toget kan gjøres ved å bruke Length og Drop; å ta vogner fra starten av toget kan gjøres ved å bruke Take; å legge til vogner til et spor kan gjøres ved å bruke Append. 4

Om S er en tilstand kan man få vognene på main ved å ta S.main. Strukturen til ApplyMoves kan se slik ut: fun {ApplyMoves S Ms} %% S is the state, Ms the list of moves to be applied %% Returns list of resulting states case Ms of nil then... [] M Mr then %% Compute S1 as new state S1 = case M of tracka(n) then if... then... else... end [] trackb(n) then end in... end end if... then... else... end Lagre programmet ditt i ei fil kalt ApplyMoves.oz Ikke glem å bruke visualiseringsprogrammet for å overbevise deg selv om at løsningen din virker. Task 3 Å finne flytt Lag en funksjon Find some tar to tog Xs og Ys som input og returner en liste med flytt slik at flyttene transformerer tilstanden: state(main:xs tracka:nil trackb:nil) til state(main:ys tracka:nil trackb:nil) Xs og Ys må her inneholde de samme elementene(vogner) og hver vogn må være unik. Dette betyr at Xs er en permutasjon av Ys. Angrip oppgaven slik. Problem skal løses rekursivt og hvert steg skal flytte en vogn til en posisjon krevd av Ys. Grunntilfellet er enkelt. flytt. Om det ikke er noen vogner trengs det ingen Ellers tar vi den første vognen Y fra Ys(det ønskede toget). Vårt mål er å finne en liste med flytt som fører vognen Y fremst på main. Dette er gjort på følgende måte 5

Del opp toget Xs i vognene Hs (hode) og Ts (hale) hvor Hs er vognene før Y i Xs og Ts er vognene etter Y i Xs. Skriv en funksjon SplitTrain som tar en liste av vognene Xs og vognen Y og returnerer paret Hs#Ts. For eksempel: {SplitTrain [a b c] a}= nil#[b c] Bruk funksjonene Position, Take og Drop. Flytt Y og de følgende vognene(ts) til spor tracka. Flytt resten av vognene(hs) til spor trackb. Flytt alle vognene fra tracka til main (inkludert Y). Flytt alle vognene fra trackb til main. Etter at du har flyttet en vogn til riktig posisjon trenger vi bare å se på resten av vognene av både Xs og Ys (i den nye rekkefølgene på main ) Lagre programmet ditt i Find.oz Visualisere flytt Du kan bruke visualiseringsprogrammet til å se at du gjør det riktig. Eksempel Gitt inputtoget [a b] og outputtoget[b a] er listen over flytt som blir laget av Find: [tracka(1) trackb(1) tracka(~1) trackb(~1) tracka(1) trackb(0) tracka(~1) trackb(0)] Task 4 Finn færre flytt Lag en funksjon FewFind som oppfører seg som Find, men for hver rekursiv operasjon tar for seg om den neste vognen allerede er i riktig posisjon. Hvis den er i riktig posisjon, er ingen flytt nødvendig. Gjør noen få endringer i ditt program Find (bare noen få modifikasjoner trengs). Lagre programmet ditt i FewFind.oz. Eksempel Gitt inputtoget [c a b] og outputtoget [c b a] er listen over flytt med FewFind: [tracka(1) trackb(1) tracka(~1) trackb(~1)] 6

Task 5 Enda færre flytt Listen over flytt laget av FewFind er fremdeles dårlig og kan lett optimiseres ved å innføre følgende regler: Erstatt tracka(n) direkte etterfulgt av tracka(m) med tracka(n+m). Erstatt trackb(n) direkte etterfulgt av trackb(m) med trackb(n+m). Fjern tracka(0). Fjern trackb(0). Disse forbedringene er korrekt på den måten at en kortere liste av flytt vil føre til den samme sluttilstanden. Den oppgaven er litt vanskeligere. Tenk for eksempel på: [trackb(~1) tracka(1) tracka(~1) trackb(1)] Om man bruker reglene over flere ganger vil det resultere i ingen flytt i det hele tatt. Ved å bruke den øverste regelen får vi [trackb(~1) tracka(0) trackb(1)] den tredje gir [trackb(~1) trackb(1)] den andre gir [trackb(0)] og til slutt gir regel fire nil Lag en funksjon Compress som tar en liste med flytt og returnerer en komprimert liste med flytt. Angrip denne oppgaven sånn: Lag en funksjon ApplyRules som kjører gjennom regler rekursivt. Deretter kjører du ApplyRules om igjen til listen av flytt ikke endrer seg. Compress blir seende sånn ut: 7

fun {Compress Ms} Ns={ApplyRules Ms} in if Ns==Ms then Ms else {Compress Ns} end end Lagre programmet ditt i Compress.oz Task 6 Finn virkelig få flytt Problemet med både Find og FewFind er at du alltid putter alle vognene fra tracka og trackb tilbake til main selv om det kan hende det finnes muligheter for å bruke tracka og trackb til å dytte vognene i riktig posisjon. Vi skal utnytte dette. Lag en funksjon FewerFind som tar fire argumenter: Ms for vognene på main, Os for vognene på tracka, Ts for vognene på trackb og Ys som er ønsket tog. FewerFind virker rekursivt som før og hvert rekursive kall vil flytte vognen Y av Ys til den riktige posisjonen. Det som er nytt er at en vogn kan være på hvilket som helst spor. Om Y finnes i Ms flytt den til riktig posisjon som gjort tidligere, men la vognene som flyttes unna stå igjen på spor tracka og trackb. Om Y er på spor Os: Flytt vognene som er foran først til main også til trackb. Deretter flytt Y til sin posisjon. Hvis ikke så lar vi vognene på tracka og trackb være uendret. Dette legger til en vogn i riktig posisjon på main. Gjør det samme for trackb. Hvert rekursive kall til FewerFind må selvsagt fordele vognene riktig mellom alle tre sporene. Når FewerFind kalles første gang er tracka og trackb tomme lister. For eksempel: {FewerFind [a b] nil nil [b a]} returnerer [tracka(1) trackb(1) tracka(~1) trackb(0) tracka(0) trackb(~1)] Lagre programmet ditt i FewerFind.oz 8