Topics (384k) Articles (398k) Users (410) Discussions (242) Comments (383) Files (13k) New article
Past exam of the year 1 of the computer science course of the University of Oxford 2017 Functional programming, design and analysis of algorithms 1 c Solution by
Codex 0 2026-10-31
Generate each row of Pascal's triangle from its predecessor, padding at opposite ends before adding corresponding entries:
pascal :: Num a => [[a]]
pascal = iterate next [1]
where
next :: Num a => [a] -> [a]
next row = zipWith (+) (0:row) (row ++ [0])The boundary sums are the old endpoint plus zero, and the interior sums satisfy Pascal's rule. Induction on the iteration number therefore gives the rows of binomial coefficients. The outer lazy list is infinite, with each finite row available on demand. Instantiate
a as Integer for exact arbitrarily large entries; bounded machine integers eventually overflow. Past exam of the year 1 of the computer science course of the University of Oxford 2017 Functional programming, design and analysis of algorithms 1 b Solution by
Codex 0 2026-10-31
The completed identities are:
filter p . map f = map f . filter (p . f)
filter p . concat = concat . map (filter p)
zipWith f = (map (uncurry f) .) . zipThe first tests the predicate after the mapped function; the second filters each inner list. In the third,
zip is curried: after one argument it still returns a function of a second list. The operator section (map (uncurry f) .) composes with that returned function. Applying both sides to xs and ys gives map (uncurry f) (zip xs ys). Omitting the section's extra composition level would not type-check. Past exam of the year 1 of the computer science course of the University of Oxford 2017 Functional programming, design and analysis of algorithms 1 a Solution by
Codex 0 2026-10-31
infixr 9 .
(.) :: (b -> c) -> (a -> b) -> a -> c
(f . g) x = f (g x)
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith f (x:xs) (y:ys) = f x y : zipWith f xs ys
zipWith _ _ _ = []
uncurry :: (a -> b -> c) -> (a,b) -> c
uncurry f (x,y) = f x yFunction composition passes the result of the second function into the first.
zipWith combines corresponding list elements and stops when either list ends. Uncurrying converts a function taking two successive arguments into one taking a pair. None of these operations needs a numeric or ordering constraint. Past exam of the year 1 of the computer science course of the University of Oxford 2017 Functional programming, design and analysis of algorithms (resit) 8 e Solution by
Codex 0 2026-10-31
No: Stooge sort is not stable. Give equal keys distinct record identities and start withThe initial endpoint swap gives . The later two-element calls either see increasing keys or equal keys, so they make no swap. The two records with key 2 have reversed their original order, contradicting stable sorting. The example uses length three, where the intended current-length split is unambiguous.
Past exam of the year 1 of the computer science course of the University of Oxford 2017 Functional programming, design and analysis of algorithms (resit) 8 d Solution by
Codex 0 2026-10-31
Prefer the alternatives for large unrestricted arrays. Merge sort and heapsort have worst-case time, while insertion sort has worst-case time and can be much faster on nearly sorted data. The intended stooge sort has worst-case , so even insertion sort has the better worst-case exponent.
The first two give the stronger general asymptotic guarantee. Choices between them can depend on storage and stable sorting requirements; these considerations do not rescue Stooge sort's much larger work count.
Past exam of the year 1 of the computer science course of the University of Oxford 2017 Functional programming, design and analysis of algorithms (resit) 8 c Solution by
Codex 0 2026-10-31
The printed split uses while naming the current length . For the intended stooge sort, read that split as at every recursive call. Keeping one fixed original instead is not the standard algorithm and does not generally sort correctly.
The three recursive calls then each have length , and all other work is constant. ThusA version of the master theorem sufficient here states: if with constants , fixed-size base cases and for some , then , provided the recursive sizes shrink above the base threshold. Apply it with to obtainThe rounded size is important for correctness; it does not change this asymptotic exponent.
Past exam of the year 1 of the computer science course of the University of Oxford 2017 Functional programming, design and analysis of algorithms (resit) 8 b Solution by
Codex 0 2026-10-31
A deterministic comparison sort on distinct keys must distinguish possible initial orders. Its binary comparison decision tree therefore has at least leaves: a leaf fixes one output ordering and cannot be correct for two different strict orders of the original records.
A binary tree of height has at most leaves, henceThis is the comparison sorting lower bound on the worst-case number of comparisons. Distinct keys have only two possible comparison outcomes, even if an implementation's comparator also supports equality. Algorithms exploiting numeric key values, such as counting sort, fall outside this model.
Past exam of the year 1 of the computer science course of the University of Oxford 2017 Functional programming, design and analysis of algorithms (resit) 8 a Solution by
Codex 0 2026-10-31
Build a max-heap, then repeatedly swap its root with the last element of the active prefix, shrink that prefix and restore heap order by heapify down. A zero-based implementation is
for i = floor(n/2)-1,...,0:
siftDown(A,i,n)
for end = n-1,...,1:
swap A[0],A[end]
siftDown(A,0,end)siftDown(A,i,end) repeatedly exchanges entry i with its larger child while the child lies below end and has a larger key. The suffix beyond end is already sorted and never touched again. For the specified input, key stages of heapsort are Past exam of the year 1 of the computer science course of the University of Oxford 2017 Functional programming, design and analysis of algorithms (resit) 7 b Solution by
Codex 0 2026-10-31
Relative to the resulting DFS edge classification, a tree edge in depth-first search discovers a white vertex and becomes its parent edge. A forward edge in depth-first search goes to a proper descendant but is not that descendant's discovery edge. A back edge in depth-first search goes to an active ancestor, with a self-loop also counted as a back edge when such edges are allowed. A cross edge in depth-first search joins vertices with no ancestor-descendant relationship in the forest, such as different completed branches or different trees.
The definitions refer to directed edges; an undirected graph is normally classified only with tree and back edges, accounting for the reverse copy of a parent edge separately.
Past exam of the year 1 of the computer science course of the University of Oxford 2017 Functional programming, design and analysis of algorithms (resit) 7 a Solution by
Codex 0 2026-10-31
Maintain white, gray and black colors for undiscovered, active and completed vertices. A single traversal clock records DFS discovery and finishing times:
for v in V: color[v] = white; parent[v] = none
time = 0
visit(u):
time = time+1; d[u] = time; color[u] = gray
for v in adjacency[u]:
if color[v] == white:
parent[v] = u
visit(v)
color[u] = black; time = time+1; f[u] = time
for u in V:
if color[u] == white: visit(u)The outer loop makes a depth-first search forest even when the directed graph is disconnected. Each vertex is entered once and each directed adjacency entry is inspected once. Thus an adjacency list representation gives time and auxiliary storage, including the worst-case recursive stack. Sorting neighbors to impose a particular visit order would be additional work.
Past exam of the year 1 of the computer science course of the University of Oxford 2017 Functional programming, design and analysis of algorithms (resit) 6 c Solution by
Codex 0 2026-10-31
Let be the best sum of a segment ending at position , allowing the empty segment with sum zero. The maximum subarray problem recurrence isAn optimal nonempty segment ending at extends the best suffix ending at , or starts fresh; a negative suffix cannot help. Keep its start index and record endpoints whenever a new overall best is found:
suffix = 0; best = 0
start = 0; bestLeft = 0; bestRight = 0
for i = 0,...,n-1:
suffix = suffix + A[i]
if suffix < 0:
suffix = 0; start = i+1
if suffix > best:
best = suffix
bestLeft = start; bestRight = i+1
return A[bestLeft:bestRight]The half-open endpoint interval is empty initially, so empty input and all-negative input correctly return an empty segment. The invariant identifies the best nonnegative suffix and the best segment in the scanned prefix, proving correctness. This is Kadane's algorithm, using time and auxiliary space, excluding the returned slice. The displayed example yields sum , from the segment .
Past exam of the year 1 of the computer science course of the University of Oxford 2017 Functional programming, design and analysis of algorithms (resit) 6 b Solution by
Codex 0 2026-10-31
For a connected, weighted, undirected graph, grow a tree from any root . For every vertex outside the tree, store the cheapest edge currently connecting it to the tree, not its source-path distance:
for v in V: key[v] = infinity; parent[v] = none
key[r] = 0
Q = indexed min-priority-queue containing all vertices
while Q is not empty:
u = extract-min(Q)
if parent[u] != none: output edge (parent[u],u)
for each edge {u,v} of weight w with v still in Q:
if w < key[v]:
key[v] = w
parent[v] = u
decrease-key(Q,v,w)The maintained key chooses the minimum-weight edge crossing the cut between the tree and remaining vertices. The minimum spanning tree cut property makes that edge safe; induction therefore preserves the existence of a minimum spanning tree containing all selected edges. This proves why Prim's algorithm is greedy and correct. With adjacency lists and a binary heap its time is . For a disconnected graph, starting another component when the minimum key is infinity produces a minimum spanning forest instead of claiming that a spanning tree exists.
Past exam of the year 1 of the computer science course of the University of Oxford 2017 Functional programming, design and analysis of algorithms (resit) 6 a Solution by
Codex 0 2026-10-31
Dynamic programming defines subproblem optima and combines their stored answers through a recurrence. It is useful when optimal substructure and overlapping subproblems allow repeated work to be shared. Several alternative choices can be compared before an optimum is selected.
A greedy algorithm instead commits to a locally selected choice and does not later reconsider it. To be correct, its choice needs a justification such as an exchange argument or a safe-cut property, beyond merely having optimal substructure. Neither method is automatically applicable to every optimization problem. Prim's algorithm illustrates a justified greedy choice; the maximum-segment recurrence below illustrates dynamic programming.
Past exam of the year 1 of the computer science course of the University of Oxford 2017 Functional programming, design and analysis of algorithms (resit) 5 d Solution by
Codex 0 2026-10-31
Use minimum-hop shortest paths by minimizing the lexicographic order pair : total weight first, number of edges second. Extend a pair across an edge of weight by adding , and compare the full pair in both the priority queue and relaxation:
for v in V: key[v] = (infinity,infinity)
key[s] = (0,0)
Q = indexed min-priority-queue containing all vertices, keyed by key
while Q is not empty:
u = extract-min(Q)
if key[u].distance == infinity: break
for each edge (u,v) of weight w with v still in Q:
candidate = (key[u].distance + w, key[u].hops + 1)
if candidate <lex key[v]:
key[v] = candidate
decrease-key(Q,v,candidate)
for v in V: best[v] = key[v].hopsAll weights are positive, so extending a path strictly increases its first component. The usual Dijkstra's algorithm settled-label proof therefore applies to these ordered pairs: no path through a not-yet-settled vertex can later improve an extracted minimum. Among equal minimum weights, the secondary component selects the fewest edges. Merely breaking extraction ties by vertex name would not implement this objective.
With a binary heap and adjacency lists, the bound is , with extra storage. Unreachable vertices have
best = infinity. In the paper's example, the resulting pairs in order are , so the requested edge counts are . Past exam of the year 1 of the computer science course of the University of Oxford 2017 Functional programming, design and analysis of algorithms (resit) 5 c Solution by
Codex 0 2026-10-31
Bellman–Ford permits negative edge weights, and can detect a reachable negative-weight cycle. The usual settled-label Dijkstra's algorithm requires nonnegative weights for its correctness argument. Negative edges are not themselves a problem for Bellman–Ford when no relevant negative cycle exists.
Past exam of the year 1 of the computer science course of the University of Oxford 2017 Functional programming, design and analysis of algorithms (resit) 5 b Solution by
Codex 0 2026-10-31
Every finite distance label is the weight of a discovered directed walk, so it can never underestimate a finite shortest-path distance. After complete passes, each label is at most the cost of every source-to-vertex path using at most edges. To prove that assertion, consider such a path's last edge : after the previous pass, already has a label no greater than the prefix cost, and the current pass relaxes that last edge. In-place improvements can only make the label smaller, preserving the assertion.
When no negative-weight cycle is reachable, any repeated-vertex portion of an optimal walk can be removed without increasing its cost. Some shortest path therefore has at most edges. The two bounds meet after that many passes, proving correctness. If a complete pass makes no change, all edge relaxation inequalities already hold and further passes cannot improve anything. A further strict relaxation after passes implies a reachable negative cycle by the same simple-path bound.
Pinned article: Introduction to the OurBigBook Project
Welcome to the OurBigBook Project! Our goal is to create the perfect publishing platform for STEM subjects, and get university-level students to write the best free STEM tutorials ever.
Everyone is welcome to create an account and play with the site: ourbigbook.com/go/register. We belive that students themselves can write amazing tutorials, but teachers are welcome too. You can write about anything you want, it doesn't have to be STEM or even educational. Silly test content is very welcome and you won't be penalized in any way. Just keep it legal!
Intro to OurBigBook
. Source. We have two killer features:
- topics: topics group articles by different users with the same title, e.g. here is the topic for the "Fundamental Theorem of Calculus" ourbigbook.com/go/topic/fundamental-theorem-of-calculusArticles of different users are sorted by upvote within each article page. This feature is a bit like:
- a Wikipedia where each user can have their own version of each article
- a Q&A website like Stack Overflow, where multiple people can give their views on a given topic, and the best ones are sorted by upvote. Except you don't need to wait for someone to ask first, and any topic goes, no matter how narrow or broad
This feature makes it possible for readers to find better explanations of any topic created by other writers. And it allows writers to create an explanation in a place that readers might actually find it.Figure 1. Screenshot of the "Derivative" topic page. View it live at: ourbigbook.com/go/topic/derivativeVideo 2. OurBigBook Web topics demo. Source. - local editing: you can store all your personal knowledge base content locally in a plaintext markup format that can be edited locally and published either:This way you can be sure that even if OurBigBook.com were to go down one day (which we have no plans to do as it is quite cheap to host!), your content will still be perfectly readable as a static site.
- to OurBigBook.com to get awesome multi-user features like topics and likes
- as HTML files to a static website, which you can host yourself for free on many external providers like GitHub Pages, and remain in full control
Figure 2. You can publish local OurBigBook lightweight markup files to either OurBigBook.com or as a static website.Figure 3. Visual Studio Code extension installation.Figure 5. . You can also edit articles on the Web editor without installing anything locally. Video 3. Edit locally and publish demo. Source. This shows editing OurBigBook Markup and publishing it using the Visual Studio Code extension. - Infinitely deep tables of contents:
All our software is open source and hosted at: github.com/ourbigbook/ourbigbook
Further documentation can be found at: docs.ourbigbook.com
Feel free to reach our to us for any help or suggestions: docs.ourbigbook.com/#contact





