Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido...

29
Laboratorio di Algoritmi e Strutture Dati Guido Fiorino [email protected] aa 2013-2014

Transcript of Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido...

Page 1: Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido Fiorino guido.fiorino@unimib.it aa 2013-2014

Laboratorio di Algoritmi e Strutture Dati

Guido [email protected]

aa 2013-2014

Page 2: Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido Fiorino guido.fiorino@unimib.it aa 2013-2014

Fibonacci

fib : N→ N

fib(x) =

0 if x = 01 if x = 1 or x = 2fib(x − 1) + f (x − 2) if x ≥ 3

Note that:

fib is defined only on natural numbers;

there are three base cases (namely, x = 0, x = 1 and x = 2);

according to the definition, to compute fib(x), for a given x ≥ 3, we haveto compute the values of fib for smaller values of x .

Exercise (method fib)

Write a method int fib(int n) that uses the recursive definition of thefunction fib to return the n-th Fibonacci number .

2

Page 3: Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido Fiorino guido.fiorino@unimib.it aa 2013-2014

The nf family functions

Let us consider the functions nf1, nf2, . . . of boolean functions in one propositionalvariable.Formally, for every i ≥ 1, we define a function nfi as follows:

nfi : {false, true} → {false, true} where:

nf1(p) = p;nf2(p) = ¬p;nf3(p) = ¬¬p;nf4(p) = ¬¬p → p;nfi (p) = nfi−1(p)→ (nfi−3(p) ∨ nfi−4(p)).

Note that:

according to the definition, to get the expression for nfi , for a given i ≥ 5, wehave to compute the expressions for the functions nfi−1, nfi−3 and nfi−4. Afterthat, we can compute the values for nfi (true) and nfi (false) without recursion.

Here the situation is similar to define a function h : R→ R such thath(x) = cos(x) + tan(x);

nf1,. . . ,nf4 are the base cases of the definition of the family functions.

3

Page 4: Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido Fiorino guido.fiorino@unimib.it aa 2013-2014

The nf family functions

Exercise (method nf)

Write a method String nf(int i) that for a given i > 0 returns the stringexpression of the i-th nf function. For example, nf (5) returns the string

((∼∼ p → p)→ (∼ p | p))

where ∼ stands for ¬ and | for ∨.

public static String nf(int i){

if (i == 1) { return "p"; }

if (i == 2) { return "~p"; }

if (i == 3) { return "~~p"; }

if (i == 4) { return "(~~p->p)"; }

return "( " + nf(i-1) + " -> ( " + nf(i-3) + " | " + nf(i-4) + " ) )";

}

4

Page 5: Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido Fiorino guido.fiorino@unimib.it aa 2013-2014

The nf family functions

Exercise (method nfEval)

Write a method boolean nfEval(int i, boolean p) that for a given i > 0and a boolean value p returns the value of nfi (p). For example,nfEval(5, true) returns true because the expression

((∼∼ true)→ true)→ ((∼ true)|true)

evaluates to true

5

Page 6: Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido Fiorino guido.fiorino@unimib.it aa 2013-2014

Greater Common Divisor (gcd)

The Greatest Common Divisor between two non-negative integers A and B,denoted with gcd(A,B) is the largest integer D that divides both A and B.We get a recursive definition of gcd by using the fact that if A >= B, thengcd(A,B) = gcd(A− B,B). As a matter of fact, a recursive definition of gcd is:

gcd(A,B) =

A if B = 0gcd(A− B,B) if B > 0 and A >= Bgcd(B,A) otherwise

Exercise (method gcdSlow)

Write a method long gcdSlow(long A, long B) that returns the value ofgcd(A,B) by using the definition for gcd given above.

6

Page 7: Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido Fiorino guido.fiorino@unimib.it aa 2013-2014

Greater Common Divisor (gcd)

A better definition of gcd is

gcd(A,B) =

