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 2014 Digital systems, linear algebra, introduction to formal proof 3 c Solution by
Codex 0 2026-10-31
Use a synchronous counter cascade, with the three-bit modulo-six counter advancing on every active clock edge and the Gray-code counter advancing only when the old binary state is . Its enable can therefore beOn the six valid binary states, only at . Both digital counters sample the same clock: at an edge leaving , the binary output becomes and simultaneously advances to the next Gray code. At all other edges holds. Starting from , this gives exactly the listed 24-state sequence. Use the shared clock and an enable, rather than making a combinational terminal-state signal into a new clock.[ref]
Digital systems, linear algebra, introduction to formal proof examination paper by the University of Oxford (2014). Question 3(c), printed page 4: original 24-row state/output table
For the output , every state with has . For , the only extra high states are with binary state , and with binary state or . On valid states these conditions are and , respectively. HenceThe lower circuit in the figure implements this with an AND for , an exclusive or on , an AND with , and an OR with . The resulting Morse code output blocks, in Gray code order , areAcross the two middle blocks these join to three three-clock highs separated by one-clock lows; the first and last blocks provide the three single-clock highs of each S. The specified table is a repeating SOS symbol pattern; its wraparound has a one-clock low, rather than an added inter-message pause. The output is a Moore machine decoding of current stored bits; its value changes after those bits settle.
Past exam of the year 1 of the computer science course of the University of Oxford 2014 Digital systems, linear algebra, introduction to formal proof 3 b Solution by
Codex 0 2026-10-31
Let the stored bits be , with most significant. The required Gray code transitions giveConnect directly to the first D flip-flop's data input and feed through one NOT gate to the second input. Drive both enable inputs with and both clock inputs with the same clock. Thus holds both stored bits; takes the next Gray-code counter state at the active clock edge. Reset initializes .
With ordinary uncomplemented outputs, one NOT gate is minimal: wiring alone cannot produce . If a D flip-flop already provides a complementary output, that output supplies the inversion without an external logic gate. This is a Moore machine because its output depends only on stored state; controls transitions.
Past exam of the year 1 of the computer science course of the University of Oxford 2014 Digital systems, linear algebra, introduction to formal proof 3 a Solution by
Codex 0 2026-10-31
Use three D flip-flops whose stored bits represent . Initialize them to . The Moore machine's output is this stored binary representation, and its state transition table is:
| Present | Next |
|---|---|
Treat the two unused state encodings as don't-care conditions when minimizing the sum of products. With juxtaposition for AND, for OR and a bar for NOT, one minimal choice isFor , the required ones at and cannot share one valid implicant: their differing bits would force inclusion of required zeros. Pair with the unused to get , and with unused to get . Neither term can lose a Boolean literal without covering a required zero.
For , state is isolated from every other required one and from the unused states by required zeros, so it forces the three-Boolean literal term . State pairs with unused to give . Finally is a single Boolean literal. Thus the three expressions are minimal sum of products expressions under the stated unused-state convention. In fact these choices also recover from , so initialization into an unused state eventually joins the intended modulo-six counter cycle.
Past exam of the year 1 of the computer science course of the University of Oxford 2014 Digital systems, linear algebra, introduction to formal proof 2 f Solution by
Codex 0 2026-10-31
With a resident inode, the deepest allowed path uses two address blocks and one file data block, so every byte through the end of the doubly indirect region meets the three-read bound. There are ten directly addressed file data blocks, 512 singly addressed ones and doubly addressed ones. Therefore the largest contiguous file satisfying this bound isThe next byte requires the triply indirect region, with three address-block reads and a fourth read for the file data block.
The resident-inode convention is essential. If the question's three reads must also include fetching a previously uncached inode, only two further reads remain; the maximum is thenNeither figure includes arbitrary pathname-resolution reads. These are worst-case counts in the traditional fully allocated multilevel inode indexing model; existing buffer cache entries can reduce them.
Past exam of the year 1 of the computer science course of the University of Oxford 2014 Digital systems, linear algebra, introduction to formal proof 2 d Solution by
Codex 0 2026-10-31
An access control list is attached to an object, such as a file, and lists which subjects or groups may perform which operations. Access requires checking the requesting identity against that object's list. A security capability is an unforgeable reference to an object carrying specified rights; possessing valid authority is what permits access. Protected storage or another integrity mechanism must prevent users manufacturing stronger security capabilities.
The traditional Unix owner/group/other read-write-execute permissions are a compact, restricted access control list: the inode records the owner, group and permission bits, and the operating system compares these against the caller's credentials.An already-open file descriptor can behave like a limited handle carrying rights, but that does not change the identity-based nature of the initial pathname permission check.
Past exam of the year 1 of the computer science course of the University of Oxford 2014 Digital systems, linear algebra, introduction to formal proof 2 c Solution by
Codex 0 2026-10-31
A traditional inode uses a fixed number of direct pointers to file data blocks, followed by singly, doubly and sometimes triply indirect block pointers. A singly indirect block pointer reaches one address block whose entries point to file data blocks. A doubly indirect block pointer reaches a block of pointers to singly indirect address blocks; a triply indirect one adds another level. The file data blocks need not be physically contiguous.
This multilevel inode indexing keeps the inode compact. A small file uses direct pointers without allocating address blocks, while a large file allocates deeper address blocks only as needed. If each address block holds addresses, the successive levels cover file data blocks. The logical file offset selects a path arithmetically, so random access does not require walking through all preceding file data blocks.
Past exam of the year 1 of the computer science course of the University of Oxford 2014 Digital systems, linear algebra, introduction to formal proof 2 b Solution by
Codex 0 2026-10-31
An inode holds file metadata: object type, owner and group identities, access permissions, file size, access/modification/status-change timestamps, and the hard link count. It also holds the information locating the contents, traditionally direct addresses and indirect block pointers. Device-special files instead need device-identifying information. The file's name and parent pathname belong to directory entries, not to the ordinary inode.
Past exam of the year 1 of the computer science course of the University of Oxford 2014 Digital systems, linear algebra, introduction to formal proof 2 a Solution by
Codex 0 2026-10-31
Names live in directory entries. Each ordinary directory entry associates a component name with an inode number; the corresponding inode describes the file and locates its contents. A name is therefore not stored as the identity of the inode, and hard links can give one inode several names.
To resolve
/var/mail/user, start from the root file-system directory's inode, read its directory entries and find var. Follow that entry's inode number to the var inode; read that file-system directory and find mail; repeat for user. The final inode supplies the file metadata and addresses needed to read the file data blocks. The intermediate file-system directories require search permission. This describes ordinary pathname traversal without a symbolic link or mount point changing the route. Past exam of the year 1 of the computer science course of the University of Oxford 2014 Digital systems, linear algebra, introduction to formal proof 1 b Solution by
Codex 0 2026-10-31
Add zero extension alongside sign extension, and a multiplexer controlled by a new signal
ExtSign to select between them before the existing immediate-input connection. Equivalently, make the extender itself selectable:Decode ori to ExtSign=0, RegDst=0, ALUSrc=1, RegWrite=1 and ALUFunc=OR. The arithmetic logic unit then performs bitwise OR between and the zero-extended immediate operand and writes the result to . Extend the arithmetic logic unit's control decoding if OR was not already available. Decode addi to ExtSign=1; the new signal is irrelevant for MIPS R-type instructions because ALUSrc=0.Zero extension matters even when the most significant immediate bit is one:
ori with 0x8000 must only affect the low half of the destination, whereas sign extension would incorrectly force every high bit to one.[ref]MIPS32 Architecture For Programmers Volume II by MIPS Technologies. ORI instruction entry: the 16-bit immediate is zero-extended before the logical operation
Past exam of the year 1 of the computer science course of the University of Oxford 2014 Digital systems, linear algebra, introduction to formal proof 1 a Solution by
Codex 0 2026-10-31
A MIPS R-type instruction has the 32-bit instruction encodingFor
add $x,$y,$z, the processor register indices are , and , while . The main opcode selects the R-type family and the function field selects addition. The register file reads its two operands from instruction bits 25:21 and 20:16. In the original datapath, RegDst=1 selects bits 15:11 as the destination, ALUSrc=0 selects the second register file output, and ALUFunc=ADD makes the arithmetic logic unit add its inputs. The result returns to wdata; RegWrite=1 writes it to at the active clock edge. The zero output is irrelevant here.[ref]Digital systems, linear algebra, introduction to formal proof examination paper by the University of Oxford (2014). Question 1 datapath, printed page 2: the input-0 and input-1 multiplexer labels determine these control polarities
A MIPS I-type instruction instead has the instruction encodingFor
addi $x,$y,n, , , and the low sixteen bits contain the immediate operand. The register file supplies to the first arithmetic logic unit input. Set RegDst=0 to select bits 20:16 for the destination, and ALUSrc=1 to select the extended immediate operand for the second input. The opcode directly requests addition, so ALUFunc=ADD and RegWrite=1. The second register file read is unused. The returned result is written into .The sign extension circuit retains the low sixteen bits and copies bit 15 into all sixteen new high positions:Thus sign extension preserves the signed two's complement value:
0x7fff becomes 0x00007fff, whereas 0x8000 becomes 0xffff8000. For both instructions, the architectural result above assumes no signed overflow; the full MIPS architecture specifies an overflow exception, which is outside this simplified datapath. Past exam of the year 1 of the computer science course of the University of Oxford 2013 Imperative programming 8 d Solution by
Codex 0 2026-10-31
Use an upper type bound requiring each element type to implement the supplied comparison interface for its own type. This is F-bounded polymorphism.Use this locally defined
trait Ordered[T] {
def <(that: T): Boolean
}
class MinSet[T <: Ordered[T]](contents: List[T])
extends Set[T](contents) {
def min: T = {
require(elems.nonEmpty)
var best = elems.head
var rest = elems.tail
while (rest.nonEmpty) {
if (rest.head < best) best = rest.head
rest = rest.tail
}
best
}
}Ordered, rather than silently substituting the standard library's different comparison interface. The type bound makes rest.head < best well typed. To interpret the result as a minimum, require the comparison to be a consistent strict total order; merely providing a method named < cannot establish its mathematical laws.The loop invariant is that
best is a minimum among the entries already inspected, and rest is exactly the uninspected suffix. Comparing its next head with best preserves that property. The loop variant is the length of rest. On termination,The method leaves the set unchanged, takes time complexity under constant-cost comparisons, and uses constant auxiliary space. It requires a nonempty set; inherited insertion and deletion continue to preserve the duplicate-free representation invariant. Past exam of the year 1 of the computer science course of the University of Oxford 2013 Imperative programming 8 c Solution by
Codex 0 2026-10-31
An immutable object can widen its element type when adding a value by returning a new object. Introduce a lower type bound on the method's fresh type parameter.As before, the representation invariant excludes duplicates, and the abstraction function returns the unordered set of entries. The constructor normalization makes the representation invariant hold even for repeated initial entries. Both operations construct a fresh set object and leave the original object unchanged, including when addition finds an existing member.
class ISet[+T](contents: List[T]) {
private val elems: List[T] = contents.distinct
def add[U >: T](x: U): ISet[U] = {
val widened: List[U] = elems
if (widened.contains(x)) new ISet[U](widened)
else new ISet[U](x :: widened)
}
def delete(): (T, ISet[T]) = {
require(elems.nonEmpty)
(elems.head, new ISet[T](elems.tail))
}
}For a receiver representing , the new object returned by
add represents . Deletion returns a pair with and representing . Crucially,The widened list is valid because immutable List itself has a covariant type parameter. A client can view an ISet[Int] as ISet[Any], but adding a string creates a separate widened result; it cannot put a string into the old integer set. This explains how using immutable objects makes the desired type variance sound. A direct add(x: T) on a covariant software class would still violate the variance-position rule; immutability alone does not repair an incorrectly typed method signature. Past exam of the year 1 of the computer science course of the University of Oxford 2013 Imperative programming 8 b Solution by
Codex 0 2026-10-31
If the mutable set were allowed a covariant type parameter, both variables below could refer to the same mutable object:The broad view accepts any value, including a string. The narrow view still promises that deletion returns an
val s1: Set[Int] = new Set[Int](List())
val s2: Set[Any] = s1 // hypothetically permitted
s2.add("not an integer")
val n: Int = s1.delete() // cannot return an IntInt, yet the sole stored value is that string. This violates type safety:This is covariance failure for a mutable collection. The input occurrence in add(x: T) conflicts with the positive occurrence in the result of delete. Keeping a generic type invariance restriction prevents the unsafe aliasing. The example uses an initially empty set so that the problematic deletion result is forced. Past exam of the year 1 of the computer science course of the University of Oxford 2013 Imperative programming 8 a Solution by
Codex 0 2026-10-31
Represent the set by a private list containing each value once. Normalize the constructor input as well as checking future insertions; otherwise duplicate initial entries would violate the intended set behavior.The representation invariant is that
class Set[T](contents: List[T]) {
protected var elems: List[T] = contents.distinct
def add(x: T): Unit = {
if (!elems.contains(x)) elems = x :: elems
}
def delete(): T = {
require(elems.nonEmpty)
val x = elems.head
elems = elems.tail
x
}
}elems contains no duplicates under the chosen stable value equality; the abstraction function forgets its ordering and returns its set of elements. The protected field allows the subclass in part (d) to inspect its contents; that subclass is responsible for preserving the representation invariant if it mutates them.Insertion makes the represented set . Deletion requires , returns some , and leaves . ThusDeletion does not promise to choose a minimum. With this linked list representation, insertion takes time complexity because of its membership check, while deletion takes . Values should not mutate in a way that changes their equality while stored.
Past exam of the year 1 of the computer science course of the University of Oxford 2013 Imperative programming 7 d Solution by
Codex 0 2026-10-31
Use double dispatch. Each original overload first sends a dynamically dispatched message to its argument. The argument's selected body then calls an overloaded receiver method with All three
this, whose static type inside that body is the desired argument software class.class X {
def sendTo(m: M): String = m.receive(this)
}
class Y extends X {
override def sendTo(m: M): String = m.receive(this)
}
class Z extends Y {
override def sendTo(m: M): String = m.receive(this)
}
class M {
def f(x: X): String = x.sendTo(this)
def f(x: Y): String = x.sendTo(this)
def receive(x: X): String = "f with X at M"
def receive(x: Y): String = "f with Y at M"
def receive(x: Z): String = "f with Z at M"
}
class N extends M {
override def f(x: Y): String = x.sendTo(this)
def f(x: Z): String = x.sendTo(this)
override def receive(x: X): String = "f with X at N"
override def receive(x: Y): String = "f with Y at N"
override def receive(x: Z): String = "f with Z at N"
}receive overloads must be declared in M, because sendTo receives a parameter with static type M. Declaring the Z version only in N would repeat the original problem.Whatever original The result depends on both runtime types:For the stated
f signature is selected, it invokes sendTo on the actual argument. For a Z object, dynamic dispatch enters Z.sendTo; inside that body, this has static type Z, so method overloading selects receive(Z). The final call dynamically dispatches on the actual m, giving N.receive(Z) when m refers to N. Hencef with Z at N
f with Z at N
f with Z at NX, Y, Z hierarchy, the same construction reports each argument software class correctly for either receiver software class. Further subclasses would need their own dispatch protocol to distinguish additional runtime types. Past exam of the year 1 of the computer science course of the University of Oxford 2013 Imperative programming 7 c Solution by
Codex 0 2026-10-31
Method overloading chooses a signature using the static types available at the call site. The receiver
m has static type M, whose visible overloads accept X and Y; the Z overload introduced only in N is not a candidate.For Equivalently,The runtime type of every argument is
m.f(x), the argument's static type is X, so the chosen signature is f(X). N does not override it, and the inherited M body runs. For m.f(y), the chosen signature is f(Y), and dynamic dispatch on the receiver chooses N's override. For m.f(z), both visible signatures apply, but f(Y) is more specific than f(X). Dynamic dispatch again chooses N.f(Y). Thusf with X at M
f with Y at N
f with Y at NZ, but ordinary single-receiver dynamic dispatch does not redo method overloading using that runtime type. This is overload selection followed by dynamic dispatch. 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






