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 2019 Imperative programming 8 a Solution by
Codex 0 2026-10-25
Test-driven development uses a short cycle: write a test for the next behavior and observe its failure, implement enough to pass it, then refactor without changing the tested behavior. In a conventional implementation-then-test workflow, tests primarily assess code after it has been written; in TDD they also guide each small design increment. Tests accumulate into a regression suite, but passing them is not a universal correctness proof.[ref]
Test-driven development in the Agile Alliance glossary. Definition: interleaved unit tests, implementation and refactoring
A good candidate is a deterministic priority queue operation with a precise contract. Before implementation, test that inserting two equal values permits two minimum deletions and only then leaves an empty queue. The expected result is objective, cheap to check and useful for finding the duplicate-loss bug in a set-based representation.
An exploratory decision about whether an editor's toolbar feels usable is a poor candidate for TDD alone: the desired behavior and human evaluation criteria may not yet be settled, and an executable assertion does not replace user observation. Prototypes and usability evaluation can establish the design before stable behavioral properties are tested automatically. The distinction is the availability of a useful repeatable test oracle, not a claim that interface software is inherently untestable.
Past exam of the year 1 of the computer science course of the University of Oxford 2019 Imperative programming 7 d Solution by
Codex 0 2026-10-25
Use object composition: a logging wrapper owns a private
ResizableFrame and delegates dimension operations to it, rather than being its subclass. The wrapper takes the before/after area around each public operation. Its own flip calls the component's whole flip once, compares only the completed states, and therefore records no increase. The component must be exclusively owned or defensively copied, so clients cannot bypass the wrapper's accounting.The component's internal calls cannot dynamically dispatch into the separate wrapper. This prevents the setter-based
flip implementation change from creating false log entries and reduces dependence on undocumented superclass internals. The wrapper can also choose a smaller interface. Costs include forwarding code and the loss of automatic ResizableFrame subtyping: code requiring that concrete superclass cannot necessarily accept the wrapper. A shared abstract frame interface can recover substitutability while keeping implementation reuse based on composition. Composition improves this dependency boundary; it does not remove the need for a clear mutation and ownership contract. Past exam of the year 1 of the computer science course of the University of Oxford 2019 Imperative programming 6 g Solution by
Codex 0 2026-10-25
Make two separate character iterators so that scanning uppercase letters does not consume the lowercase pass:Each filtering iterator preserves the original order of its selected characters. Concatenation therefore yields all uppercase letters in source order, then all lowercase letters in source order, omitting other characters. The two
def upperLower(s: String): Iterator[Char] = {
val upper = new FilterIterator[Char]((c: Char) => c.isUpper, s.iterator)
val lower = new FilterIterator[Char]((c: Char) => c.isLower, s.iterator)
new ConcatIterator[Char](upper, lower)
}s.iterator calls are essential: reusing a single consuming iterator would let the first pass discard lowercase characters before the second pass could return them. Construction remains lazy; an empty string yields an exhausted iterator without a special case. Past exam of the year 1 of the computer science course of the University of Oxford 2019 Imperative programming 6 f Solution by
Codex 0 2026-10-25
Use one cached optional result. Only a request for availability or the next result fills that cache:This is a demand-driven filtering iterator. When the cache is empty, its abstract remaining sequence is the filtered remaining input. When it holds
class FilterIterator[T](test: T => Boolean, iter: Iterator[T])
extends Iterator[T] {
private var cached: Option[T] = None
private def prepare(): Unit = {
while (cached.isEmpty && iter.hasNext) {
val x = iter.next()
if (test(x)) cached = Some(x)
}
}
def hasNext: Boolean = {
prepare()
cached.nonEmpty
}
def next(): T = {
prepare()
cached match {
case Some(x) =>
cached = None
x
case None => throw new NoSuchElementException("Filtered iterator exhausted")
}
}
}Some(x), the abstract sequence is x followed by the filtered remaining input. The loop invariant for prepare says that all input elements consumed during the present search have failed test, except for the one cached passing value if one has been found. The first passing value stops the loop, so it cannot read past a result that the client has not yet consumed.Construction performs no underlying reads, and repeated
hasNext calls reuse a cached result. next also works without a preceding hasNext, clears only the result it returns, and does not prefetch its successor. Some(x), rather than Option(x), allows a passing null value to remain a genuine cached value. For finite remaining input, its length is a loop variant; for infinite input, availability can legitimately run forever if no further passing element exists. Deterministic terminating tests and exclusive ownership of the consuming input are assumed. One cache slot is extra storage. Past exam of the year 1 of the computer science course of the University of Oxford 2019 Imperative programming 6 e Solution by
Codex 0 2026-10-25
The expression constructs a valid iterator object; it does not itself return the concatenated numeric or character values. The element types have a common supertype Successive calls return
AnyVal, and covariance lets Iterator[Int] and Iterator[Char] serve as the two inputs to ConcatIterator[AnyVal]. In the ordinary Scala 2 typing of this expression, the common element type is AnyVal. One can make the intended widening explicit:new ConcatIterator[AnyVal](
List(1, 2, 3).iterator,
List('a', 'b', 'c').iterator
)1, 2, 3, 'a', 'b', 'c', then exhaustion. Characters remain characters: viewing an existing iterator at a wider type does not convert its contents to integer character codes. No next() is invoked merely by constructing this adapter. The common-type argument uses subtype polymorphism and covariant type parameters, rather than requiring the two concrete input types to be equal. Past exam of the year 1 of the computer science course of the University of Oxford 2019 Imperative programming 6 d Solution by
Codex 0 2026-10-25
Use iterator concatenation and short-circuit the second availability test while the first iterator still has results:The abstract remaining sequence is the remaining sequence of
class ConcatIterator[T](first: Iterator[T], second: Iterator[T])
extends Iterator[T] {
def hasNext: Boolean = first.hasNext || second.hasNext
def next(): T = {
if (first.hasNext) first.next()
else second.next()
}
}first followed by that of second. Each next() consumes the head of precisely this sequence. When both are exhausted, delegation to second.next() raises the required exception. Construction consumes no elements, and hasNext never calls either underlying next(). As usual, clients should not separately consume these iterators while relying on the adapter's traversal. Sharing one underlying iterator between both arguments also shares its state; it does not duplicate its elements. Past exam of the year 1 of the computer science course of the University of Oxford 2019 Imperative programming 6 c Solution by
Codex 0 2026-10-25
The plus marks a covariant type parameter: if , then
Iterator[S] <: Iterator[T]. An iterator producing a subtype's values can be used where an iterator of the supertype is required. For example, a string iterator can be viewed as an iterator of AnyRef, because strings are reference values. The direction is appropriate for a producer: calling next() gives a value valid at the wider type. It would not be safe to expose an ordinary insertion method accepting arbitrary wider-type values into a subtype-only collection. This is a subtyping relationship, not a request to transform each produced value.[ref]Scala 2.12 types specification. Conformance of parameterized types with covariant parameters
Past exam of the year 1 of the computer science course of the University of Oxford 2019 Imperative programming 6 b Solution by
Codex 0 2026-10-25
The essential abstract methods are:
def hasNext: Boolean
def next(): ThasNext reports whether another result is available. next() returns that result and advances; if exhausted, it throws NoSuchElementException. The other ordinary iterator operations are implemented using these primitives. An availability check must not silently discard a result visible to the client, although an adapter may need to fetch and cache underlying values in order to decide availability.[ref]Scala 2.12 iterator API documentation. Iterator abstract members hasNext and next; exhaustion contract
Past exam of the year 1 of the computer science course of the University of Oxford 2019 Imperative programming 6 a Solution by
Codex 0 2026-10-25
The Iterator pattern gives clients a uniform way to inspect and consume the elements of a collection without exposing how that collection is stored. An iterator has a traversal state separate from the abstract collection interface, so the same client loop can process an array, a linked list or generated values. It preserves encapsulation and representation independence: changing the underlying data structure need not change the traversal client. Separate iterator instances can track separate traversals; two aliases of one consuming iterator instead share its progress.
Past exam of the year 1 of the computer science course of the University of Oxford 2019 Imperative programming 5 d Solution by
Codex 0 2026-10-25
Insert before the first entry that is at least the new value; equal values remain separate occurrences:In the scanning branch, the loop invariant says that
class ListPriorityQueue extends PriorityQueue[Int] {
private var first: Node = null
def clear(): Unit = { first = null }
def isEmpty(): Boolean = first == null
def insert(x: Int): Unit = {
if (first == null || x <= first.value) {
first = new Node(x, first)
} else {
var p = first
while (p.next != null && p.next.value < x) {
p = p.next
}
p.next = new Node(x, p.next)
}
}
def delMin(): Int = {
require(first != null, "Empty priority queue")
val result = first.value
first = first.next
result
}
}p is reachable and all values from first through p are strictly smaller than x. The rest of the chain is unchanged and remains sorted. The loop variant is the number of nodes after p. At exit either the next value is at least x or there is no next node, so inserting between p and p.next preserves the representation invariant and adds exactly one occurrence under the abstraction function. The head branch covers an empty chain, a new minimum and equality with the old minimum. delMin returns the head's minimum value and removes exactly that occurrence.Insertion is worst-case;
delMin, isEmpty and the head-resetting clear are . Reclaiming an abandoned chain later is garbage-collection work, not an explicit traversal performed by clear. Storage is , including separate nodes for duplicate values. No fixed insertion-capacity precondition has been added. Past exam of the year 1 of the computer science course of the University of Oxford 2019 Imperative programming 5 c Solution by
Codex 0 2026-10-25
Use one real linked list node per occurrence, with a private reference to the first:The representation invariant says that the reachable chain is finite, acyclic and nondecreasing in
class Node(val value: Int, var next: Node)
// Inside the queue implementation:
private var first: Node = nullvalue, and is owned by the queue. Equal adjacent values are explicitly allowed. The abstraction function is the multiset containing one occurrence of v.value for every reachable real linked list node v. Initially first==null represents the empty multiset. No artificial smallest Int is needed as a sentinel, and Int.MinValue remains a valid real value. 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





