Anvendelser I Leg og spil.

Slides:



Advertisements
Lignende præsentationer
1 Problemkompleksitet 2 Problemers kompleksitet En ineffektiv algoritme: køretiden vokser eksponentielt med input- størrelsen Et problem, der ikke kan.
Advertisements

Velkommen til Softwarekonstruktion
SQL 1 DDL og DML.
1 Rekursion og algoritmedesign. 2 Rekursion Rekursiv definition af X: X defineres i termer af sig selv. Rekursion er nyttig, når en generel version af.
KONCEPT Klasser og objekter En klasse beskriver et World ArrayList
Rekursion og algoritmedesign
1 Parsing. 2 Mål: Et program til indlæsning og beregning af aritmetiske udtryk Eksempel: Beregn (3*5 + 4/2) - 1 Løs et lettere problem først: Læs en streng.
Grundlæggende programmering Efterår 2001
Begreber og Redskaber 8. Plan for idag Sortering fortsat Comparable Søgning –Lineær søgning –Binær søgning.
Søgning & sortering Intro søgning Lineær søgning Binær søgning
1 Bevisteknikker. 2 Bevisteknikker (relevant både ved design og verifikation) Teorem: Der findes uendeligt mange primtal Bevis: Antag at der findes et.
GP5, Martin Lillholm 1 Grundlæggende Programmering (GP) Efterår 2005 Forelæsning 5 Slides ligger på nettet. Du er velkommen til at printe dem nu. Vi begynder.
1 UNION-FIND. 2 inddata: en følge af heltalspar (p, q); betydning: p er “forbundet med” q uddata: intet, hvis p og q er forbundet, ellers (p, q) Eksempel.
GP 10, 7/ Grundlæggende programmering Efterår 2001 Forelæsning 10 onsdag 7/ kl. 9:15 – 12:00.
MM4 Algoritmiske grundprincipper. MM1 Lister, stakke og køer. MM2 Hash-tabeller og Træer. MM3 Sortering.MM4 Søgning.MM5.
FEN IntroJava AAU1 Java grundelementer Variable og datatyper Sætninger og udtryk Metoder.
Operationer på relationer
1 Algoritme til at løse knude P-center problemet Algoritmen brugte set covering problemet Virker derfor kun til knude problemer Vi vil alligevel bruge.
1 Søgning I. 2 Plan Sekventiel søgning Binær søgning Binære søgetræer Balancerede binære søgetræer træer.
Introduktion til Kryptering
Intro til C# apps Kodegennemgang af simpel C# app
Interfaces – brug. Overblik Tidligere: –Interfaces Comparable gør det muligt at bruge Collections metoderne –min, max, sort, … –Algoritmemønstre Find.
GP 11, 14/ Grundlæggende programmering Efterår 2001 Forelæsning 11 onsdag 14/ kl. 9:15 – 12:00.
Lektion 7 Læsestof: Kopier fra Caranno
Fundamentale datastrukturer
GP 8, 24/ Grundlæggende programmering Efterår 2001 Forelæsning 8 onsdag 24/ kl. 9:15 – 12:00.
Forelæsning 5.1 Brug af klassen Collections og interfacet Comparable samt parametriserede typer Projektuge: Ants and Spiders / Lommeregner dIntProg,
Design, verifikation og analyse
1 Design, analyse og verifikation. 2 Design Bevisteknikker Design ved hjælp at matematisk induktion Analyse O-notation Logaritmer Binær søgning Verifikation.
1 Sortering. 2 Plan Elementære metoder til sortering -sortering ved indsættelse -Shellsort Sorteringsmetoder baseret på rekursion –quicksort –flettesortering.
Ingeniørhøjskolen i Århus Slide 1 Newton approximation ”Oversæt” til algoritme - Step 5: Skriv kode - Step 4: Skriv pseudokode - Step 3: Specificér pre-
Grafalgoritmer II.
Slide Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley Chapter 15 Algorithms for Query Processing and Optimization.
1 Sortering. 2 Sortering ved fletning (merge-sort) 7 2 | 9 4  | 2  2 79 | 4   72  29  94  4.
1 Fundamentale datastrukturer. 2 Definitioner: abstrakt datatype, datastruktur Elementære datastrukturer og abstrakte datatyper : arrays, stakke, køer,
Paradigmer i Programmering 2. Sammensatte typer Tupler og lister Programmering med rekursion Programmering med pipe-lines Programmering med polymorfe.
Paradigmer i Programmering 1. Program for idag : Funktioner og udtryk i SML : Øvelse : Frokost – 14.00: Deklarative.
1 Søgning II 2 Plan Søgning ved nøgletransformation (hashing) –Hashfunktioner –Kollisionsstrategier –Effektivitet –Hashing i Java ( class HashTable )
Begreber og Redskaber 7. Plan for idag Rekursive underprogrammer Rekursive datastrukturer Rekursion vs iteration Rekursivt: Flette sortering.
8 RÅD VEDRØRENDE GOD PROGRAMMERING Effective (brown) Java.
FEN IntroJava AAU1 Klasser og objekter Grundbegreber Student-Course.
Paradigmer i Programmering 1. Plan for kurset 4 x Mads R, 4 x Torben B, 2 x opgave MR: Funktionsprogrammering, SML TB: Logikprogrammering, Prolog Opgave:
Fundamentale sprogbegreber
KF04 GRAY Item 2, 12, 22, 32, 42, 52. Consider a builder when faced with many constructor parameters Item 2.
Anvendelser I Leg og spil.
03 – Udtryk og metoder. 2 NOEA2009Java-kursus – Udtryk og metoder Udtryk i Java Java har standard udtrykene… Værditildeling Subrutiner og funktionskald.
Opfølgning på Dygtig Skildpadde (Michael) To algoritmeskabeloner findEn findAlle Primitive typer (forfremmelse og begrænsning) Identitet versus lighed.
Grundlæggende programmering Forår 2002
Begreber og Redskaber 11. Plan for idag Lidt afrunding: Collections Framework i Java Noget om oversættere og sprog Evaluering Sidste gang øvelser før.
Forelæsning 7.1 – repetition
Identitet vs lighed. Spørgsmål Hvad udskriver run metoden? 1.”Ens!” 2.”Forskellige!” 3.Ved ikke public class Driver{ public static void run(){ String.
Paradigmer i Programmering 3. Højere ordens funktioner Idag: Højere ordens funktioner Algebraiske datatyper Næste gang: I/O, Filer, interaktive programmer.
Begreber og Redskaber 4. Plan for idag Om metoder, parametre, returværdier Et par ord om objekt-orientering Håndkøring af programmer.
Begreber og Redskaber 3. Plan for idag Om metoder, parametre, returværdier Overblik over klasser,objekter,nedarvning Et par ord om objekt-orientering.
Søgning.  Michael E. Caspersen, 2000Introducerende objektorienteret programmeringSøgning.2 Søgeproblemer... Søgning efter fil(er) Søgning i databaser.
I o p o DAIMI, AU, November 1999Programkonstruktion I9E.1 Konstruktion og brug af klasser – en stak og en HP-regnemaskine push pop.
 Michael E. Caspersen, 2000Introducerende objektorienteret programmering9B.1 Fletning.
MATLAB Repetition og Udførelse af programmer Anders P. Ravn Institut for Datalogi Aalborg Universitet Forår 2005 >>mit_modul minf.m … minf(a) … mit_modul.m.
 Michael E. Caspersen, 2000Introducerende objektorienteret programmering7B.1 Søgning.
 Michael E. Caspersen, 2000Introducerende objektorienteret programmering6A.1 Programmering med interfaces – en stak og en HP-regnemaskine push pop.
Programmering med interfaces Separering af specifikation, anvendelse og implementation.
Klasser og objekter – grundbegreber.  Michael E. Caspersen, 2001Introducerende objektorienteret programmeringKlasser og objekter.2 Klasser og objekter.
Programmering med interfaces – en stak og en HP-regnemaskine push pop.
 Jens Bennedsen 2001Multimedie programmering4.1 Definition af begreber Interface, implements, klasse.
DAIMIIntroducerende objektorienteret programmeringfletning.1 Fletning.
Programmering med interfaces – en stak og en HP-regnemaskine push pop.
I o p o DAIMI, AU, Oktober 1999Introducerende objektorienteret programmering7B.1 Søgning.
Algoritmeskabeloner findOne, findAll, findNoOf, findSumOf Primitive typer (forfremmelse og begrænsning) Identitet versus lighed (for objekter, herunder.
Forelæsning Uge 2 – Torsdag
Forelæsning Uge 4 – Mandag
Præsentationens transcript:

Anvendelser I Leg og spil

Plan Leg og spil Ordkvadrater Tomandsspil (Kryds-og-bolle) Stakke og oversættere Check af parentesstrukturer En simpel kalkulator Indlæsning og beregning af aritmetiske udtryk

Ordkvadrater Problem: Givet et kvadrat bestående af bogstaver samt en ordbog. Find alle de ord i kvadratet, der optræder i ordbogen. Ordene læses vandret, lodret eller diagonalt i enhver retning (i alt 8 retninger). Eksempler: tank, ank, an, en, real, te, anke, nota, ral, ro, et, at, ark, ko, kok

Løsningsalgoritmer Ineffektiv algoritme: for ethvert ord W i ordbogen for enhver række R for enhver søjle C for enhver retning D afgør om W findes i række R, søjle C og retning D Antag R = C = 32 og W = 40,000 Antal ordsammenligninger i indre løkke: 40,000*R*C*8 = 327,680,000

Forbedret algoritme: for enhver række R for enhver søjle C for enhver retning D for enhver ordlængde L afgør om de L tegn i række R, søjle C og retning D findes som et ord i ordbogen Antal check i indre løkke (antag L = 20): R*C*8*L = 32*32*8*20 = 163,840 Hvis hvert opslag i ordbogen foretages med binær søgning maksimalt 163,840 * (Îlog240,000˚ + 1) = 163,840 * 16 = 2,621,440 ordsammenligninger. For eksemplet her er algoritmen blevet cirka 125 gange hurtigere.

Yderligere forbedret algoritme: for enhver række R for enhver søjle C for enhver retning D for enhver ordlængde L afgør om de L tegn i række R, søjle C og retning D findes som et ord i ordbogen hvis de ikke udgør et præfiks for noget ord i ordbogen, så break; // ud af den inderste løkke Om de L tegn udgør et præfiks for et ord i ordbogen kan afgøres ved binær søgning.

Implementering i Java int solvePuzzle() { int matches = 0; for (int r = 0; r < rows; r++) for (int c = 0; c < columns; c++) for (int rd = -1; rd <= 1; rd++ ) for (int cd = -1; cd <= 1; cd++) if (rd != 0 || cd != 0 ) matches += solveDirection(r, c, rd, cd); return matches; }

int solveDirection(int r, int c, int rd, int cd) { int numMatches = 0; String chars = "" + theBoard[r][c]; for (int i = r + rd, j = c + cd; i >= 0 && j >= 0 && i < rows && j < columns; i += rd, j += cd) { chars += theBoard[i][j]; int index = prefixSearch(theWords, chars, numEntries); if (!theWords[index].startsWith(chars)) break; if (theWords[index].equals(chars)) { numMatches++; System.out.println("Found " + chars + " at " + r + " " + c + " to " + i + " " + j ); } return numMatches;

int prefixSearch(String[] a, String chars, int n) { int low = 0; int high = n - 1; while (low < high) { int mid = (low + high)/2; if (a[mid].compareTo(chars) < 0) low = mid + 1; else high = mid; } return low;

Spil

Kryds-og-bolle (Engelsk: Tic-tac-toe) ... Bolle vinder Uafgjort Kryds vinder

Mini-max strategien 1. Hvis stillingen er en slutstilling, så returner dens værdi. 2. Ellers, hvis det er computeren til at trække, så returner den maksimale værdi af alle de stillinger, der fremkommer ved at udføre et træk. Værdierne beregnes rekursivt. 3. Ellers, hvis det er mennesket til at trække, så returner den minimale værdi af alle de

Mini-max strategien udfører megen overflødig søgning C1 C2 C3 H2A H2B H2D H2C uafgjort maksimer Beskæring: C2 kan aldrig blive bedre end “uafgjort”. minimer

Alpha-beta-beskæring Trækket H2A kaldes en gendrivelse af trækket C2. Trækket er godt nok, men ikke nødvendigvis det bedste. alpha: Den hidtil bedste værdi opnået af computeren. beta: Den hidtil bedste værdi opnået af mennesket. Beskæring sker (1) hvis mennesket opnår en værdi, der er mindre end eller lig med alpha. (2) hvis computeren opnår en værdi, der er større end eller lig med beta.

public Best chooseMove(int side, int alpha, int beta) { int bestRow = 0, bestColumn = 0; int value, opp; if ((value = positionValue()) != UNCLEAR) return new Best(value); if (side == COMPUTER) { opp = HUMAN; value = alpha; } else { opp = COMPUTER; value = beta; } Outer: for (int row = 0; row < 3; row++) for (int column = 0; column < 3; column++) if (squareIsEmpty(row, column)) { place(row, column, side); Best reply = chooseMove(opp, alpha, beta); place(row, column, EMPTY); if (side == COMPUTER && reply.val > value || side == HUMAN && reply.val < value) { value = reply.val; if (side == COMPUTER) alpha = value; else beta = value; bestRow = row; bestColumn = column; if (alpha >= beta) break Outer; } return new Best(value, bestRow, bestColumn);

Driver-rutine Best chooseMove(int side) { return chooseMove(side, HUMAN_WIN, COMPUTER_WIN); }

Effekten af alpha-beta-beskæring Beskæringen er størst, når algoritmen i enhver stilling altid undersøger det bedste træk først. I praksis er antallet af knuder, der bliver undersøgt ved brug af alpha-beta-beskæring O( ), hvor N er det antal knuder, der ville blive undersøgt uden brug af alpha-beta-beskæring. På den samme tid kan der søges dobbelt så dybt.

Beskæring ved hjælp af tabel Undgå genberegninger ved at gemme evaluerede stillinger i en tabel. To søgninger resulterer i samme stilling. Benyt en hashtabel.

class Position implements Hashable { int[][] board; int value; Position(int theBoard[][]) { board = new int[3][3]; for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) board[i][j] = theBoard[i][j]; } public boolean equals(Object rhs) { if (board[i][j] != ((Position) rhs).board[i][j]) return false; return true; public int hash(int tableSize) { int hashVal = 0; hashVal = hashVal*4 + board[i][j]; return hashVal % tableSize;

public Best chooseMove(int side, int alpha, int beta, int depth) { int bestRow = 0, bestColumn = 0; int value, opp; Position thisPosition = new Position(board); int tableDepth = 5; if ((value = positionValue()) != UNCLEAR) return new Best(value); if (depth == 0) transpositions.makeEmpty(); else if (depth >= 3 && depth <= tableDepth) { try { Position lookupVal = (Position) transpositions.find(thisPosition); return new Best(lookupVal.value); } catch (ItemNotFound e) {} } ... thisPosition.value = value; if (depth >= 3 && depth <= tableDepth) transpositions.insert(thisPosition); return new Best(value, bestRow, bestColumn);

En generel pakke til tomandsspil med perfekt information package twoPersonGame; public abstract class Position { public boolean maxToMove; public abstract Vector successors(); public abstract int value(); public boolean unclear() { return false; } public int alpha_beta(int alpha, int beta, int maxLevel); public Position bestSuccessor() { return bestSuccessor; } private Position bestSuccessor; }

public int alpha_beta(int alpha, int beta, int maxLevel) { Vector successors; if ((maxLevel <= 0 && !unclear()) || (successors = successors()).isEmpty()) return value(); for (int i = 0; alpha < beta && i < successors.size(); i++) { Position successor = (Position) successors.elementAt(i); int value = successor.alpha_beta(alpha, beta, maxLevel-1); if (maxToMove && value > alpha) { alpha = value; bestSuccessor = successor; } else if (!maxToMove && value < beta) { beta = value; return maxToMove ? alpha : beta;

Minimering af kode (nega-max) public int alpha_beta(int alpha, int beta, int maxLevel) { Vector successors; if ((maxLevel <= 0 && !unclear()) || (successors = successors()).isEmpty()) return (maxToMove ? 1 : -1) * value(); for (int i = 0; alpha < beta && i < successors.size(); i++) { Position successor = (Position) successors.elementAt(i); int value = -successor.alpha_beta(-beta, -alpha, maxLevel-1); if (value > alpha) { alpha = value; bestSuccessor = successor; } return alpha;

import twoPersonGame.*; public class TicTacToePosition extends Position { public TicTacToePosition(int row, int column, TicTacToePosition predecessor) { ... } public Vector successors() { Vector successors = new Vector(); if (!isTerminal()) for (int row = 0; row < 3; row++) for (int column = 0; column < 3; column++) if (board[row][column] == '.') successors.addElement( new TicTacToePosition(row, column, this)); return successors; } public int value() { return isAWin('O') ? 1 : isAWin('X') ? -1 : 0; } public boolean unclear() { return value() == 0; } public boolean boardIsFull() { ... } public boolean isAWin(char symbol) { ... } public boolean isTerminal() { ... } public void print() { ... } int row, column; char[][] board = new char[3][3];

Stakke og oversættere

Check af parentesstrukturer Problem: Givet en streng indeholdende parenteser. Afgør om parenteserne ”balancerer”, d.v.s. om der til hver venstreparentes svarer en højreparentes, og der til hver højreparentes svarer en venstreparentes. For eksempel balancerer parenteserne i “[()]”, men ikke i “[(])”. I det følgende forsimples problemet ved at antage, at strengen udelukkende indeholder parenteser.

Kun én type parenteser Hvis der kun er én type parenteser, f.eks. ’(’ og ’)’, er løsningen simpel. Vi kan kontrollere balancen med en tæller. boolean balanced(String s) { int balance = 0; for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c == '(') balanced++; else if (c == ')') { balance--; if (balance < 0) return false; } return balance == 0;

Flere typer af parenteser Hvis der derimod er flere typer af parenteser, kan problemet ikke løses ved tællere. Men vi kan let kontrollere balancen med en stak. Algoritme: 1. Lav en tom stak. 2. Sålænge strengen ikke er læst, så læs det næste tegn. a. Hvis tegnet er en startparentes, så læg det på stakken. b. Hvis tegnet er en slutparentes, og stakken er tom, så giv en fejlmeddelelse. c. Ellers, afstak det øverste tegn. Hvis dette ikke er en startparentes svarende til den læste slutparentes, så giv en fejlmeddelelse. 3. Hvis stakken ikke er tom, så giv en fejlmeddelelse.

Eksempel Streng s = "([]}" ( [ ( ( ] } Fejl! parenteser: (, ), [, ], { og } Streng s = "([]}" ( [ ( ( ] } Fejl!

Javakode boolean balanced(String s) { Stack stack = new charStack(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c == '(' || c == '[' || c == '{') stack.push(c); else if (stack.isEmpty() || (c == ')' && stack.pop() != '(')) || (c == ']' && stack.pop() != '[')) || (c == '}' && stack.pop() != '{')) return false; } return stack.isEmpty();

Indlæsning og beregning af aritmetiske udtryk Beregn udtrykket 1 * 2 + 3 * 4 Værdi = (1 * 2) + (3 * 4) = 2 + 12 = 14. Simpel beregning fra venstre mod højre kan ikke benyttes. Vi må tage højde for, at multiplikation har hørere præcedens end addition (* binder stærkere end +). Det er nødvendigt at gemme mellemresultater.

Associativitet Hvis to operatorer har samme præcedens, afgør deres associativitet beregningsrækkefølgen. Udtrykket 4 - 3 - 2 beregnes som (4 - 3) - 2, fordi minus associerer fra venstre mod højre. Udtrykket 4 ^ 3 ^ 2, hvor ^ betegner potensopløftning, beregnes som 4 ^ (3 ^ 2), fordi ^ associerer fra højre mod venstre.

Parenteser Beregningsrækkefølgen kan klarlægges ved hjælp af parenteser. Eksempel: 1 - 2 - 4 * 5 ^ 3 * 6 / 7 ^ 2 ^ 2 beregnes som ( 1 - 2 ) - ( ( ( 4 * ( 5 ^ 3 ) ) * 6 ) / ( 7 ^ ( 2 ^ 2 ) ) ) Parenteserne hjælper, men det er uklart, hvorledes beregningerne kan automatiseres.

Postfix-notation Den normale notation for aritmetiske udtryk kaldes for infix-notation (operatorerne står imellem sine operander, f.eks. 3 + 4). Beregningerne kan forenkles ved omskrivning til postfix-notation (operatorerne står efter sine operander, f.eks. 3 4 +). 1 - 2 - 4 ^ 5 * 3 * 6 / 7 ^ 2 ^ 2 (infix) omskrives til 1 2 - 4 5 ^ 3 * 6 * 7 2 2 ^ ^ / - (postfix) Postfix-notation er parentesfri.

Beregning af postfix-udtryk ved hjælp af en stak 1 2 1 - -1 4 -1 5 4 -1 ^ -1 1024 3 -1 1024 * -1 3072 6 -1 3072 * -1 18432 18432 7 -1 2 -1 7 18432 2 -1 7 18432 ^ -1 7 18432 4 ^ -1 2401 18432 / -1 7 -8 -

class Calculator { static int valueOf(String str) { intStack s = new intStack(); for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); if (Character.isDigit(c)) s.push(Character.getNumericValue(c)); // only one digit else if (!Character.isWhitespace(c)) { int rhs = s.pop(), lhs = s.pop(); switch(c) { case '+': s.push(lhs + rhs); break; case '-': s.push(lhs - rhs); break; case '*': s.push(lhs * rhs); break; case '/': s.push(lhs / rhs); break; case '^': s.push((int) Math.pow(lhs, rhs)); break; } return s.pop(); class intStack { void push(int v) { s[++top] = v; } int pop() { return s[top--]; } int s[] = new int[100], top = -1; }

Omformning fra infix til postfix ved hjælp af en stak (Dijkstras vigesporsalgoritme) Infix-streng Postfix-streng operander operatorer Operatorstak

Omformning fra infix til postfix 1 - 1 2 - 12 - 12- 4 - 12-4 ^ - 12-4 5 - ^ 12-45 * - 12-45^ 3 - * 12-45^3 * - 12-45^3* 6 - * 12-45^3*6 / - 12-45^3*6* 7 - / 12-45^3*6*7 ^ - / 12-45^3*6*7 2 - / ^ 12-45^3*6*72 2 12-45^3*6*722^^/- ^ - /

Syntaksanalyse Mål: Et program til indlæsning og beregning af aritmetiske udtryk (AE) . Løs et lettere problem først: Læs en streng og undersøg, om den er et lovligt AE.

Grammatik for aritmetiske udtryk Benyt en grammatik til at beskrive AE: <expression> ::= <term> | <term> + <expression> | <term> - <expression> <term> ::= <factor> | <factor> * <term> | <factor> / <term> <factor> ::= <number> | (<expression>) Grammatikken er beskrevet ved produktionsregler og består af (1) nonterminale symboler: expression, term, factor og number. (2) terminale symboler: +, -, *, /, ( og ). (3) metasymboler: ::=, <, >, og | .

Syntaksanalyse expression En streng er et aritmetisk udtryk, hvis det ved hjælp af produktionsreglerne er muligt at udlede strengen ud fra expression, dvs. ud fra expression i en række skridt nå frem til strengen ved i hvert skridt at erstatte et nonterminal-symbol med et af alternativerne på højresiden af en produktion for dette symbol. Syntakstræ for (3*5+4/2)-1 expression term - expression factor term ( expression ) factor term + expression number factor * factor term 1 number number factor / factor 3 5 number number 4 2

Syntaksdiagrammer expression: term: factor: term factor + * - / number ( )

Syntaksanalyse ved rekursiv nedstigning (top-down parsing) Et rekursivt Java-program til syntaksanalyse kan konstrueres direkte ud fra syntakstræerne. void expression() { term(); while (token == PLUS || token == MINUS) if (token == PLUS) { getToken(); term(); } else } static final int PLUS = 1, MINUS = 2, MULT = 3, DIV = 4, LPAR = 5, RPAR = 6, NUMBER = 7, EOS = 8; int token;

void term() { factor(); while (token == MULT || token == DIV) if (token == MULT) { getToken(); factor(); } else } void factor() { if (token == NUMBER) ; else if (token == LPAR) { getToken(); expression(); if (token != RPAR) error("missing right paranthesis"); } else error("illegal factor: " + token);

Eksempel på kald: StringTokenizer str; void parse(String s) { str = new StringTokenizer(s,"+-*/() ",true); getToken(); expression(); } Eksempel på kald: parse("(3*5+4/2)-1");

void getToken() { String s; try { s = str.nextToken(); } catch(NoSuchElementException e) { token = EOS; return; if (s.equals(" ")) getToken(); else if (s.equals("+")) token = PLUS; else if (s.equals("-")) token = MINUS; else if (s.equals("*")) token = MULT; else if (s.equals("/")) token = DIV; else if (s.equals("(")) token = LPAR; else if (s.equals(")")) token = RPAR; else { Float.valueOf(s); token = NUMBER; catch(NumberFormatException e) { error(”number expected"); }

Beregning af aritmetiske udtryk Beregning kan opnås ved få simple ændringer af syntaksanalyse-programmet. Analysemetoderne skal returnere med deres tilhørende værdi (i stedet for void). float valueOf(String s) { str = new StringTokenizer(s,"+-*/() ",true); getToken(); return expression(); } Eksempel på kald: float r = valueOf("(3*5+4/2)-1");

float expression() { float v = term(); while (token == PLUS || token == MINUS) if (token == PLUS) { getToken(); v += term(); } else { getToken(); v -= term(); } return v; } float term() { float v = factor(); while (token == MULT || token == DIV) if (token == MULT) { getToken(); v *= factor(); } else { getToken(); v /= factor(); } return v; }

float factor() { float v; if (token == NUMBER) v = value; else if (token == LPAR) { getToken(); v = expression(); if (token != RPAR) error("missing right paranthesis"); } else error("illegal factor: " + token); return v;

void getToken() { String s; try { s = str.nextToken(); } catch(NoSuchElementException e) { token = EOS; return; if (s.equals(" ")) getToken(); else if (s.equals("+")) token = PLUS; else if (s.equals("-")) token = MINUS; else if (s.equals("*")) token = MULT; else if (s.equals("/")) token = DIV; else if (s.equals("(")) token = LPAR; else if (s.equals(")")) token = RPAR; else { try{ value = Float.valueOf(s).getFloat(); token = NUMBER; catch(NumberFormatException e) { error(”number expected"); }

Ugeseddel 5 9. oktober - 16. oktober • Læs kapitel 12 og 13 i lærebogen (side 331-365) • Løs følgende opgaver 5-1. Opgave 10.2 5-2. Opgave 11.2 5-3. Opgave 11.3 5-4. Løs opgaven på næste side.

Møntproblemet En 20-krone, en 10-krone, en 1-krone og en 25-øre er lagt på et bræt med 5 felter, som vist nedenfor. Opgaven går ud på at placere mønterne i omvendt rækkefølge i de 4 felter længst til højre på brættet, ved anvendelse af færrest muligt antal træk. I hvert træk flyttes en mønt et felt til højre eller venstre. Mønterne kan stables, men i et træk må kun den øverste mønt i en stabel flyttes, og en mønt må aldrig placeres ovenpå en mønt, der er mindre. Løs denne opgave ved hjælp af et Java-program 20 10 1 25 1 10 20 25