LUNDS TEKNISKA HÖGSKOLA 1(5) Institutionen för datavetenskap Tentamen, EDAA20/EDA501 Programmering 2015 08 20, 8.00 13.00 Anvisningar: Denna tentamen består av fyra uppgifter. Preliminärt ger uppgifterna 8 + 19 + 7 + 6 = 40 poäng. För godkänt betyg krävs 20 poäng. Tillåtet hjälpmedel: Java-snabbreferens. Lösningsförslag kommer att finnas på kursens hemsida senast dagen efter tentamen. När rättningen är klar läggs resultatet in direkt i ladok och anslås inte på någon anslagstavla. Tentamensvillkor för EDA501: Om du tenterar utan att vara tentamensberättigad annulleras din skrivning. För att undvika att någon skrivning annulleras av misstag kommer alla som, enligt institutionens noteringar, tenterat utan att vara tentamensberättigade att kontaktas via epost. Felaktigheter i institutionens noteringar kan därefter påtalas fram till nästa tentamenstillfälle då resterande skrivningar annulleras.
2(5) 1. Java har många mer eller mindre avancerade klasser för att hantera datum och tid. Ibland kan det dock finnas anledning att skapa egna klasser för detta. En början kan vara en enkel klass för att, givet en sträng i ett visst format, spara datum och tid separat. DateTime /** Skapar ett tidpunktsobjekt innehållande tid och datum. Strängen input har formatet YYYY-MM-DD HH:MM */ DateTime(String input); /** Returnerar strängen som representerar tidpunktens tid på formatet HH:MM */ String gettime(); /** Returnerar strängen som representerar tidpunktens datum på formatet YYYY-MM-DD */ String getdate(); /** Jämför denna tidpunkt med tidpunkten d. Returnerar true om de båda innehåller exakt samma datum och tid */ boolean equals(datetime d); /** Returnerar tidpunkten som en sträng på formatet YYYY-MM-DD HH:MM */ String tostring(); Implementera klassen DateTime enligt specifikationen ovan samt följande ledning: Javas klass String innehåller metoder för att få fram varianter av en sträng i form av nya strängobjekt. Dessa metoder kan vara användbara t.ex. då en sträng behöver delas. Metoder lämpliga för uppgiften är (det är inget krav att använda samtliga metoder): String /** Returnerar en ny sträng som är en del (substring) av denna sträng. Strängen som returneras innehåller en kopia av tecknen från index beginindex fram till strängens slut. Exempel: "unhappy".substring(2) returnerar "happy" */ String substring(int beginindex); /** Returnerar en ny sträng som är en del (substring) av denna sträng. Strängen som returneras innehåller en kopia av tecknen från index beginindex fram till och med endindex - 1. Exempel: "smiles".substring(1, 5) returnerar "mile" */ String substring(int beginindex, int endindex); /** Delar strängen runt strängen r och returnerar delarna i en vektor. Exempel: "boo:and:foo".split(":") returnerar vektorn { "boo", "and", "foo" } */ String[] split(string r);
3(5) 2. På Malmös godsbangård ankommer dagligen hundratals tåg vars vagnar ska besiktas och kopplas om för att bli nya tåg på väg mot rätt destination. Tågen kommer in på ett antal spår och kopplas där isär för att sedan skickas vidare ut på spåren för avgående tåg. Information om inkommande tåg ges i form av en textfil per tåg, där varje rad innehåller information om en vagn. Baserat på informationen räknar personalen på bangården ut vilka vagnar som ska kopplas isär. För att spara tid önskar man nu istället att datorn ska räkna ut detta. Målsättningen är att koppla isär så få vagnar som möjligt enligt ett antal regler (nedan). Exempel på ingående textfil: NBR # DEPARTURE TIME # DESTINATION # LOAD WEIGHT # BREAK CAPACITY # LENGTH 1 # 2015-08-15 12:37 # CPH # 50 # 400 # 25 2 # 2015-08-15 12:37 # CPH # 50 # 100 # 25 3 # 2015-08-16 12:37 # CPH # 50 # 100 # 20 4 # 2015-08-16 12:37 # CPH # 90 # 2 # 25 5 # 2015-08-15 15:15 # HBG # 85 # 0 # 25 6 # 2015-08-15 15:15 # HBG # 100 # 100 # 25 7 # 2015-08-15 15:15 # HBG # 0 # 0 # 20 8 # 2015-08-15 15:15 # HBG # 70 # 0 # 25 9 # 2015-08-15 16:18 # YST # 10 # 300 # 25 10 # 2015-08-15 16:18 # YST # 10 # 100 # 25 11 # 2015-08-15 16:18 # YST # 30 # 100 # 33 Reglerna för hur vagnarna ska kopplas isär är följande: En vagn med 0 i lasten och en bromskapacitet på 0 ska till reparation och ska därför alltid kopplas loss från framförvarande och bakomvarande vagn (ingen speciell hänsyn behöver tas till en lastad vagn med bromskapacitet 0. En sådan ska inte särbehandlas då lasten först måste lossas vid destinationen innan reparation sker). Vagnar med olika avgångstider och/eller destination ska alltid kopplas isär. Vagnar som ska till samma destination vid exakt samma tidpunkt ska ej kopplas isär, med undantag för nästa punkt. Tågen som skickas till spåren för avgående tåg får, av tekniska skäl, vara max 80m långa (längden i filen är angiven i meter). Utdata skrivs direkt till skärmen och består av samtliga vagnsrader från indata i bibehållen ordning med en blankrad mellan alla vagnar som skall kopplas isär. Dvs genom att göra en blankrad i utdata anger vi vilka vagnar som ska kopplas isär. Översta raden i indata ignoreras och ska inte komma med i utdata. Indataexemplet ovan ger då följande resultat: 1 # 2015-08-15 12:37 # CPH # 50 # 400 # 25 2 # 2015-08-15 12:37 # CPH # 50 # 100 # 25 3 # 2015-08-16 12:37 # CPH # 50 # 100 # 20 4 # 2015-08-16 12:37 # CPH # 90 # 2 # 25 5 # 2015-08-15 15:15 # HBG # 85 # 0 # 25 6 # 2015-08-15 15:15 # HBG # 100 # 100 # 25 7 # 2015-08-15 15:15 # HBG # 0 # 0 # 20 8 # 2015-08-15 15:15 # HBG # 70 # 0 # 25 9 # 2015-08-15 16:18 # YST # 10 # 300 # 25 10 # 2015-08-15 16:18 # YST # 10 # 100 # 25 11 # 2015-08-15 16:18 # YST # 30 # 100 # 33 För att lösa problemet har vi, förutom klassen DateTime från föregående uppgift, följande klasser:
4(5) CargoWagon /** Skapar ett vagnsobjekt utifrån en textsträng input med följande format: NBR # DEPARTURE TIME # DESTINATION # LOAD WEIGHT # BREAK CAPACITY # LENGTH */ CargoWagon(String input); /** Returnerar avgångstiden för det tåg där vagnen ska ingå efter omkoppling */ DateTime getdeparturetime(); /** Returnerar vagnens längd i meter */ int getlength(); /** Returnerar destinationen till vilken vagnen ska gå efter omkoppling */ String getdestination(); /** Returnerar vikten på vagnens last i ton */ int getloadweight(); /** Returnerar vagnens bromskapacitet */ int getbreakcapacity(); /** Returnerar vagnens nummer i inkommande tåg */ int getnumber(); /** Returnerar en strängrepresentation av vagnen på formen: NBR # DEPARTURE TIME # DESTINATION # LOAD WEIGHT # BREAK CAPACITY # LENGTH */ String tostring(); Klassen CargoWagon är färdigskriven. CargoTrainUtilities /** Skapar ett objekt med information om alla vagnar i ett tåg */ CargoTrainUtilities(Scanner input); /** Beräknar och skriver ut vilka vagnar som ska kopplas loss enligt beskrivningen ovan */ void printunchained(); Samt ett exempel på en mainmetod för att testa programmet med filen Trains.txt: public static void main(string[] args) { try { Scanner s = new Scanner(new File("Train.txt")); CargoTrainUtilities util = new CargoTrainUtilities(s); util.printunchained(); } catch (FileNotFoundException e) { System.out.println("Error! The file does not exist"); } } Implementera klassen CargoTrainUtilities enligt specifikationen ovan samt följande anvisningar: CargoTrainUtilities ska innehålla en ArryList med CargoWagon-objekt. Denna lista ska, efter att objektet skapats, alltid representera hela det inkommande tåget och ska alltså vara oförändrad även efter att printunchained exekverats.
5(5) 3. Godsbolagen har insett att de har ganska mycket bromsproblem. För att få överblick över detta vill de ha ett tillägg till klassen CargoTrainUtilities. Vi får därför i uppgift att implementera en metod som skriver ut alla tågets vagnar sorterat stigande med avseende på bromskapaciteten (varje vagn ska skrivas ut på samma format som tidigare). Utökning av klassen CargoTrainUtilities void printsortedbybreakcapacity(); Implementera metoden printsortedbybreakcapacity enligt följande anvisningar: Om två vagnar har samma bromsvikt ska deras inbördes ordning i tåget inte brytas, d.v.s. om både vagn 5 och 6 har bromkapacitet 20 ska 5 skrivas ut först och 6 därefter. Listan över tågets vagnar ska ju alltid representera det inkommande tåget och ska alltså vara oförändrad även efter att printsortedbybreakcapacity exekverats. Tips: Enklast är att skapa en ny lista och där sätta in elementen på ett sådant sätt att den nya listan hela tiden hålls sorterad (en variant av insättningssortering = sätta in ett nytt element i en redan sorterad följd upprepade gånger). 4. Godsbolagets logistikavdelning behöver veta hur stor del av vagnarnas kapacitet som utnyttjas och behöver därför en metod för att samla in statistik om detta. Metoden ska returnera en vektor som innehåller information om hur många vagnar i tåget som är lastade med 0-10 ton, 11-50 ton och mer än 50 ton. Exemplet ovan skulle således ge oss följande vektor: 3 4 4 Utökning av klassen CargoTrainUtilities int[] getloadstatistics(); Implementera metoden getloadstatistics.