- functions
- decomposition / abstraction
- scope

29/03/2023

- functions
- decomposition / abstraction
- scope

- more functions
- recursion

- Write a function that computes the
**least common multiple**: smallest number that is a multiple of two provided numbers.

- To solve a problem
**understand**the problem- see
**examples** - develop a
**strategy** **refine**the strategy- convert strategy to
**code**, **test**result- go back to previous steps if necessary (if something fails)

Write a function that computes the

**least common multiple**: smallest number that is a multiple of two provided numbers.**understanding**- we are given two numbers: X and Y
- we will find a number Z, such that
- Z is perfectly divided by X
- Z is perfectly divided by Y
- Z is minimal (there is no smaller Z)

Write a function that computes the

**least common multiple**: smallest number that is a multiple of two provided numbers.**examples**- For 2 and 3 -> 6
- For 4 and 5 -> 20
- For 4 and 6 -> 12
- For 3 and 9 -> 9

Write a function that computes the

**least common multiple**: smallest number that is a multiple of two provided numbers.**strategy**- let
**BIG**be the larger number and**SMALL**be the smaller - if
**BIG is divisible by SMALL**- then we are
**done**,*return BIG*

- then we are
- otherwise, let
**i = 2**- if
**BIG * i**is divisible by SMALL- then we are
**done**, return*BIG * i*

- then we are
- otherwise increment i and repeat the above check

- if

- let

**least common multiple**: smallest number that is a multiple of two provided numbers.**refine**- let
**BIG**be the larger number and**SMALL**be the smaller ~~if BIG is divisible by SMALL~~~~then we are done, return BIG~~

~~otherwise~~, let**i =**~~2~~1~~if~~while**BIG * i**is*NOT*divisible by SMALL~~then we are done, return BIG * i~~~~otherwise~~increment i~~and repeat the above check~~

- return
**BIG * i**

- let

**least common multiple**: smallest number that is a multiple of two provided numbers.**refine**- let
**BIG**be the larger number and**SMALL**be the smaller - let
**i = 1** - while
**BIG * i**is*NOT*divisible by SMALL- increment i

- return
**BIG * i**

- let

**least common multiple**: smallest number that is a multiple of two provided numbers.**code**

def LCM(X, Y): if X > Y: BIG, SMALL = X, Y else: BIG, SMALL = Y, X i = 1 while not ((BIG * i) % SMALL == 0): i = i + 1 return (BIG * i)

**least common multiple**: smallest number that is a multiple of two provided numbers.**test**

print(LCM(3, 5))

## 15

print(LCM(1, 4))

## 4

print(LCM(12, 4))

## 12

print(LCM(6, 8))

## 24

Write a program that sums up two rational numbers

**understanding**- We are given two rational numbers: \(\frac{a}{b}\) and \(\frac{c}{d}\)
- We have to compute \(\frac{a}{b}+\frac{c}{d}\)
- To do this, we need to find the LCM of b and d
- Then we multiply a with \(\frac{lcm}{b}\)
- and multiply c with \(\frac{lcm}{d}\)

- When both denominators are equal to lcm, we sum up the numerators. The result is

\[\frac{a*lcm/b}{lcm} + \frac{c*lcm/d}{lcm} = \frac{a*lcm/b+c*lcm/d}{lcm}\]

Write a program that sums up two rational numbers

**examples**- \(\frac{2}{3}+\frac{4}{5} = \frac{22}{15}\)
- \(\frac{1}{4}+\frac{1}{2} = \frac{3}{4}\)
- \(\frac{3}{7}+\frac{5}{21} = \frac{14}{21}\)

Normally, \(\frac{14}{21}\) should be simplified as \(\frac{2}{3}\), but we will

**omit**this for now.

Write a program that sums up two rational numbers

**strategy**- ask for a, b, c and d
- compute lcm = LCM(c, d)
*reusing the LCM function from previous exercise* - output \(\frac{a*lcm/b+c*lcm/d}{lcm}\)

Write a program that sums up two rational numbers

**refine**- There doesn’t seem to be any area for refinement

Write a program that sums up two rational numbers

**code**

def sumRationals(a, b, c, d): lcm = LCM(b, d) numerator = int(a * lcm / b + c * lcm / d) #use int() to avoid x.0 print(numerator, "/", lcm)

**QUESTION**: why not return? why print?

Write a program that sums up two rational numbers

**test**

# Normally this should be requested from the user using input() sumRationals(2, 3, 1, 4)

## 11 / 12

sumRationals(1, 3, 1, 3)

## 2 / 3

sumRationals(4, 15, 2, 5)

## 10 / 15

- Let \(n!\) be the factorial of n,
- \(n! = 1\times 2\times 3\times ...\times n-2 \times n-1 \times n\)
- \(n! = (n-1)! \times n\)
- \((n-1)! = (n-2)! \times (n-1)\)
- \((n-2)! = (n-3)! \times (n-2)\)
- \((n-3)! = (n-4)! \times (n-3)\)
- …
- \(1! = 1\)

- Let
`fact(n)`

be a function that computes factorial of n - How do you implement it?

- Let
`fact(n)`

be a function that computes factorial of n **strategy**`fact(1) = 1`

*this is the base case*`fact(n) = fact(n - 1) * n`

*this is the inductive step*

`fact(n) = fact(n - 1) * n`

