Sekvenser af længde mellem 1 og 4 ord repræsenteres ved en klasse Segment, som uden grundlæggende ser således ud:

Relaterede dokumenter
Abstrakte datatyper C#-version

Skriftlig eksamen i Datalogi

Ugeseddel 4 1. marts - 8. marts

AAU, Programmering i Java Intern skriftlig prøve 18. maj 2007

b) Udvid din implementation af forme til at understøtte.equals. To objekter af samme form er ens hvis de har samme værdier i felterne.

Datalogi OB, Efterår 2002 OH er, forelæsning 10/ Klasser og nedarvning

Hashing og hashtabeller

Hashing og hashtabeller

Tree klassen fra sidste forelæsning

Løsning af møntproblemet

University of Southern Denmark Syddansk Universitet. DM502 Forelæsning 4

DANMARKS TEKNISKE UNIVERSITET

Videregående Programmering Obligatorisk opgave - 3. semester, efterår 2004

Tabelbegrebet. Klassediagrammer (III) Oversigt. Anvendelse af Tabeller. Tabeller og qualified associations

Skriftlig eksamen i Datalogi

Klasser og nedarvning

class Time { int hours, min; } } Time t1; // Erklær variabel af type Time class Time1 { public static void main(string[] args) { Time t1; t1.

DM01 DM Obl. Afl. Jacob Christiansen, , D12, Elias 18/ Side 1 af 11

Tabeller (I) Tabeller

DM507 Algoritmer og datastrukturer

Rekursion og dynamisk programmering

Eksempel: Skat i år 2000

DM507 Algoritmer og datastrukturer

DM507 Algoritmer og datastrukturer

DM507 Algoritmer og datastrukturer

DM507 Algoritmer og datastrukturer

Forelæsning Uge 4 Mandag

Kursus i OOP og Java. Kursus i Objektorienteret programmering i Java

Kursus navn: Indledende programmering Kursus nr

Anvendelse af metoder - Programmering

Kursusarbejde 3 Grundlæggende Programmering

Civilingeniøreksamen januar Skriftelig prøve den 12. januar 2001 Kursusnummer 49104

Forelæsning 17, tirsdag 2. november 1999 Søgning efter en given værdi i en tabel. Programmering 1999

Programmering 1999 KVL Side 5-4. Klassen Time: metoder. Metoder i objektet giver mulighed for at ændre tilstanden, eller kigge på tilstanden.

University of Southern Denmark Syddansk Universitet. DM502 Forelæsning 3

Opgaven fortsat. Opfølgning på Opgave 2 og Use Cases. Opgaven. Trin 1: Væsentlige begreber. Resultatliste: 100 bryst, herrer

BRP Tal. Om computer-repræsentation og -manipulation. Logaritmer

Forelæsning Uge 4 Torsdag

//Udskriver System.out.println("Hej " + ditfornavn + " " + ditefternavn + "."); System.out.println("Du er " + dinalder + " aar gammel!

Forelæsning Uge 4 Mandag

DM502. Peter Schneider-Kamp

Bits, bit operationer, integers og floating point

Opfølgning på Dygtig Skildpadde (Michael) To algoritmeskabeloner

Skriftlig eksamen i Datalogi

Forelæsning Uge 4 Mandag

Algoritmeskabeloner: Sweep- og søgealgoritmer C#-version

Martin Olsen. DM507 Projekt Del I. 19. marts 2012 FOTO: Colourbox

DM507 Algoritmer og datastrukturer

Studiepraktik. Thomas Bøgholm Mikkel Hansen Jacob Elefsen

Forelæsning Uge 2 Torsdag

Forelæsning Uge 2 Torsdag

DM01 DM Obl. Afl. Jacob Christiansen, , D12, Elias 13/ Side 1 af 7

Grundlæggende Programmering ITU, Efterår Skriftlig eksamen i Grundlæggende Programmering

Datalogi OB, Efterår 2002 OH er, forelæsning 3/ forstå datastrukturer og algoritmer (teoretisk forståelse og intuition)

Sekvensafstand DM34 - Eksamensopgave. Jacob Aae Mikkelsen

Find største element, sæt det på sidste plads. Grundidé i hobsortering. er er

Test af It-komponent

