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 2022 Digital systems, linear algebra, introduction to formal proof resit 6 a ii Solution by
Codex 0 2026-10-25
Past exam of the year 1 of the computer science course of the University of Oxford 2022 Digital systems, linear algebra, introduction to formal proof resit 6 a i Solution by
Codex 0 2026-10-25
For , the all-ones matrix is , so and whenever . These subspaces have dimensions one and two and span . Thus the eigenvalues are and .
Past exam of the year 1 of the computer science course of the University of Oxford 2021 Imperative programming 8 d ii Solution by
Codex 0 2026-10-25
Constructing channel implementations, decorators and adapters allocates software objects that hold state and references to other software objects. As configurations and temporary processing chains are replaced, some old software objects become unreachable. A typical Scala program on a managed runtime relies on garbage collection to recycle that storage; otherwise unreclaimed allocation can exhaust the available heap memory.
A reachable wrapper keeps its wrapped component reachable. Sharing a channel among several wrappers can extend its lifetime until all relevant references disappear. Many software objects alone do not imply that collection can free them: if the program deliberately retains every channel, those software objects remain live. The reason garbage collection is useful is repeated allocation combined with changing reachability, not an assumption that the integer-returning
apply operation allocates a fresh channel on every call. Past exam of the year 1 of the computer science course of the University of Oxford 2021 Imperative programming 8 d i Solution by
Codex 0 2026-10-25
Garbage collection automatically reclaims allocated memory that is no longer reachable by the running program. Garbage collection roots such as active references and static storage lead through object-reference fields to reachable software objects in heap memory. A tracing garbage collection implementation preserves reachable software objects and can reclaim unreachable ones, including unreachable cycles.
An software object becoming unreachable is different from its state being old or its last object method call having finished. A retained reference can keep it live indefinitely. Collection timing is an implementation matter; automatic reclamation does not promise that an software object is reclaimed immediately when the final useful reference disappears.
Past exam of the year 1 of the computer science course of the University of Oxford 2021 Imperative programming 8 c ii Solution by
Codex 0 2026-10-25
Use the adapter pattern, keeping the existing component software object in both directions:
class PipeAsChannel(pipe: Pipe) extends Channel {
override def apply(n: Int): Int = {
pipe.consume(n)
pipe.result
}
}
class ChannelAsPipe(channel: Channel, initialResult: Int) extends Pipe {
private var last = initialResult
override def consume(n: Int): Unit = {
last = channel(n)
}
override def result: Int = last
}The first adapter feeds the input before reading the pipe's output. The second invokes the channel exactly once per consume and caches its returned output; subsequent result queries do not advance it. Its initial result must be supplied explicitly, because a general channel object interface exposes no initial-output query. Calling the channel on a dummy input during construction would mutate arbitrary state and would invent behavior the object interface does not promise.
These adapters preserve the sequential update/output behavior after each real input, assuming no interfering access to the wrapped component. They do not claim a perfect inverse for every aspect of the original object interfaces: pipe initialization is additional observable state, whereas a channel alone does not specify that observation.
Past exam of the year 1 of the computer science course of the University of Oxford 2021 Imperative programming 8 c i Solution by
Codex 0 2026-10-25
The pipe object interface supports command-query separation: consuming an input changes state, while querying the result observes the current output without feeding another input. A client can inspect the result repeatedly, including an initial result when the concrete pipe defines one. That is useful for accumulated statistics.
The channel object interface instead packages an input update and its associated output into one call. For request-and-result processing this is simpler: the caller cannot forget which update precedes a query. A pipe caller must respect the intended order of operations, and interleaving other callers between consume and result can change the observation. A single channel object method is not automatically thread-safe either; synchronization is a separate property.
Neither object interface is universally better. The choice depends on whether clients need independent observation of state or a combined transformation step. The adapters below can reconcile their protocols, provided the initial-result policy is made explicit.
Past exam of the year 1 of the computer science course of the University of Oxford 2021 Imperative programming 8 a iii Solution by
Codex 0 2026-10-25
Class inheritance offers a compact specialized implementation: the scaled sum is also a
SumChannel and can be used where that concrete type is required, while its inherited state handling is reused directly.The decorator supports run-time object composition over any
Channel implementation, including an already constructed stateful software object, without editing or subclassing each concrete software class. Its extra software object and delegation are a small cost. The two approaches therefore serve different reuse needs; the wrapper need not pretend to be the concrete sum-channel software class. Past exam of the year 1 of the computer science course of the University of Oxford 2021 Imperative programming 8 a ii Solution by
Codex 0 2026-10-25
Use the decorator pattern. The wrapper implements the same object interface as its component and delegates before changing the output:
class ScaledChannel(inner: Channel, factor: Int) extends Channel {
override def apply(n: Int): Int = factor * inner(n)
}It can wrap any channel software object, not only a sum channel. Constructing the wrapper at run time chooses the additional behavior for an existing component, and several wrappers can be composed without adding a subclass for every combination. Each call reaches the wrapped channel once, preserving its state evolution. Scaling the input instead would define a different transformation, particularly for a component that already has history.
Past exam of the year 1 of the computer science course of the University of Oxford 2021 Imperative programming 8 a i Solution by
Codex 0 2026-10-25
Override the operation and scale the result of exactly one superclass call:
class ScaledSumChannel(factor: Int) extends SumChannel {
override def apply(n: Int): Int = factor * super.apply(n)
}The superclass updates its previous-input state once and returns its ordinary sum; only that returned value is scaled. The inputs and superclass history are unchanged by the scaling. Reimplementing the state update is unnecessary and could accidentally diverge from the superclass contract. As in the supplied channel, arithmetic uses the declared fixed-width integer type.
Past exam of the year 1 of the computer science course of the University of Oxford 2021 Imperative programming 7 d ii Solution by
Codex 0 2026-10-25
Fun[Base, Derived] can safely supply a Fun[Base, Base] contract; Fun[Base, Base] cannot in general supply a Fun[Base, Derived] contract. The input obligation is unchanged, while a derived result satisfies every base-result promise. This is the covariant output rule of function subtyping.With the invariant printed trait, implement the safe view explicitly:
def widenResult(f: Fun[Base, Derived]): Fun[Base, Base] =
new Fun[Base, Base] {
def apply(x: Base): Base = f(x)
}Using the illustrative classes from part i, an unsafe substitution would let a client assume a derived-only operation on a result that is merely a base software object:
val broadResult = new Fun[Base, Base] {
def apply(x: Base): Base = new Base
}
def derivedResultClient(f: Fun[Base, Derived]): Int =
f(new Base).special()
// derivedResultClient(broadResult) must be rejected.The direct, variance-aware object interface that would express both safe directions is
trait Fun[-S, +T] { def apply(x: S): T }. Its object method consumes the contravariant parameter and produces the covariant parameter. This is an explicitly proposed variant of the printed invariant declaration, not an assumption that its annotations were already present. Past exam of the year 1 of the computer science course of the University of Oxford 2021 Imperative programming 7 d i Solution by
Codex 0 2026-10-25
A function accepting every
Base can safely be used where only Derived inputs will be supplied. The reverse direction is unsafe. A Derived argument is already a valid Base argument; restricting the possible callers introduces no new obligation for the function. This is the contravariant input rule of function subtyping.The printed trait has generic type invariance, so Scala does not directly permit either parameter-changing assignment. The safe behavior can be exposed using an explicit adapter without changing that trait:
def restrictInput(f: Fun[Base, Base]): Fun[Derived, Base] =
new Fun[Derived, Base] {
def apply(x: Derived): Base = f(x)
}For the unsafe direction, take illustrative classes in which a derived software object has an extra operation:
class Base
class Derived extends Base { def special(): Int = 1 }
val narrow = new Fun[Derived, Base] {
def apply(x: Derived): Base = { x.special(); x }
}
def broadClient(f: Fun[Base, Base]): Base = f(new Base)
// broadClient(narrow) must be rejected.If that substitution were accepted, the client could pass an ordinary base software object to code that calls
special, which that software object does not support. The rejected call is intentional counterexample code, not a promised compilable application. Variance annotations are needed to make sound direct conversions part of the generic trait's declared subtyping relation.[ref]Scala 2.13 variance annotations specification. Variance Annotations: missing annotation is invariant; method-input positions reverse variance
Past exam of the year 1 of the computer science course of the University of Oxford 2021 Imperative programming (resit) 7 b iii Solution by
Codex 0 2026-10-25
Reject the empty string because it has no positive total count to normalize:The support contains each occurring character once, and a character absent from the string gets mass zero. The occurrence counts sum to the nonzero string length, proving normalization. For a separate example, the string
final class DistFromString(s: String) extends FiniteDist[Char] {
require(s.nonEmpty)
private val frequencies =
s.foldLeft(Map.empty[Char, Int]) { (counts, c) =>
counts.updated(c, counts.getOrElse(c, 0) + 1)
}
def getDom: List[Char] = s.toList.distinct
def getProb(c: Char): Double =
frequencies.getOrElse(c, 0).toDouble / s.length.toDouble
}"aba" gives masses and to its two characters. The interpretation follows Scala's Char elements, so it counts UTF-16 code units rather than imposing a separate Unicode-code-point representation. The Double results approximate the corresponding rational probabilities. Past exam of the year 1 of the computer science course of the University of Oxford 2021 Imperative programming (resit) 7 b ii Solution by
Codex 0 2026-10-25
Use a widened interval width, so the arithmetic also handles endpoints near the limits of The support lists every integer in the inclusive interval once. Its cardinality is
Int:final class Uniform(l: Int, u: Int) extends FiniteDist[Int] {
require(l <= u)
private val width = u.toLong - l.toLong + 1L
def getDom: List[Int] = {
val builder = List.newBuilder[Int]
var value = l.toLong
while (value <= u.toLong) {
builder += value.toInt
value += 1L
}
builder.result()
}
def getProb(x: Int): Double =
if (l <= x && x <= u) 1.0 / width.toDouble else 0.0
}width, so assigning each atom mass gives total mass one. The loop counter is also widened, preventing an increment past Int.MaxValue from wrapping to a negative value. Returning the full support takes time and space proportional to its width and can be impractical for a very large interval; the mass query itself is constant-time. The full integer interval has width , which fits Long but not positive Int. Past exam of the year 1 of the computer science course of the University of Oxford 2021 Imperative programming (resit) 7 b i Solution by
Codex 0 2026-10-25
Validate the parameter, and include exactly the outcomes of positive mass:The range test also rejects
final class Flip(p: Double) extends FiniteDist[Boolean] {
require(p >= 0.0 && p <= 1.0)
def getDom: List[Boolean] =
if (p == 0.0) List(false)
else if (p == 1.0) List(true)
else List(false, true)
def getProb(x: Boolean): Double = if (x) p else 1.0 - p
}NaN, since its ordered comparisons are false. At the endpoints one outcome has zero mass and must be omitted from the support; listing both unconditionally would violate the supplied interface contract. For an interior parameter the two masses are positive and sum to one. Past exam of the year 1 of the computer science course of the University of Oxford 2021 Imperative programming (resit) 4 d ii Solution by
Codex 0 2026-10-25
With that display format the output isThe first removal takes the newly prepended left value . The right removal later takes the most recently appended . The next left removal takes the earlier , leaving the ordered sequence . The two equal values are different occurrences, and the displayed order follows the links rather than numerical sorting.
20
10
10
Queue status: [30, 40, 15] Past exam of the year 1 of the computer science course of the University of Oxford 2021 Imperative programming (resit) 4 d i Solution by
Codex 0 2026-10-25
Add this method inside the concrete class:Its precondition is a valid receiver, including an empty one. Its postcondition leaves and prints the entries of from left to right in the displayed bracket format, followed by a newline. The loop invariant says that the printed entries are precisely the chain before
def display: Unit = {
print("[")
var current = first
var separator = ""
while (current != null) {
print(separator)
print(current.datum)
separator = ", "
current = current.next
}
println("]")
}current; the not-yet-printed entries are the chain starting there. Advancing along the acyclic chain terminates after its length. Printing changes the output stream, but it changes neither links nor payloads. Past exam of the year 1 of the computer science course of the University of Oxford 2021 Discrete mathematics, continuous mathematics, and probability 9 b iv Solution by
Codex 0 2026-10-25
For , the success probability is , and the definition of conditional expectation on an event givesThereforeAt the value is zero because the trial has already ended. At the left absorbing state , conditioning on success would be undefined because it has zero probability. The formula concerns the successful trajectories, so it need not equal the unconditional mean .
Past exam of the year 1 of the computer science course of the University of Oxford 2021 Discrete mathematics, continuous mathematics, and probability 9 b iii Solution by
Codex 0 2026-10-25
Write and . Since , the latter expected value is finite. Conditional on the first move to or , total time is one plus the remaining time, while the terminal success indicator random variable is unchanged. The Markov property and linearity of expectation giveAt either absorbing boundary the remaining time is zero, so .
Let . The linear term has zero second difference and has second difference . Consequentlywhich is exactly the required recurrence, and . Uniqueness follows as before: the difference of two solutions has zero second difference and zero endpoint values. HenceThis is the success-weighted duration underlying the duration of gambler's ruin conditioned on a chosen boundary.
Past exam of the year 1 of the computer science course of the University of Oxford 2021 Discrete mathematics, continuous mathematics, and probability 9 b ii Solution by
Codex 0 2026-10-25
Let . Time is accumulated in each transient chamber before the next move; arrival at either terminal state ends the trial immediately. Thus . A block of identical rightward choices forces absorption, so the geometric tail bound from a uniform escape probability gives finite expected value of .
First-step analysis now givesThe quadratic has the correct boundary values and second difference , so it solves this system. The difference of two solutions would be linear in with zero values at both endpoints, hence zero. ThereforeThis is the expected duration of symmetric gambler's ruin. It includes the first minute in the starting transient chamber and does not add a minute after absorption.
Past exam of the year 1 of the computer science course of the University of Oxford 2021 Discrete mathematics, continuous mathematics, and probability 9 b i Solution by
Codex 0 2026-10-25
The expected value of an indicator random variable is the probability of its event. For a simple symmetric random walk absorbed at , the gambler's ruin success probability from is . HenceThe boundary values are at the left exit and at chamber .
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