`fact(n - 1) = fact(n - 2) * (n - 1)`

`fact(n - 2) = fact(n - 3) * (n - 2)`

`fact(n - 3) = fact(n - 4) * (n - 3)`

- …
`fact(1) = 1`

**code**

def fact(n): if n == 1: return (1) else: return (n * fact(n - 1))

**test**

print(fact(2)) # 2x1

## 2

print(fact(5)) # 5x4x3x2x1

## 120

print(fact(7)) # 7x6x5x4x3x2x1

## 5040

- Recursion is a bit more difficult to think and code
- But if cleverly done, it results in much
**shorter**and**cleaner**code

- Can we implement Fibonacci numbers with recursion?
- \(F_n = F_{n-1}+F_{n-2}\)
- Yes!

def fibo(n): if n == 1 or n == 2: return (1) else: return fibo(n - 1) + fibo(n - 2) print(fibo(5))

## 5

print(fibo(7))

## 13

- What is really going on???
- Let’s change the code a bit to
**debug**it

- Let’s change the code a bit to

def fibo(n, depth): print(depth * " " + "Computing fibo(" + str(n) + ")...") if n == 1 or n == 2: return (1) else: return fibo(n - 1, depth + 1) + fibo(n - 2, depth + 1) print(fibo(5, 0))

## Computing fibo(5)... ## Computing fibo(4)... ## Computing fibo(3)... ## Computing fibo(2)... ## Computing fibo(1)... ## Computing fibo(2)... ## Computing fibo(3)... ## Computing fibo(2)... ## Computing fibo(1)... ## 5

- Can we reverse a string recursively?

- Can we reverse a string recursively?
- Yes!

def reverse(s): if len(s) == 1: return (s) else: return ( s[-1] + reverse( s[:-1] ) ) print(reverse("burkay genc"))

## cneg yakrub

- Find whether a given string is a palindrome
- palindrome: a string that is equal to its reverse

- Find whether a given string is a palindrome
- First solution with
*reuse*of`reverse()`

:

def isPalindrome(s): return s == reverse(s) print(isPalindrome("burkay genc"))

## False

print(isPalindrome("abcdedcba"))

## True

- Find whether a given string is a palindrome
- Second solution with
*recursion*:

def isPalindrome(s): if len(s) == 0 or len(s) == 1: return True else: return s[0] == s[-1] and isPalindrome(s[1:-1]) print(isPalindrome("burkay genc"))

## False

print(isPalindrome("abcdedcba"))

## True

- Write a recursive function that checks whether a given sequence of numbers contains any negative numbers

- Write a recursive function that checks whether a given sequence of numbers contains any negative numbers

def hasNegative(s): if len(s) == 0: return False return s[0] < 0 or hasNegative(s[1:]) print(hasNegative([1,2,3,4,5,6]))

## False

print(hasNegative([1,2,3,-4,5,6]))

## True

**DIFFICULT EXERCISE**

Write a recursive function which takes two arguments: a sequence of numnbers and a target number; and returns True if a subset of the numbers in the sequence sum up to the target number.

- Example
- Given [4,7,-2,7,5,5,-1] and a target value of 13, the return value is True, because 7 + 7 + (-1) = 13.
- However, with the same sequence and a target value of 29, the return value is False.

**DIFFICULT EXERCISE**

Write a recursive function which takes two arguments: a sequence of numnbers and a target number; and returns True if a subset of the numbers in the sequence sum up to the target number.

def subsetsum(s, t): if t == 0: # if the target is 0, we are done return True elif len(s) == 0: # and we know t != 0, because of the above condition return False else: # we either have s[0] in the solution or not: return subsetsum(s[1:], t - s[0]) or subsetsum(s[1:], t) print(subsetsum([4,7,-2,7,5,5,-1], 13))

## True

print(subsetsum([4,7,-2,7,5,5,-1], 29))

## False

Write a function that takes two strings S1 and S2, and returns the position index of S2 in S1. If S2 does not exist in S1, then the function returns -1.

Write a function

`str_replace`

that takes three strings, S1, S2 and S3; and replaces the first occurence of S2 in S1 with S3.- For example,
`str_replace("burkay genc", "kay", "ak")`

returns`"burak genc"`

- For example,
Try to solve the first problem using a recursive strategy.

Using only 10 lira and 20 lira banknotes, in how many different ways can you pay 100 liras? Develop a recursive strategy to solve this problem.

- The order of the banknotes are important. So
`10+20+20+20+20+10`

and`20+20+20+20+10+10`

are counted as two different payments.

- The order of the banknotes are important. So
Now, try to convert the strategy you have developed in 4 to Python code. You have to create a function

`pay(total, bn1, bn2)`

.`total`

is what you have to pay,`bn1`

and`bn2`

are the values of the banknotes you have to use. The function returns the number of ways this can be done.

These slides are a direct adaptation of the slides used for MIT 6.0001 course present (as of February 2020) on MIT OCW web site.

**Original work by:**

Ana Bell, Eric Grimson, and John Guttag. 6.0001 Introduction to Computer Science and Programming in Python. Fall 2016. Massachusetts Institute of Technology: MIT OpenCourseWare. License: Creative Commons BY-NC-SA.

**Adapted by and for:**

Asst. Prof. Dr. Burkay Genç. MUH101 Introduction to Programming, Spring 2020. Hacettepe University, Computer Engineering Department.