### Pearls of Functional Algorithm Design (Find the Smallest

```Pearls of Functional Algorithm
Design
Chapter 1
Roger L. Costello
June 2011
1
I am reading this book
2
Chapter 1
• The following slides amplifies the content of the
book’s Chapter 1.
• Chapter 1 shows three ways to solve the problem
of finding the smallest free number. Also, it shows
a neat sorting algorithm.
• Slides 1 – 57 describes version #1 of finding the
smallest free number.
• Slides 58 – 89 describes the sorting algorithm.
• Slides 90 – 105 describes version #2 of finding
the smallest free number.
• Slides 106 – 133 describes version #3 of finding
the smallest free number.
3
What is Functional
Algorithm Design?
• It is solving problems by composing functions.
4
Function Composition
+
map
toUpper
toUpper
map
5
Function Composition (cont.)
“hello world”
map toUpper
“HELLO WORLD”
6
Attention
• As you go through these slides, be alert to the
functions (puzzle pieces) used.
• Observe how they are composed to solve
problems (i.e., how the puzzle pieces are put
together to create something new).
• Example: The previous slide composed two
functions to solve a problem -- convert strings
to uppercase.
7
The Problem We Will Solve
8
Recurring Problem
• Cooking: a recipe calls for this list of
ingredients: eggs, flour, milk, chocolate. In my
kitchen I have some ingredients. Is there a
difference between what the recipe requires
versus what I have in my kitchen?
9
Recurring Problem (cont.)
• Product Inventory: the inventory sheet says
one thing. The actual products on the shelf
says another. Is there a difference between
what the inventory sheet says versus what is
actually on the shelves?
10
Recurring Problem (cont.)
• Air Mission: the air mission calls for aircraft
and weapons. In the military unit there are
aircraft and weapons. Is there a difference
between what the air mission requires versus
what is in the military unit?
11
Problem Statement
• Find the difference between list A and list B.
• List A is in ascending order; list B is in no
particular order.
12
Just the First Difference
• We will just find the first difference, not all the
differences.
13
Abstract Representation
of the Problem
• List A: represent it using the natural numbers,
N = (0, 1, …)
• List B: also represent it using the natural
numbers; the numbers may be in any order
14
What is the smallest number
not in this list?
[08, 23, 09, 00, 12, 11, 01, 10, 13, 07, 41, 04, 14, 21, 05, 17, 03, 19, 02, 06]
15
15
Problem Re-Statement
• Find the smallest natural number not in a given
finite list of natural numbers.
16
We Will Solve The Problem
In Two Ways
17
Solution #1
18
notElem
• “notElem” is a standard function.
• It takes two arguments, a value and a list.
• It returns True if the value is not an element of
the list, False otherwise.
notElem 23 [08, 23, 09, …, 06]
False
19
notElem (cont.)
• The notElem function can be used to help
solve the problem.
• Iterate through each natural number and see if
it is not an element of the list. Retain any
natural number not in the list.
• See next slide. (Note: “N” denotes the natural
numbers: 0, 1, 2, …)
20
for each x in N
x
no
notElem
?
[08, 23, 09, …, 06]
yes
retain x
21
filter
• “filter” is a standard function.
• It does all that stuff shown on the previous
slide:
– it selects, one by one, the values in N
– it hands the value to the notElem function, “Hey, is
this value not an element of [08, 23, 09, …, 06]?”
– if notElem returns True, it retains the value.
22
Compose filter and notElem
[08, 23, 09, 00, 12, 11, 01, 10, 13, 07, 41, 04, 14, 21, 05, 17, 03, 19, 02, 06]
filter (notElem ___) [0, 1, 2, ..]
[15, 16, 18, 20, 22, 24, 25, 26, 27, …]
23
• “head” is a standard function.
• It selects the first value in a list.
• Compose it with filter and notElem to
complete the solution:
[08, 23, 09, 00, 12, 11, 01, 10, 13, 07, 41, 04, 14, 21, 05, 17, 03, 19, 02, 06]
head (filter (notElem ___) [0, 1, 2, ..])
15
24
Solution #1
head (filter (notElem xs) [0 ..])
xs (pronounced, ex’es) is the list that we are analyzing.
[0 ..] is the natural numbers.
25
Solution #2
26
Okay to discard some values
• Recall that we are analyzing a list of values.
• We are representing the values using numbers.
• We represent one value as 0, another value as
2, and so forth.
• Suppose we have 20 values. Suppose one of
the values has the number 23. We can discard
it.
• Therefore, use the filter function to retain only
values that are less than the length of the list.
27
Example
[08, 23, 09, 00, 12, 11, 01, 10, 13, 07, 41, 04, 14, 21, 05, 17, 03, 19, 02, 06]
length = 20
28
Example (cont.)
[08, 23, 09, 00, 12, 11, 01, 10, 13, 07, 41, 04, 14, 21, 05, 17, 03, 19, 02, 06]
x
no
length [08, 23, …, 06]
<=
yes
retain x
29
Example (cont.)
[08, 23, 09, 00, 12, 11, 01, 10, 13, 07, 41, 04, 14, 21, 05, 17, 03, 19, 02, 06]
filter (<=n) xs where n = length xs
[08, 09, 00, 12, 11, 01, 10, 13, 07, 04, 14, 05, 17, 03, 19, 02, 06]
These values are discarded: 23, 21
30
zip
• “zip” is a standard function.
• It takes two lists and zips them up (just like a
zipper zips up two pieces of clothing). That is,
it pairs:
– the first value in the first list with the first value in
the second list
– the second value in the first list with the second
value in the second list
– etc.
31
zip (cont.)
Pair this value with this value
32
zip the filtered set
with a list of True values
[08, 09, 00, 12, 11, 01, 10, 13, 07, 04, 14, 05, 17, 03, 19, 02, 06]
[True, True, …]
zip
[(08, True), (09, True), (00, True), (12, True), (11, True), …, (06, True)]
33
repeat
• “repeat” is a standard function.
• It repeats its argument an infinite number of
times.
repeat True
[True, True, True, …]
34
Create a list of pairs
[08, 23, 09, 00, 12, 11, 01, 10, 13, 07, 41, 04, 14, 21, 05, 17, 03, 19, 02, 06]
zip (filter (<=n) xs) (repeat True)
where n = length xs
[(08, True), (09, True), (00, True), (12, True), (11, True), …, (06, True)]
35
Association List
• A list of pairs is called an “association list” (or
alist for short)
• The first value in a pair is the index. The
second value is the value.
• A value can be quickly obtained given its
index.
Association List:
[(08, True), (09, True), (00, True), (12, True), (11, True), …, (06, True)]
36
“OR” each value in the alist
with False
• For all indexes from 0 to the length of the list,
OR the value with False. OR is represented by
this symbol: ||
[(0,True),(1,True),(2,True),(3,True),(4,True), …,(14,True),(17,True), (19,True)]
(||) False (||) False ………………. (||) False ………. (||) False ……….
[(0,True),(1,True),(2,True),(3,True),(4,True), …,(14,True),(15,False),(16,False),…]
37
Gaps result in the creation of a pair
with a value of False
[(0,True),(1,True),(2,True),(3,True),(4,True), …,(14,True),(17,True), (19,True)]
Here’s a gap in the alist.
It produces a pair with a
value of False.
38
accumArray
• “accumArray” is a standard function.
• It does all the stuff shown on the previous two
slides:
For each index from 0 to the length of the list do
Apply a function (e.g., ||) to the value
39
Nearly finished!
[08, 23, 09, 00, 12, 11, 01, 10, 13, 07, 41, 04, 14, 21, 05, 17, 03, 19, 02, 06]
accumArray (||) False
(zip (filter (<=n) xs) (repeat True))
where n = length xs
[(0,True),(1,True),(2,True),(3,True),(4,True), …,(14,True),(15,False),(16,False),…]
40
checklist
• “checklist” is a (user-defined) function; it is
the collection of functions shown on the
previous slide (copied below).
checklist
accumArray (||) False
(zip (filter (<=n) xs) (repeat True))
where n = length xs
41
elems
• “elems” is a standard function.
• Give it an alist and it returns its values:
[(0,True),(1,True),(2,True),(3,True),(4,True), …,(14,True),(15,False),(16,False),…]
elems
[True, True, True, True, True, …,True, False, False, True, True]
42
id
• “id” is a standard function.
• It is the identity function; give it a value and it
returns the same value:
True
False
id
id
True
False
43
takeWhile
• “takeWhile” is a standard function.
• It takes two arguments, a function and a list; it
starts at the beginning of the list and retains
each value until it arrives at a value for which
the function returns False.
44
takeWhile (cont.)
[True, True, True, True, True, …,True, False, False, True, True]
takeWhile id ___
[True, True, True, True, True, …,True]
takeWhile stops when it gets to the first False.
45
length
• “length” is a standard function.
• It takes one argument, a list; it returns the
number of values in the list:
[True, True, True, True, True, …,True]
length ___
15
46
Hey, that’s the answer!
[True, True, True, True, True, …,True]
length ___
15
“15” is the
the problem
47
From alist to answer
[(0,True),(1,True),(2,True),(3,True),(4,True), …,(14,True),(15,False),(16,False),…]
length takeWhile id elems ___
15
48
search
• “search” is a (user-defined) function; it is the
collection of functions shown on the previous
slide (copied below).
search
length takeWhile id elems
49
Solution #2
search checklist xs
xs (pronounced, ex’es) is the list we are analyzing
50
Comparison of the
two solutions
51
Solution #1
• With a list of length “n” this solution takes, in
the worst case, on the order of n2 steps.
• This will give you an idea of idea how fast the
time requirements grow:
n
time
1
1
2
4
3
9
4
16
5
25
6
36
52
Solution #2
• With a list of length “n” this solution takes on
the order of n steps.
• That is, it is a linear-time solution for the
problem. That’s nice!
53
Implementation
54
• Haskell is a functional programming language.
• The following slides show how to express the
two solutions using Haskell.
55
Solution #1
findGap :: [Int] -> Int
findGap xs = head (filter (`notElem` xs) [0..])
56
Solution #2
import Data.Array
checklist :: [Int] -> Array Int Bool
checklist xs = accumArray (||) False (0,n)
(zip (filter (<=n) xs) (repeat True))
where n = length xs
search :: Array Int Bool -> Int
search = length . takeWhile id . elems
findGap = search . checklist
57
Sort
Problem: Sort a list of values
58
The Problem We Will Solve
59
Recurring Pattern
• Kitchen: In my kitchen I have a 2 quart sauce
pan, a 1 quart sauce pan, a 5 quart sauce pan,
and another 2 quart sauce pan. I want to
organize (sort) them by increasing size.
60
Recurring Pattern
• Bookshelf: On my bookshelf I have a bunch of
books. I want to organize (sort) them by
author.
61
Problem Statement
• Sort a list of items. There may be duplicates in
the list; that’s okay.
62
Abstract Representation
of the Problem
• Represent the items in the list using the natural
numbers, N = (0, 1, …)
63
Example of sorting a list
[08, 15, 09, 00, 12, 11, 01, 10, 13, 07, 16, 04, 14, 15, 05, 17, 03, 19, 02, 06]
sort
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 16, 17, 19]
64
Important Assumptions
• Assumption: Each item in the list has a value
that is less than the length of the list
– On the previous slide the list contains 20 elements.
Thus, each item’s value is 0≤x<20
• Assumption: Duplicates are okay.
– On the previous slide there are two occurrences
of 15
65
Time Required
• Given the assumptions on the previous slide,
the algorithm shown on the following slides
performs a sort in a time proportional to the
length of the list.
• That is, the time to sort is linear, i.e., O(n)
• That’s fast!
66
Create a list of 1’s
using the repeat function
repeat 1
[1, 1, 1, …]
67
Create a list of pairs
using the zip function
[08, 15, 09, 00, 12, 11, 01, 10, 13, 07, 16, 04, …, 19, 02, 06]
[1, 1, …]
zip
[(08, 1) , (15, 1), (09, 1), (00, 1), (12, 1), (11, 1), (01, 1), (10, 1)…, (06, 1)]
68
Compose the
zip and repeat functions
[08, 15, 09, 00, 12, 11, 01, 10, 13, 07, 16, 04, 14, 15, 05, 17, 03, 19, 02, 06]
zip ___ (repeat 1)
[(08, 1) , (15, 1), (09, 1), (00, 1), (12, 1), (11, 1), (01, 1), (10, 1)…, (06, 1)]
69
Interpret each pair as
(index, count)
[(08, 1) , (15, 1), (09, 1), (00, 1), (12, 1), (11, 1), (01, 1), (10, 1)…, (06, 1)]
one occurrence
index
70
Merge pairs with the same index
(add their count values)
[(08, 1) , (15, 1), (09, 1), (00, 1), (12, 1), (11, 1), … (15, 1)…, (06, 1)]
(15, 2)
“There are two occurrences of 15”
71
The accumArray Function
• The accumArray function goes through a list
of pairs and merges the pairs that have a
duplicate index.
• accumArray is flexible in how it merges – you
supply it a function and it will use that
function to merge the pairs’ values.
• In our problem we supply it the plus (+)
function because we want the values added.
72
The accumArray Function (cont.)
• The accumArray function has four arguments.
I describe them in reverse order:
– A list of pairs, such as that shown two slides back
– A pair, (0, n), where n is the length of the list
– An initial value for the function (see next)
– A function to be applied on the values of pairs with
duplicate indexes
73
The result is an “array”
[(08, 1) , (15, 1), (09, 1), (00, 1), (12, 1), (11, 1), … (15, 1)…, (06, 1)]
accumArray (+) 0 (0, n) (___)
where n = length xs
array (0,20) [(0,1),(1,1),(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),…,(19,1),(20,0)]
74
Compose
accumArray, zip, and repeat
[08, 15, 09, 00, 12, 11, 01, 10, 13, 07, 16, 04, 14, 15, 05, 17, 03, 19, 02, 06]
accumArray (+) 0 (0, n) (zip xs (repeat 1))
where n = length xs
array (0,20) [(0,1),(1,1),(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),…,(15,2),…,(19,1),(20,0)]
75
countlist
• “countlist” is a (user-defined) function; it is the
collection of functions shown on the previous
slide (copied below).
countlist
accumArray (+) 0 (0, n) (zip xs (repeat 1))
where n = length xs
76
The assocs Function
• The function takes as its argument an array and
returns just the list of pairs.
array (0,20) [(0,1),(1,1),(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),…,(15,2),…,(19,1),(20,0)]
assocs ____
[(0,1),(1,1),(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),…,(15,2),…,(19,1),(20,0)]
77
Replicate n times
the index in (index, n)
[(0,1),(1,1),(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),…,(15,2),…,(19,1),(20,0)]
replicate once
(0)
replicate once
………………………..
(1)
replicate twice
(15)
(15)
78
The replicate function
• The replicate function creates n copies of a
value. It returns a list, containing n items.
replicate 3 "Ho" returns ["Ho","Ho","Ho"]
replicate 2 15 returns [15,15]
79
Recall “set comprehensions”
from your school days
{ 2  x | x  N , x  10 }
“The set of the first ten even numbers”
A set comprehension builds a more specific set out of a
general set. In this example, the more general set is N, the set
of natural numbers.
80
Terminology
variable
input
set
{ 2  x | x  N , x  10 }
output
function
predicate
81
List Comprehensions
• List comprehensions are similar to set
comprehensions.
• The set comprehension on the previous slide is
equivalently expressed in Haskell using this
list comprehension:
[2*x|x <- [1..10]]
[2,4,6,8,10,12,14,16,18,20]
82
Explanation
[2*x|x <- [1..10]]
“x is drawn from [1 .. 10] and for every value drawn, that value
is doubled.”
83
Create a list of the indexes
[(0,1),(1,1),(2,1),(3,1),(4,1),(5,1),…(13,1),(14,1),(15,2),(16,1),(17,1),(18,0),(19,1),(20,0)]
[x | (x,y) <- ____ ]
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
Oops! There should be two of
these. Need to replicate.
84
Replicate the indexes the
proper number of times
[(0,1),(1,1),(2,1),(3,1),(4,1),(5,1),…(13,1),(14,1),(15,2),(16,1),(17,1),(18,0),(19,1),(20,0)]
[replicate y x | (x,y) <- ____ ]
[[0],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15,15],[16],[17],[],[19],[]]
Now we need to merge (concat) the list of lists.
85
The concat function
• The concat function creates a single list out of
a list of lists
[[0],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15,15],[16],[17],[],[19],[]]
concat ____
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,15,16,17,19]
86
array -> sorted list
array (0,20) [(0,1),(1,1),(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),…,(15,2),…,(19,1),(20,0)]
concat [replicate k x | (x, k) <- assocs (countlist xs)]
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,15,16,17,19]
87
sort
• “sort” is a (user-defined) function; it is the
collection of functions shown on the previous
slide (copied below).
sort
concat [replicate k x | (x, k) <- assocs (countlist xs)]
88
Here’s the Solution
import Data.Array
countlist :: [Int] -> Array Int Int
countlist xs = accumArray (+) 0 (0, n) (zip xs (repeat 1))
where n = length xs
sort :: [Int] -> [Int]
sort xs = concat [replicate k x | (x, k) <- assocs \$ countlist xs]
89
Find the smallest free number
Version #2
90
The Problem We Will Solve
91
Problem Statement
• Find the smallest natural number not in a given
finite list of natural numbers.
92
What is the smallest number
not in this list?
[8, 9, 0, 12, 11, 1, 10, 13, 7, 4, 14, 14, 14, 5, 17, 3, 19, 2, 6]
15
93
Important Assumptions
• Assumption: Each item in the list has a value
that is less than the length of the list
– On the previous slide the list contains 19 elements.
Thus, each item’s value is 0≤x<19
• Assumption: Duplicates are okay.
– On the previous slide there are three occurrences
of 14
94
Recall the countlist function
[8, 9, 0, 12, 11, 1, 10, 13, 7, 4, 14, 14, 14, 5, 17, 3, 19, 2, 6]
countlist ___
array (0,19) [(0,1),(1,1),(2,1),(3,1),(4,1), … , (14,3),(15,0),(16,0),(17,1),(18,0),(19,1)]
See slides 67-76 for an explanation of the countlist function.
95
The countlist function
countlist
accumArray (+) 0 (0, n) (zip xs (repeat 1))
where n = length xs
xs is the list of Natural numbers.
96
Recall the checklist function
• The first version (see slides 27-41) to the
problem used the checklist function:
[8, 9, 0, 12, 11, 1, 10, 13, 7, 4, 14, 14, 14, 5, 17, 3, 19, 2, 6]
checklist xs = accumArray (||) False (0,n)
(zip (filter (<=n) xs) (repeat True))
where n = length xs
array (0,19) [(0,True),(1,True),(2,True),(3,True),(4,True),…,(14,True),(15,False),(16,False),(17,True),(18,False),(19,True)]
97
Compare countlist and checklist
[8, 9, 0, 12, 11, 1, 10, 13, 7, 4, 14, 14, 14, 5, 17, 3, 19, 2, 6]
countlist xs = accumArray (+) 0 (0, n) (zip xs (repeat 1))
where n = length xs
array (0,19) [(0,1),(1,1),(2,1),(3,1),(4,1), … , (14,3),(15,0),(16,0),(17,1),(18,0),(19,1)]
[8, 9, 0, 12, 11, 1, 10, 13, 7, 4, 14, 14, 14, 5, 17, 3, 19, 2, 6]
checklist xs = accumArray (||) False (0,n)
(zip (filter (<=n) xs) (repeat True))
where n = length xs
array (0,19) [(0,True),(1,True),(2,True),(3,True),(4,True),…,(14,True),(15,False),(16,False),(17,True),(18,False),(19,True)]
We will use countlist
to solve the problem
99
A number that was not in the input
will have the form (_, 0)
[8, 9, 0, 12, 11, 1, 10, 13, 7, 4, 14, 14, 14, 5, 17, 3, 19, 2, 6]
countlist ___
array (0,19) [(0,1),(1,1),(2,1),(3,1),(4,1), … , (14,3),(15,0),(16,0),(17,1),(18,0),(19,1)]
These numbers were not in the
input list, as indicated by 0 in the
second value of their pairs
100
Select all pairs with (_,0)
[8, 9, 0, 12, 11, 1, 10, 13, 7, 4, 14, 14, 14, 5, 17, 3, 19, 2, 6]
[(x, k) | (x, k) <- assocs (countlist ___), k == 0]
[(15,0), (16,0), (18,0)]
101
Explanation of this
list comprehension
input set
[(x, k) | (x, k) <- assocs (countlist xs), k == 0]
predicate
“The (x, k) pairs are drawn from the list of pairs returned by the
assocs function (after applying the condition that the second value
in each pair equal zero).”
102
Select just the first value
in each pair
[8, 9, 0, 12, 11, 1, 10, 13, 7, 4, 14, 14, 14, 5, 17, 3, 19, 2, 6]
[x | (x, k) <- assocs (countlist ___), k == 0]
[15, 16, 18]
For each pair, output only the first value.
103
Select the first value
[8, 9, 0, 12, 11, 1, 10, 13, 7, 4, 14, 14, 14, 5, 17, 3, 19, 2, 6]
head [x | (x, k) <- assocs (countlist ___), k == 0]
15
head returns the first item in the list.
104
Here’s the Solution
import Data.Array
countlist :: [Int] -> Array Int Int
countlist xs = accumArray (+) 0 (0, n) (zip xs (repeat 1))
where n = length xs
findGap :: [Int] -> Int
findGap xs = head [x | (x, k) <- assocs \$ countlist xs, k == 0]
105
Find the smallest free number
Version 3
106
The Problem We Will Solve
107
Problem Statement
• Find the smallest natural number not in given
finite list of natural numbers.
108
What is the smallest number
not in this list?
[8, 9, 0, 12, 11, 1, 10, 13, 7, 4, 14, 24, 34, 5, 17, 3, 19, 2, 6]
15
109
Divide and Conquer
• We will split the list in half, determine if the left half
contains a missing number and if it does we will
recurse on that, otherwise we recurse on the right half.
• We will use the Haskell partition function. It
divides a list into a pair consisting of two lists. It has
two arguments:
– A Boolean function
– A list
For each element in the list, if the Boolean function evaluates
it to True then it goes in the first list, otherwise it goes in the
second list.
partition (<10) [2, 45, 5, 18, 12] returns ([2,5],[45,18,12])
110
Assumption
• The list we are processing has no duplicates
• If the list has duplicates, the algorithm may
enter into an infinite recursion
111
Partition using this function: (<b)
where b = half the length of the list
[8, 9, 0, 12, 11, 1, 10, 13, 7, 4, 14, 24, 34, 5, 17, 3, 19, 2, 6]
partition (<b) ___
where b = 1 + n `div` 2
n = length xs
b==10
[8,9,0,1,7,4,5,3,2,6]
[12,11,10,13,14,24,34,17,19]
112
Does the left list have gaps?
[8, 9, 0, 1, 7, 4, 5, 3, 2, 6]
How do we tell if the list is any missing numbers?
Here’s an easy way to tell:
1. Get the length of the list
2. If there are any missing numbers then the length is less than b.
Example: on the previous slide b = length xs `div` 2, which is 10.
The length of the above list is 10. Thus, it must not have any gaps.
Pretty neat, aye?
113
Variable names we will use
xs = [8, 9, 0, 12, 11, 1, 10, 13, 7, 4, 14, 24, 34, 5, 17, 3, 19, 2, 6]
partition
us = [8,9,0,1,7,4,5,3,2,6]
vs = [12,11,10,13,14,24,34,17,19]
a = index of the first item
m
n = length xs
b = a + 1 + (n `div` 2)
m = length us
114
Does the left list have gaps?
xs = [8, 9, 0, 12, 11, 1, 10, 13, 7, 4, 14, 24, 34, 5, 17, 3, 19, 2, 6]
partition
us = [8,9,0,1,7,4,5,3,2,6]
vs = [12,11,10,13,14,24,34,17,19]
a = index of the first item
If m == b – a then the left list has no gaps
n = length xs
b = a + 1 + (n `div` 2)
m = length us
115
If we recurse on the left list …
xs = [8, 9, 0, 12, 11, 1, 10, 13, 7, 4, 14, 24, 34, 5, 17, 3, 19, 2, 6]
partition
xs = [8,9,0,1,7,4,5,3,2,6]
vs = [12,11,10,13,14,24,34,17,19]
a = the previous value of a
n = the previous value of m
116
If we recurse on the right list …
xs = [8, 9, 0, 12, 11, 1, 10, 13, 7, 4, 14, 24, 34, 5, 17, 3, 19, 2, 6]
partition
us = [8,9,0,1,7,4,5,3,2,6]
xs = [12,11,10,13,14,24,34,17,19]
a = the previous value of b
n = the previous value of n minus
the previous value of m
117
Let’s trace an example
• The following slides traces the processing of a
list using the divide-and-conquer algorithm.
118
xs = [8, 9, 0, 12, 11, 1, 10, 13, 7, 4, 14, 24, 34, 5, 17, 3, 19, 2, 6]
a=0
n = length xs = 19
b = a + 1 + (n `div` 2) = 0 + 1 + (19 `div` 2) = 10
119
xs = [8, 9, 0, 12, 11, 1, 10, 13, 7, 4, 14, 24, 34, 5, 17, 3, 19, 2, 6]
a=0
n = length xs = 19
b = a + 1 + (n `div` 2) = 0 + 1 + (19 `div` 2) = 10
partition (< b) xs
us = [8,9,0,1,7,4,5,3,2,6]
vs = [12,11,10,13,14,24,34,17,19]
120
xs = [8, 9, 0, 12, 11, 1, 10, 13, 7, 4, 14, 24, 34, 5, 17, 3, 19, 2, 6]
a=0
n = length xs = 19
b = a + 1 + (n `div` 2) = 0 + 1 + (19 `div` 2) = 10
partition (< b) xs
us = [8,9,0,1,7,4,5,3,2,6]
vs = [12,11,10,13,14,24,34,17,19]
m = length us = 10
m == b – a == 10 – 0 == True
Therefore, this list has no missing
numbers and we should recurse on
the other list, vs.
121
set a to the value of b (10)
set n to this value: n – m (19 – 10 = 9)
xs = [12,11,10,13,14,24,34,17,19]
122
a = b = 10
n = n – m = 19 – 10 = 9
xs = [12,11,10,13,14,24,34,17,19]
b = a + 1 + (n `div` 2)
= 10 + 1 + (9 `div` 2)
= 15
123
a = b = 10
n = n – m = 19 – 10 = 9
xs = [12,11,10,13,14,24,34,17,19]
b = a + 1 + (n `div` 2)
= 10 + 1 + (9 `div` 2)
= 15
partition (< b) xs
us = [12,11,10,13,14]
vs = [24,34,17,19]
124
a = b = 10
n = n – m = 19 – 10 = 9
xs = [12,11,10,13,14,24,34,17,19]
b = a + 1 + (n `div` 2)
= 10 + 1 + (9 `div` 2)
= 15
partition (< b) xs
us = [12,11,10,13,14]
vs = [24,34,17,19]
m = length us = 5
m == b – a == 15 – 10 == True
Therefore, this list has no missing numbers and we should recurse on the other.
125
set a to the value of b (15)
set n to the value of n - m (4)
xs = [24,34,17,19]
126
set a to the value of b (15)
set n to the value of n - m (4)
xs = [24,34,17,19]
b = a + 1 + (n `div` 2)
= 15 + 1 + (4 `div` 2)
= 18
127
set a to the value of b (15)
set n to the value of n - m (4)
xs = [24,34,17,19]
b = a + 1 + (n `div` 2)
= 15 + 1 + (4 `div` 2)
= 18
partition (< b) xs
us = [17]
vs = [24,34,19 ]
m = length us = 1
m == b – a == 18 – 15 == False
Therefore, this list has a missing number and we should recurse on it.
128
set a to the old value of a (15)
set n to the value of m (1)
xs = [17]
129
set a to the old value of a (15)
set n to the value of m (1)
xs = [17]
b = a + 1 + (n `div` 2)
= 15 + 1 + (1 `div` 2)
= 16
130
set a to the old value of a (15)
set n to the value of m (1)
xs = [17]
b = a + 1 + (n `div` 2)
= 15 + 1 + (1 `div` 2)
= 16
partition (< b) xs
us = [ ]
vs = [17]
m = length us = 0
m == b – a == 16 – 15 == False
Therefore, this list has a missing number and we should recurse on it.
131
set a to the old value of a (15)
set n to the value of m (0)
If n == 0 then return a
Done! The answer is: 15
132
Time Requirements
• With a list of length “n” this algorithm takes
on the order of n steps.
• That is, it is a linear-time solution for the
problem.
133
Here’s the Solution
import List
minfree :: [Int] -> Int
minfree xs = minfrom 0 (length xs, xs)
minfrom :: Int -> (Int, [Int])
minfrom a (n, xs) | n == 0
| m == b - a
| otherwise
where (us,
b
m
-> Int
= a
= minfrom b (n - m, vs)
= minfrom a (m, us)
vs) = partition (<b) xs
= a + 1 + (n `div` 2)
= length us
134
```