public Set(int size) { this.listelement = new LinkedList<Integer>(); }

class subklasse-navn extends superklasse-navn { } NorwaySpruce har superklassen Spruce, som igen har superklassen Tree.

University of Southern Denmark Syddansk Universitet. DM502 Forelæsning 2

DM507 Algoritmer og datastrukturer

Forelæsning Uge 4 Torsdag

RMI introduktion. Denne artikel beskriver Java RMI (Remtote Method Invocation).

Threads i Java. Denne artikel giver en introduktion til threads i Java. Den beskriver hvad tråde er og forklarer hvordan de bruges i Java

Offset til terminalskærm i Java

A Profile for Safety Critical Java

DM507 Algoritmer og datastrukturer

Skriftlig eksamen i Datalogi

BRP Kursusintroduktion og Java-oversigt

Syntaks og syntaksgenkendelse, særligt regulære udtryk og tilstandsmaskiner og lidt om anvendelser i bioinformatik

Forelæsning Uge 5 Mandag

Design by Contract Bertrand Meyer Design and Programming by Contract. Oversigt. Prædikater

DM507 Algoritmer og datastrukturer

Forelæsning Uge 3 Mandag

RMI avanceret. Denne artikel beskriver nogle mere avancerede features i RMI. Den gør det muligt at lave mere realistiske applikationer.

Forelæsning Uge 6 Mandag

Spil Master Mind. Indledning.

Det er muligt at chekce følgende opg. i CodeJudge: og

Vejledende løsninger

Java Klasse nedarvninger

Prepared Statements. Denne artikel beskriver hvorfor prepared statements er gode. Den forudsætter lidt kendskab til Java og JDBC.

Forelæsning Uge 2 Mandag

COMPUTERSPIL 1. Opgave 1. Opgave 2

Singleton pattern i C#

Singleton pattern i Java

Tilfældige tal. Denne artikel introducerer generering af tilfældige tal og viser lidt om hvad man kan og ikke mindst hvad man ikke bør bruge.

Parameters. Denne artikel beskriver hvorfor parameters er gode. Den forudsætter lidt kendskab til C# og ADO.NET.

Hvad er Objekter - Programmering

Kapitel 3 Betinget logik i C#

Forelæsning Uge 3 Mandag

Forelæsning Uge 2 Torsdag

14.1 Internationale programmer

Introduktion til datastrukturer. Philip Bille

Forelæsning Uge 3 Mandag

Indledning. Hvorfor det forholder sig sådan har jeg en masse idéer om, men det bliver for meget at komme ind på her. God fornøjelse med læsningen.

Forelæsning Uge 3 Mandag

University of Southern Denmark Syddansk Universitet. DM503 Forelæsning 11

Hvordan vælger jeg dokumentprofilen?

Forelæsning Uge 2 Torsdag

Forelæsning Uge 2 Mandag

Transkript:

Besvarelse af opgave til formuleret til øvelserne 10. september 2002 Datastrukturer og algoritmer Henning Christiansen 22/9-2002 Følgende er ikke en eksakt besvarelse af opgaven, idet den benytter hashtabeller og ikke den banale array-repræsentation, som er foreslået i opgaven (hashtabeller først omtalt på kurset efter opgaven blev stillet). Opgaveformuleringen forudsættes kendt og forstået. Kildetekst til besvarelse: Word.java, Segment.java, SegmentCount.java Spørgsmål 1 Word-klassen har kun et ikke-statisk medlem som er en heltalsvariabel kaldet wordno. Konstruktoren kaldes med en tekststreng som parameter, og klassen opretholder en en-tilen relation mellem streng og wordno for de strenge som er forekommet (dvs. sendt med konstruktoren). En hashtabel som er fælles for alle objekter i klassen afbilder strenge over i wordno, så den kan bruges af konstruktoren. Første forekommende streng tildeles nr. 0, næste nr. 1, og så fremdeles. For at kunne implementere en tostring metode på effektiv måde opretholdes afbildningen fra nummer til faktisk string i et array, så Word objekt med nr. n har sin streng i dette arrays position n. Endelig indeholder klassen en equals-metode som sammenligner på wordno. Kildeteksten Word.java minus faciliteter til de efterfølgende spørgsmål kan skitseres som følger: public class Word { public Word(String s) {Object foundwordno; if( (foundwordno = table.get(s))!= null ) wordno = ((Integer)foundWordNo).intValue(); else { wordno = wordcount++; table.put(s, new Integer(wordNo)); stringtable[wordno]=s; public String tostring() {return stringtable[wordno]; // the following very inefficient way to compare two ints... sic, Java :( public boolean equals(object rhs){ if(rhs==null getclass()!= rhs.getclass()) return false; return wordno == ((Word)rhs).wordNo; private int wordno; public int wordno() {return wordno; private static int wordcount = 0; private static HashMap table = new HashMap(10000); private static String [] stringtable = new String [10000]; } Spørgsmål 2 Sekvenser af længde mellem 1 og 4 ord repræsenteres ved en klasse Segment, som uden grundlæggende ser således ud:

public class Segment { public static final int maxsegmentlength = 4; // hardwired in code :( Word [] words; public Segment(Word w1) { words = new Word [1]; words[0]=w1; public Segment(Word w1,word w2) { words = new Word [2];words[0]=w1;words[1]=w2; public Segment(Word w1,word w2,word w3) { words = new Word[3];words[0]=w1;words[1]=w2;words[2]=w3; public Segment(Word w1,word w2,word w3,word w4) { words = new Word[4];words[0]=w1;words[1]=w2;words[2]=w3; words[3]=w4; public String tostring() {String s =""; for(int i=0; i<words.length; i++) s= s + " " + words[i]; return s;} } public boolean equals(object rhs){ if(rhs==null getclass()!= rhs.getclass()) return false; if(words.length!= ((Segment)rhs).words.length) return false; for(int i=0; i<words.length; i++) if(!words[i].equals( ((Segment)rhs).words[i])) return false; return true; Vi har valgt at repræsentere sekvensen ved et array af Word objekter, hvor længden af arrayet svarer til antallet af ord. Der er fire forskellige konstruktører svarende til de forskellige længder. Dette er ikke helt hensigtsmæssigt, da der skal skrives nye konstruktører såfremt nogen kunne finde på at sætte den mulige maksimale sekvenslængde op. Det havde været mere hensigtsmæssigt i det lys med kun en konstruktor (der så skulle tage et array eller lignende af Word objekter som argument). Optælling af strenge sker ved en separat klasse SegmentCount der indeholder en hashtabel fra segment til antal gange det er forekommet, og så en main-metode som indlæser ord fra en fil. Opgaveformuleringen beskriver, at inputfilen skal slutte med ordet endoffile så vi kan bruge det til at teste om vi er færdige. For at få det til at virke, tilføjer vi følgende til Word klassen: private static int endoffilewordcount; public boolean isendoffileword() {return wordno == endoffilewordcount; public static Word readword(filereader f) {... se kildetekst... Konstanten endoffile defineres i en statisk initialiseringdel i Word ved at skrive new Word("endoffile"); endoffilewordcount=wordcount-1; public boolean isendoffileword(){return wordno==endoffilewordcount;

Klassen SegmentCount kan skitseres som følger; det bliver noget forgræmmet på grund af indlæsning fra fil: public class SegmentCount { public static void main(string [] args) throws IOException{ FileReader datafile = new FileReader("duckling"); Word w1 = Word.readWord(dataFile); Word w2 = Word.readWord(dataFile); Word w3 = Word.readWord(dataFile); Word w4 = Word.readWord(dataFile); while(!w4.isendoffileword()) {count(new Segment(w1)); count(new Segment(w1,w2)); count(new Segment(w1,w2,w3)); count(new Segment(w1,w2,w3,w4)); w1=w2;w2=w3;w3=w4;w4=word.readword(datafile); //the end count(new Segment(w1)); count(new Segment(w1,w2)); count(new Segment(w1,w2,w3)); count(new Segment(w2)); count(new Segment(w2,w3)); count(new Segment(w3)); //print out those occurring 3 or more times slettet her, da det bliver meget klodset pga. designbøffer i Java; se kildetekst private static HashMap segmentcounts = new HashMap(10000) ; private static class IntegerVar //to be use in segmentcounts only {public int value; public IntegerVar(int i){value=i; public void inc(){value++; public String tostring(){return ""+value; public static void count(segment s) {Object foundsegcount; if( (foundsegcount = segmentcounts.get(s))!= null ) ((IntegerVar)foundSegCount).inc(); else segmentcounts.put(s, new IntegerVar(1)); Strukturen omkring hashtabellen skyldes at vi ikke kan opbare heltal i en hashtabel, men det skal være noget som er underklasse af Object. Vi kunne i princippet benytte objekter af java.lang s Integer klasse, men de har den egenskab, at deres værdi ikke kan tælles op (de er immutable ). Det ville betyde, at for at tælle én op for en sekvens, så skulle vi slette en indgang i hashtabellen (med det gamle Integer objekt), oprette en ny Integer objekt med en højere værdi og endelig lægge det eksplicit ind i tabelle. For at undgå alt det, har vi indført en lokal klasse IntegerVar som kan tælles op med med en metode inc.

Bemærk at koden som foretager optællingen er afhængig af at den valgte max-længde for sekvenser. Det ville være bedre at formulere denne del af koden i form af en løkkekonstruktion, som aflæste konstanten maxsegmentlength i klassen Segment. Spørgsmål 3 Der beskrives en løsning, som tager hensyn til de såkaldte stopwords med det samme. Desuden tages der et særligt hensyn til ordet the som ikke fremgår af opgaven; forklares nedenfor. Vi har indført en metode i klassen Segment som afgør om det givne segment er interessant: public boolean isinteresting() {... For at kunne implementere den må vi kunne klassificere de enkelt Word objekter i underarter. En mulighed kunne være at lave forskellige underklasser af Word, men det ville medføre at Java-Compileren må tilføje ekstra dynamisk typeinformation til den faktiske objektrepræsentation. I stedet har vi valgt at koble bool ske metoder på Word klassen, som spørger til arten af Word objektet. Stopord skal indlæses fra en fil når klassen startes, så derfor har Word en statisk initialiseringsdel, som gør det. Implementationen er så visseligt indrettet, at den tildeler ordnr. 0 til end-of-file. Derefter indlæses all stopordene og oprettes med new... dvs. de får de efterfølgende numre, og vi kan registrere ordtællerens aktuelle værdi i en skjult variabel maxstopwordcount; dvs. ord med lavere nummer er stopord, med højere, ikke et stopord. Som et eksperiment er artiklen the ikke i dette program opfattet som storord, men som et særligt ord (det kommer vi til senere). Den statiske initialiseringsdel i word bliver nu sådan her (bemærk, at stopordsfilen også forventes at slutte med endoffile ): new Word("endoffile"); endoffilewordcount = wordcount-1; FileReader stopwordfile = new FileReader("stopwords"); Word w = readword(stopwordfile); while(!w.isendoffileword()) w=readword(stopwordfile); maxstopwordcount = wordcount-1; new Word("the"); thewordcount = wordcount-1; Metoderne i klasse Word til klassifikation bliver nu således: public boolean isstopword() {return wordno <= maxstopwordcount; public boolean istheword() {return wordno == thewordcount; public boolean isendoffileword() {return wordno == endoffilewordcount; public boolean iscontentword() {return!isstopword() &&!istheword(); Som det fremgår indfører vi en ny kategori ContentWord som er alt som ikke er stopord eller the ; bemærk at end-of-file på denne måde også kategoriseres som stopord, men det skulle helst være lige meget, da den ikke er tænkt at skulle proppes ind i segmenter. Vi kan nu udfylde metoden i Segment som afgør hvorvidt en sekvens er interessant (dvs. om vi gider at tælle den med): public boolean isinteresting() { if(words[0].isstopword()) return false; if(!words[words.length-1].iscontentword()) return false;

return true; Det er lige for at modificere main metoden i SegmentCount så den kun tæller de interessante med. Vi har i udskriften af analysen af den grimme ælling på engelsk begrænset os til at vise sekvenser på længde 3 og derover som forekommer mindst 4 gange: among the rushes: 3 the tom cat: 4 said the hen: 3 the poor duckling: 3 the poor little: 4 said the duckling: 3 said the old duck: 3 said the duck: 3 said the old: 4 said the mother: 4 the old duck: 3