160 likes | 239 Views
Informatik I (D-ITET) Group 7, 15:00-17:00, ETZ H91 Assistant: Ercan Ucan. Slides at http://people.inf.ethz.ch/eucan/inf-1 /. Exercise 8 ( 19/11/2012 ) . Modular Programming. For larger projects you may have several functions, and thousands of lines of code.
E N D
Informatik I (D-ITET)Group 7, 15:00-17:00, ETZ H91Assistant: Ercan Ucan Slides at http://people.inf.ethz.ch/eucan/inf-1/ Exercise8 (19/11/2012)
Modular Programming • For larger projects you may have several functions, and thousands of lines of code. • Putting everything in one big source file has several drawbacks (confusing code, large compilation time, problems withmaintaining the code etc). • In addition, there are several functions that perform related tasks and can be grouped together. • These functions can be grouped together into individual files: • Header files ( *.h , e.g. header.h ) • Function prototypes • Structure declarations • Symbolic constants • For more, see the C++ primer page 394 • Source files (*.cpp , e.g. header.cpp ) • Implementations of the functions declared in the header file. • Why is it not a good idea to define a function or declare a variable in a header file?
Modular Programming • By such a division you could reuse pieces of code very efficiently. • Whenever you need the functionality defined in the header file, you have to include it in your code(note the “ ”, instead of the angle brackets <>) • #include “example.h” • This could cause problems if you include a header file several times without knowing (think for example a header file that includes another header file etc). • Use the preprocessor in order to avoid this: • #ifndef NAME_H • #define NAME_H • … • #endif • From each source file after compilation you get an “object file”. • The “Linker” collects all object files and links them in one executable program.
Modular Programming • Assume we have the following files: • main.cpp, laybrinth.h, labyrinth.cpp • g++ -Wall -o Labyrinth *.cpp • - Compiles and links and generates the executable Labyrinth. • g++ -Wall -c *.cpp • - Only compiles and generates the object files main.o and labyrith.o • g++ -Wall -o Labyrinth *.o • - Links main.o and labyrinth.o and generates the executable Labyrinth.
Recursion • Recursion in computer science is a method where the solution to a problem depends on solutions to smaller instances of the same problem. • “The power of recursion evidently lies in the possibility of defining an infinite set of objects by a finite statement. In the same manner, an infinite number of computations can be described by a finite recursive program, even if this program contains no explicit repetitions.” Niklaus Wirth • We will(informally) say that a function is recursive if it calls itself. • To be explained later: every recursive function can be transformed into an iterative function by using a stack.
Recursion The Sierpinski Triangle
Recursion • The concept: • A function is defined recursively if some initial value (e.g. f(0)) is returned and the value of f(n) is expressed in terms of f(n-1). • An example (factorial) : • f(0) = 1 • f(n) = n * f(n-1) • In code: • int factorial(int n) • { • int value; • if (n == 0) • value = 1; • else • value = n*factorial(n-1); • return value; • } The function calls itself !! This is the key to recursion
int factorial(int n) { int value; if (n == 0) value = 1; else value = n*factorial(n-1); return value; } Recursion • An example (factorial) : • Suppose you call • int res = factorial(4); • What will happen?
Recursion res = 24 int res = factorial(4); = 4 * 6 = 24 value = 4*factorial(3); factorial(3); value = 3*factorial(2); = 3 * 2 = 6 factorial(2); value = 2*factorial(1); = 2 * 1 = 2 factorial(1); int factorial(int n) { int value; if (n == 0) value = 1; else value = n*factorial(n-1); return value; } value = 1*factorial(0); = 1 * 1 = 1 factorial(0); value = 1; return value;
Recursion (another example – The Fibonacci number) In mathematical terms, the sequence Fn of Fibonacci numbers is defined by : The first ones: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144 … intfibonacci (int n) { if (n==0) return 0; if (n==1) return 1; return( fibonacci(n-2) + fibonacci(n-1) ); }
The key to thinking recursively is to see the solution to the problem as a “smaller” version of the same problem. Recursion Every recursion should have the following characteristics: One (or more) base case for which we explicitly provide a return value (solution to the minimum problem instance). If not, endless recursion and stack overflow. A way to go towards the base case, i.e. to generate smaller problem instances. A recursive call which will pass the simpler problem solution back to the calling function. int factorial(int n) { int value; if (n == 0) value = 1; else value = n*factorial(n-1); return value; }
Exercise 1 - Recursive Functions double foo(double a, unsigned int b) { if (b == 0) return 1.0; double c = foo(a,b/2); c = c*c; if (b % 2 != 0) c = a*c; return c; } RECURSION !!! Multiplications 1a) What is the return value foo( 3.0 , 6 ) ? 1b) Which mathematical function functionfoo() implements ? 1c) How many floating-point multiplications are performed if you call foo( 1.2345 , 61 ) ? 1d) Modify the above function in order to correctly treat negative values for b.
Exercise 1 – The Labyrinth • A labyrinth is a 2-dim Array with characters (representing a real labyrinth or maze). A labyrinth looks something like this: • You are given a lot of utility functions, which are • defined in labyrinth.cpp and labyrinth.h (you have • to #include “labyrinth.h” to be able to • use them): • loadLabyrinth(“./labyrinth.map”); • zeichenAnPosition(int x, int y); • setzeZeichenAnPosition • (char zeichen, int x, int y); • resetLabyrinth(); • printLabyrinth();
Exercise 1 – The Labyrinth • Load and print the labyrinth on the screen • Ask from the user to specify a starting point (x1,y1) and also an end point (x2, y2). Check if the input is valid, i.e. if the points are out of the labyrinth points or if they hit an obstacle. • Calculate a valid path between the starting and the end point (x1,y1) -> (x2,y2) and print it on screen. • Ask the user if he/she wants to try again with another path. Geben Sie die X-Koordinate fuer den Start ein: 37 • Geben Sie die X-Koordinate fuer den Start ein: 37 • Geben Sie die Y-Koordinate fuer den Start ein: 18 • Geben Sie die X-Koordinate fuer das Ziel ein: 2 • Geben Sie die Y-Koordinate fuer das Ziel ein: 18 XXXXXXXXXXXXXXXXXXXXXX 1 X X X X X X 2 X XXXXX 3 X X XXXXXXX X X 4 X XXXXX X X 5 X XX XXXX X 6 X XXXX 7 X XXX X XX X X 8 X X XXXX XX X X 9 X XXX X XXX 10 X XX XXXXXX 11 X XX XXXXXX XXX X 12 X XXXXXX X XXX X 13 X XX 14 X XXXXX X 15 X XXXXXXXXXXXXXXXX X X 16 X Xv<<<<<<<X X XXXXXX 17 X X>>vX>>>^X X 18 X Z<<<<<<<<<<X^<<<<<<<<<<<<<<<<<<<<<<SX 19 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX Nochmal (j, n)? START END PATH
Exercise 2 – The Labyrinth • Therefore, your main task is to implement a function • bool sucheWeg(int sx, int sy, int zx, int zy) • which takes as input the coordinates of the starting and end point and returns true if it has found a valid • path between them. This function has to be recursive. • As a recursive function it has to have an abort criterion ( as for example factorial(0) ): • Return true if the starting point is the same as the end point. • Return false if around the starting point there is no free space. • Also it has to call itself in order to explore the space of the labyrinth. So if the above cases do not hold: • Start looking recursively towards the right (increasing sx) printing ‘>’ as you go on. • If this recursion returns true you have found the end point. • Otherwise you have to look recursively in the other directions with the following order (left, up and down), printing respectively ( ‘<‘ , ‘v’, ‘^’)as you follow the path. • If all the above steps fail for a starting point (sx,sy) print ‘.‘ at thepoint and return false.
Exercise 3 (Optional) – Hanoi Towers You have to write a recursive program that solves the Hanoi Towers problem: No more hints as this is an optional task…