{A if B = 0gcd(B,A%B) otherwise

that gives rise to a faster implementation requiring less nested recursive calls.

Exercise (method gcdFast)

write a method long gcdFast(long A, long B) that returns the value ofgcd(A,B) by using the definition for gcd given above.

7

Page 8: Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido Fiorino guido.fiorino@unimib.it aa 2013-2014

Printing natural numbers a digit at a time

We want to print out a non-negative number N in decimal, one digit at a time.As an example to print the number 926, first we need to print the digit 9, thenthe digit 2 and finally the digit 6.This task can be described recursively:

Getting the digits of a decimal number

to print a number N whose digits are d1 . . . dn−1dn, first print the digitsd1 . . . dn−1, then the digit dn. The base case is when the number N has onedigit.

Given N = d1 . . . dn we can split it in the head d1 . . . dn−1 and the tail dn byusing the operators / and %.

Exercise (method printDecimal)

Write a method void printDecimal(int n) that prints out n as a decimalnumber one digit at a time.

8

Page 9: Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido Fiorino guido.fiorino@unimib.it aa 2013-2014

Conversion from base 10 to any base b

A variant of the previous problem is to print out a decimal number N in a givenbase (for sake of concreteness we limit the given base to a value between 2 and16). The task can be recursively stated as follows:

Conversion of a natural number from base 10 to any base b ≥ 2

Given the decimal number N, convert in base b the number N/b, thenconcatenate to the result the digit N%b. The base case is when N < b: theconversion coincides N.

Exercise (method convertDecimal)

Write a method void convertDecimal(int N, int b) that prints N in baseb, assume 2 ≤ b ≤ 16.

A variant is

Exercise (method convertDecimal)

Write a method String convertDecimal(int N, int b) that returns astring corresponding to N in base b, assume 2 ≤ b ≤ 16.

9

Page 10: Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido Fiorino guido.fiorino@unimib.it aa 2013-2014

Integer power of a number

To calculate ab, with a ∈ R and b ∈ N we can apply the well known definition:

ab =

1 if b = 0a ∗ · · · ∗ a︸ ︷︷ ︸

b times

otherwise

A recursive definition is:

ab =

{1 if b = 0a ∗ ab−1 otherwise

According to the previous definition, the value ab is found by b recursive callsand b − 1 multiplications. The following definition is mathematically equivalentbut gives rise to a faster algorithm:

ab =

1 if b = 0ab/2 ∗ ab/2 if b > 0 and b evenab/2 ∗ ab/2 ∗ a otherwise (b > 0 and b odd)

10

Page 11: Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido Fiorino guido.fiorino@unimib.it aa 2013-2014

Integer power of a number

Exercise (method powerSlow)

Write a method long powerSlow(long a, long b) that given b ≥ 0,calculates ab by using the first version of the recursive definition.

Exercise (method powerFast)

Write a method long powerFast(long a, long b) that given b ≥ 0,calculates ab by using the second version of the recursive definition.

11

Page 12: Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido Fiorino guido.fiorino@unimib.it aa 2013-2014

Drawing a ruler

Consider the problem of drawing the markings of a ruler l units long. For sakeof concreteness let us consider l an integer power of two.

We have to draw a mark of length h every 12 l units, one mark of length h − 1

every 14 l units, one mark of length h − 2 every 1

8 l units and so on. The processends when the length of the mark is zero or when we have to draw a mark at adistance that is less than one unit.

Notice that as the size of the interval decreases by an half, the length of themark decreases by one. Result:

length of the mark in the middle of the ruler is h;

the ruler is divided in two halves and the length of the marks in the middleof the two halves is h − 1;

each of the two halves are divided in two halves and the length of themarks in the middle of the four pieces is h − 2 and so on.

12

Page 13: Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido Fiorino guido.fiorino@unimib.it aa 2013-2014

Drawing a ruler

A ruler can be drawn by a divide-and-conquer algorithm.

Given l and h, proceed recursively as follows:

Base case: if h = 0 or l = 1, then nothing to do;

Recursion:1 recursively draw the first half of the ruler as a ruler of length 1

2l with mark a

of length h − 1 in the middle;2 draw a mark of length h at 1

2l ;

3 recursively draw the second half of the ruler as a ruler of length 12l with a

mark of length h − 1 in the middle.

13

Page 14: Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido Fiorino guido.fiorino@unimib.it aa 2013-2014

Drawing a ruler

We provide an equivalent but probably clearer description.

Given the length l of the ruler as an interval [left, right] and the length h of themark in the middle of the ruler, proceed recursively as follows:

Base case: if h = 0 or right − left ≤ 1, then nothing to do;

Recursion:1 recursively draw a ruler of length left+right

2with mark of length h − 1 in the

middle of the interval [left, left+right2

];2 draw a mark of length h at left+right

2;

3 recursively draw a ruler of length left+right2

with mark of length h − 1 in the

middle of the interval [ left+right2

, right].

14

Page 15: Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido Fiorino guido.fiorino@unimib.it aa 2013-2014

Drawing a ruler

Exercise (method rulerMarkings)

We want a Java method that prints the positions and the length of themarkings in a ruler of length l that in the middle has a mark of length h.

To this aim it is necessary to know if we are in the first half of a ruler or in thesecond half. Thus we handle the length l as difference between the startingposition start and the ending position end.

We implement the Java method

ruleMarkings(int start, int end, int h).

15

Page 16: Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido Fiorino guido.fiorino@unimib.it aa 2013-2014

Drawing a ruler - implementation of rulerMarkings

//Prints where to draw the markings in a ruler

public static void rulerMarkings(int start, int end, int height){

if ((end-start) > 1 && height > 0){

//first half

rulerMarkings(start, (start+end)/2, height-1);

System.out.println("at position: " + (start+end)/2 +

" put a mark of length: " + height);

//second half

rulerMarkings((start+end)/2, end, height-1);

}

} // end rulerMarkings

Example (Output of rulerMarkings(0,8,2))

at position: 2 put a mark of length: 1

at position: 4 put a mark of length: 2

at position: 6 put a mark of length: 1

16

Page 17: Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido Fiorino guido.fiorino@unimib.it aa 2013-2014

Drawing a ruler - implementation of rulerMarkings

Tree of the recursive calls on rulerMarkings(0, 8, 2)

rulerMarkings(0, 2, 0)

rulerMarkings(0, 4, 1)

rulerMarkings(2, 4, 0)

rulerMarkings(0, 8, 2)

rulerMarkings(4, 6, 0)

rulerMarkings(4, 8, 1)

rulerMarkings(6, 8, 0)

17

Page 18: Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido Fiorino guido.fiorino@unimib.it aa 2013-2014

Drawing a ruler

Exercise (method drawRuler)

We want a Java method that prints a ruler in vertical.

We can do this by implementing the divide-and-conquer method given above.

We provide an implementation of the Java method

void drawRuler(int length, int height).

Example (Output of drawRuler(8,2))

*** This is the border of the ruler ***

.

-

.

--

.

-

.

*** This is the border of the ruler ***

The first and the last line are printed by the caller.

18

Page 19: Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido Fiorino guido.fiorino@unimib.it aa 2013-2014

Drawing a ruler - implementation of drawRuler

//Draw a ruler in vertical

public static void drawRuler(int length, int height){

//base case: if there is space but the height is zero

//we print a dot to emphasize that height of the marker is zero

if (length > 1 && height ==0) System.out.println(".");

//recursive step.

//Note that we handle the cases with length=0 implicitly as base cases

if (length > 1 && height > 0){

//draw the upper part

drawRuler(length/2, height-1);

//draw the mark of length height

for(int i=1; i<= height; i++)

System.out.print("-");

System.out.println();

//draw the lower part

drawRuler(length/2, height-1);

}

} // end drawRuler

19

Page 20: Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido Fiorino guido.fiorino@unimib.it aa 2013-2014

Drawing a ruler - implementation of drawRuler

Tree of the recursive calls on drawRuler(8, 2)

drawRuler(2, 0)

drawRuler(4, 1)

drawRuler(2, 0)

drawRuler(8, 2)

drawRuler(2, 0)

drawRuler(4, 1)

drawRuler(2, 0)

20

Page 21: Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido Fiorino guido.fiorino@unimib.it aa 2013-2014

Drawing a real ruler

In a real ruler, if the length l is 2n units, then the length of the mark in themiddle of the rule is n.

Exercise (method drawRulerLength)

Write a Java method void drawRulerLength(int height) that draws avertical ruler only using as formal parameter the height of the mark in themiddle of the ruler.

public static void drawRulerLength(int height){

if (height > 0){

drawRulerLength(height-1);

for(int i=1; i<= height; i++)

System.out.print("-");

System.out.println("");

drawRulerLength(height-1);

}

} // end drawRuler

21

Page 22: Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido Fiorino guido.fiorino@unimib.it aa 2013-2014

Drawing a real ruler - Implementation ofdrawRulerLength

Example (Output of drawRulerLength(3))

*** This is the border of the ruler ***

-

--

-

---

-

--

-

*** This is the border of the ruler ***

The first and the last line are printed by the caller.

22

Page 23: Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido Fiorino guido.fiorino@unimib.it aa 2013-2014

Drawing a real ruler - Implementation ofdrawRulerLength

Tree of the recursive calls on drawRulerLength(3)

drawRulerLength(0)

drawRulerLength(1)

drawRulerLength(0)

drawRulerLength(2)

drawRulerLength(0)

drawRulerLength(1)

drawRulerLength(0)

drawRulerLength(3)

drawRulerLength(0)

drawRulerLength(1)

drawRulerLength(0)

drawRulerLength(2)

drawRulerLength(0)

drawRulerLength(1)

drawRulerLength(0)

23

Page 24: Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido Fiorino guido.fiorino@unimib.it aa 2013-2014

Drawing a real ruler - Drawing a real ruler

Given the length l of a real ruler, we want to draw it.We do not need to calculate the length h of the mark in the middle. We can getthis information on-the-fly.Given the length l proceed recursively as follows:

Base case: if l = 1 then return 0;

Recursion:1 recursively draw the upper middle ruler of length l

2and let h the value

returned by the recursive call;2 draw a mark of length h + 1;3 recursively draw the lower middle ruler of length l

2;

4 return h + 1

Exercise

Write a Java method that implements the divide-and-conquer algorithm givenabove.

24

Page 25: Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido Fiorino guido.fiorino@unimib.it aa 2013-2014

Drawing a real ruler - implementation of drawRulerNew

//Draws a ruler given the length

//length is supposed to be a power of two

public static int drawRulerNew(int length){

if (length > 1){

int h = drawRulerNew(length/2);

for(int i=1; i<= h+1; i++)

System.out.print("-");

System.out.println("");

drawRulerNew(length/2);

return h+1;

}

else //base case

return 0;

} // end drawRulerNew

25

Page 26: Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido Fiorino guido.fiorino@unimib.it aa 2013-2014

Drawing a real ruler - implementation of drawRulerNew

Example (Output of drawRulerNew(8))

*** This is the border of the ruler ***

-

--

-

---

-

--

-

*** This is the border of the ruler ***

26

Page 27: Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido Fiorino guido.fiorino@unimib.it aa 2013-2014

Drawing a real ruler - implementation of drawRulerNew

Tree of the recursive calls on drawRulerNew(8)

drawRulerNew(1)

drawRulerNew(2)

drawRulerNew(1)

drawRulerNew(4)

drawRulerNew(1)

drawRulerNew(2)

drawRulerNew(1)

drawRulerNew(8)

drawRulerNew(1)

drawRulerNew(2)

drawRulerNew(1)

drawRulerNew(4)

drawRulerNew(1)

drawRulerNew(2)

drawRulerNew(1)

27

Page 28: Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido Fiorino guido.fiorino@unimib.it aa 2013-2014

The tower of Hanoi

We are given a tower of n disks, initially stacked in decreasing size on one ofthree pegs. The puzzle is to move the n disks to one of the other pegs, movingonly one disk at a time and never moving a larger one onto a smaller.

Let us call A, B and C the three pegs. Let A be the peg where the n disks arestacked and B the peg where we want to transfer them.

The idea of the recursive solution is the following:

recursively move the first n − 1 disks from A, to C , the third peg;

move the n-th disk from A to B;

recursively move the n − 1 disks from C to B.

What about the base case of the recursion?

If n = 1 move the disk from A to B.

28

Page 29: Laboratorio di Algoritmi e Strutture Dati · Laboratorio di Algoritmi e Strutture Dati Guido Fiorino guido.fiorino@unimib.it aa 2013-2014

The tower of Hanoi

Exercise (method tower)

Write a Java method

void tower(String Sorg, String Dest, String Temp, int n)

that prints the list of the moves to transfer n disks from Sorg to Dest.

Example (output of tower(‘‘A’’,’’B’’,’’C’’,3))

move disk 1 from A to B

move disk 2 from A to C

move disk 1 from B to C

move disk 3 from A to B

move disk 1 from C to A

move disk 2 from C to B

move disk 1 from A to B

29