Computer Science at Oxford. Stephen Drape Access/Schools Liaison Officer. Four myths about Oxford. There’s little chance of getting in It’s expensive College choice is very important You have to be very bright. Myth 1: Little chance of getting in. False!
Access/Schools Liaison Officer
There’s little chance of getting in
College choice is very important
You have to be very bright
Admissions data for 2007 entry:
Design and Analysis of Algorithms
Logic and Proof
It’s not about learning new programming languages.
It is about understanding why programs work, and how to design them.
If you know how programs work then you can use a variety of languages.
It is the study of the Mathematics behind lots of different computing concepts.
The first 10 Fibonacci numbers (from 1) are:
The Fibonacci numbers occurs in nature, for example: plant structures, population numbers.
Named after Leonardo of Pisa
who was nicked named “Fibonacci”
The next number in the sequence is worked out by adding the previous two terms.
The next numbers are therefore
34 + 55 = 89
55 + 89 = 144
To work out the nth Fibonacci number, which we’ll call fib(n), we have the rule:
We also need base cases:
fib(0) = 0 fib(1) = 1
This sequence is defined using previous terms of the sequence – it is an example of a recursive definition.
fib(n – 1) + fib(n – 2)
The sequence has a relationship with the Golden Ratio
Fibonacci numbers have a variety of properties such as
Using a language called Haskell, we can write the following function:
> fib(0) = 0
> fib(1) = 1
> fib(n) = fib(n-1) + fib(n-2)
which looks very similar to our algebraic definition
Suppose we want to find fib(5)
The program blindly follows the definition of fib, not remembering any of the other values.
(fib(3) + fib(2)) + fib(3)
the calculation for fib(3) is worked out twice.
The number of steps needed to work out fib(n) is proportional to n – it takes exponential time.
Why this program is so inefficient is because at each step we have two occurrences of fib (termed recursive calls).
When working out the Fibonacci sequence, we should keep track of previous values of fib and make sure that we only have one occurrence of the function at each stage.
> fibtwo(0) = (0,1)
> fibtwo(n) = (b,a+b)
> where (a,b) = fibtwo(n-1)
> newfib(n) = fst(fibtwo(n))
The function fst means take the first number
The function fibtwo actually works out:
fibtwo(n) = (fib(n), fib(n+1))
We have used a technique called tupling – this means that we keep extra results at each stage of a calculation.
This version is much more efficient that the previous one (it is linear time).
When designing algorithms, we have to consider a number of things:
Our algorithm should be efficient – that is, where possible, it should not take too long or use too much memory.
We should look at ways of improving existing algorithms.
We may have to try a number of different approaches and techniques.
We should make sure that our algorithms are correct.
If there’s any comments or questions then please ask.
There should be staff and students available to talk to
Find the HCF of 308 and 1001.
1) Find the factors of both numbers:
308 – [1,2,4,7,11,14,22,28,44,77,154,308]
1001 – [1,7,11,13,77,91,143,1001]
2) Find those in common
3) Find the highest
Answer = 77
For our example, we had three steps:
Find the factors
Find those factors in common
Find the highest factor in common
These steps allow us to construct an algorithm.
We are going to use a programming language called Haskell.
Haskell is used throughout the course at Oxford.
It is very powerful as it allows you write programs that look very similar to mathematical equations.
You can easily prove properties about Haskell programs.
We need produce a list of factors for a number n – call this list factor(n).
A simple way is to check whether each number d between 1 and n is a factor of n.
We do this by checking what the remainder is when we divide n by d.
If the remainder is 0 then d is a factor of n.
We are done when d=n.
We create factor lists for both numbers.
Now that we have our factor lists, which we will call f1 and f2, we create a list of common factors.
We do this by looking at all the numbers in f1 to see if they are in f2.
We there are no more numbers in f1 then we are done.
Call this function: common(f1,f2).
Now that we have a list of common factors we now check which number in our list is the biggest.
We do this by going through the list remembering which is the biggest number that we have seen so far.
Call this function: highest(list).
If list is empty then return 0, otherwise we check whether the first member of list is higher than the rest of list.
To calculate the hcf for two numbers a and b, we just follow the three steps in order.
So, in Haskell, we can define
Remember that when composing functions, we do the innermost operation first.
Although this method is fairly easy to explain, it is quite slow for large numbers.
It also wastes quite a lot of space calculating the factors of both numbers when we only need one of them.
Can we think of any ways to improve this method?
Remember factors occur in pairs so that we actually find two factors at the same time.
If we find the factors in pairs then we only need to check up to n.
We could combine common and highest to find the hcf more quickly (this kind of technique is called fusion).
Could use prime numbers.
This algorithm was apparently first given by the famous mathematician Euclid around 300 BC.
The algorithm works because any factor of a and b is also a factor of a – b
hcf(1001,308) 1001 = 3 × 308 + 77
= hcf(308,77) 308 = 4 × 77
Core CS 1(75%)
Core CS 2(50%)