The set is countable, hence closed, and does not contain . Its complement is an open neighborhood of . Convergence therefore places every sufficiently late term outside , which is possible only if those terms equal . Thus the sequence is eventually constant at its limit, and the set of exceptional indices is finite. This conclusion concerns repeated indices as well as distinct values.
A sequence converges to if every open neighbourhood of contains all sufficiently late terms. A Hausdorff space separates any two distinct points by disjoint open neighbourhoods.
If a sequence had distinct limits in a Hausdorff space, choose disjoint open neighbourhoods of and of . Convergence to each limit implies that all sufficiently late terms lie in both and , contradicting . Hence a convergent sequence in a Hausdorff space has a unique limit.
does not have sequential compactness. Take the sequenceEvery subsequence has usual limit of a sequence . If a subsequence converged in the subspace topology of the Sorgenfrey line, it would also converge in the usual subspace topology, since part (c) makes the identity function from the former to the latter continuous. Uniqueness of a limit of a sequence in the usual Hausdorff space therefore forces that limit of a sequence to be .
But is an open neighbourhood of in , and no term belongs to it. Thus no subsequence converges to in , proving the assertion.
Let , and choose in each circle the point opposite :In the subspace topology from the Euclidean plane, the sequence converges to , which does not belong to . Thus is not closed in .
On the other hand, let . With the quotient map from part (i),This is closed in : its complement is the open set . The definition of the quotient topology, applied to complements, says that is closed in . A homeomorphism would carry this closed set to the closed set , a contradiction. Therefore is not a homeomorphism.
The obstruction occurs at the common point. The open set contains the collapsed point, but its image contains no neighbourhood of , since . The wedge sum topology allows a separate small neighbourhood on each circle; a neighbourhood of in the Hawaiian earring must contain all sufficiently small whole circles.
Use two indices, initially the first and last positions of the ordered sequence. The two elements occupy distinct positions, so continue only while
i < j:i := 0; j := n-1;
WHILE i < j DO
t := S[i] + S[j];
IF t = x THEN RETURN TRUE
ELSIF t < x THEN i := i+1
ELSE j := j-1
END
END;
RETURN FALSEThe loop invariant is: a solution exists in the original input if and only if one exists with both indices in
[i,j]. If S[i]+S[j] < x, then S[i]+S[k] <= S[i]+S[j] < x for every k <= j, so index i cannot belong to a remaining solution. If the sum is too large, S[k]+S[j] >= S[i]+S[j] > x for every k >= i, so index j cannot belong to one. This proves preservation of the loop invariant. Equality gives the desired pair, and an interval with fewer than two positions contains none.Every unsuccessful iteration decreases the loop variant
j-i by one, so there are at most sum comparisons and only constant space is needed. Duplicate values are permitted if they occupy distinct positions. Under exact constant-cost real arithmetic and endpoint access,The continuous nonalgebraic unit interval isEvery nonempty directed set has a least upper bound by completeness of the real numbers, and that least upper bound lies in . Thus this is a directed-complete partial order.
For , we have . Indeed, if and no were at least , then would be an upper bound for , implying , a contradiction. If , the singleton directed set excludes . If , the increasing sequence , , has least upper bound and has no member at least , so .
Under the usual nonempty convention, . Therefore the elements way-below form , and those way-below form . These are directed sets with least upper bounds and , respectively, proving that is a continuous directed-complete partial order. Its only compact element is . For any , the compact elements below have least upper bound , rather than , so it is not an algebraic partially ordered set.
Under the literal empty-set convention of the paper, as well. The elements way-below zero then form the empty set, which is directed in that convention and has least upper bound zero. There are no compact elements, and their empty set still fails to approximate any positive . Thus both conventions give the same requested classification:
Use an abstract finite sequence of integers, initially empty. In the following trait, comments are the mathematical specification; means the abstract state on entry, and The postcondition of
result means the returned value.trait ReversableBuffer {
// Abstract state s: finite sequence of Int, initially [].
// Pre: true. Post: s = s0 ++ [x].
def append(x: Int): Unit
// Pre: true. Post: s = [x] ++ s0.
def prepend(x: Int): Unit
// Pre: 0 <= i < length(s0).
// Post: result = s0 !! i,
// s = take i s0 ++ drop (i+1) s0.
def get(i: Int): Int
// Pre: true. Post: s = reverse(s0).
def rev: Unit
}get includes removal: it is not merely indexed reading. In particular,Repeated equal values elsewhere in the sequence remain present. List concatenation, indexing and list reversal in the specification describe abstract behavior without committing to a physical representation.Use a doubly linked list, store both physical endpoints and its length, and maintain a flag for lazy reversal of a doubly linked list. This makes endpoint insertion and reversal constant time. Finding an arbitrary indexed element takes a traversal from whichever physical endpoint is nearer.Define to be the sequence of values obtained by starting at
class LLBuffer extends ReversableBuffer {
private class Node(val value: Int) {
var prev: Node = null
var next: Node = null
}
private var first: Node = null
private var last: Node = null
private var size = 0
private var backwards = false
// Methods from (ii) go here.
}first and repeatedly following next until null. The representation invariant says that size is nonnegative; size == 0 holds exactly when both endpoints are null; otherwise there are exactly size distinct reachable linked list nodes, the final one is last, first.prev == null, last.next == null, and all neighboring links are reciprocal. These conditions make finite and the physical linked list acyclic. The abstraction function isThe flag does not change the representation invariant. An empty physical linked list represents the empty sequence for either flag value. No client receives a linked list node reference, so clients cannot invalidate its links.Physical doubly linked list order and logical sequence order under lazy reversal of a doubly linked list
. Details. Keep a running total in the mixin, and use only the inherited public operations. Updating after a successful superclass operation leaves the total unchanged if an empty For this trait mixed directly into
pop fails its precondition.trait SumPlugin extends Stack {
private var total = 0
override def push(x: Int): Unit = {
super.push(x)
total += x
}
override def pop(): Int = {
val x = super.pop()
total -= x
x
}
def sum: Int = total
}Stack, its representation invariant is , where is the abstract stack sequence. A successful push adds exactly its argument and a successful pop removes exactly its returned value. ThusThe mixin reads no private Stack fields. Its operations add constant time complexity. As in the paper's Int interface, an unbounded mathematical total requires excluding integer overflow, or replacing the accumulator with BigInt if the interface is allowed to change. A later mixin can transform a pushed value at a different point in the Scala trait linearization; the effect is analyzed in the next part.These operations consume the receiver, as expected for this destructive iterator interface. For
exists stops immediately after the first successful test.trait RichIter[T] extends Iter[T] {
def foreach(f: T => Unit): Unit = {
while (hasNext) f(next())
}
def exists(p: T => Boolean): Boolean = {
while (hasNext) {
if (p(next())) return true
}
false
}
def foldLeft[U](x: U)(f: (U, T) => U): U = {
var acc = x
while (hasNext) acc = f(acc, next())
acc
}
}foreach, after iterations the supplied function has been applied in order to exactly the first entries. For exists, every consumed entry has failed the predicate unless the method is returning true. For the left fold, the loop invariant after consuming entries isEach iteration extends the expression by the next entry on the right. For a finite remaining sequence, its unconsumed length is a common loop variant. ThusAn empty iterator invokes no callback, gives false for exists, and returns from the left fold. On an infinite iterator, exists can terminate when it finds a match; the other two operations ordinarily do not terminate. With constant-cost callbacks, finite input of length takes time complexity and constant auxiliary space.A simple current-value implementation works when is a pure function, but sharing a mutable closure between copies would violate the independence requirement used in part (d). Use a memoized successor chain for stateful iterator copies: the generated sequence has shared cells, and each iterator has its own current-cell pointer.The representation invariant is that
object FunIter {
final class Cell[T](val head: T, f: T => T) {
lazy val tail: Cell[T] = new Cell[T](f(head), f)
}
}
class FunIter[T](v: T, f: T => T) extends Iter[T] {
private var cursor = new FunIter.Cell[T](v, f)
def hasNext: Boolean = true
def next(): T = {
val x = cursor.head
cursor = cursor.tail
x
}
def copy(): Iter[T] = {
val result = new FunIter[T](cursor.head, f)
result.cursor = cursor
result
}
}cursor points to the next cell to be returned, and each cell's lazy tail is computed at most once. The abstraction function is the infinite sequence of heads starting at that cell. Advancing changes only this iterator's pointer. A copy starts at the same cell, so both observe the same remaining heads even when their calls are interleaved:For a stateful , the generator state must be privately owned by this shared chain; unrelated external calls to must not change it. As usual, the values and transition must allow successive results to be observed without externally mutating old results. No interface can independently clone the hidden state of an arbitrary externally mutated closure from its function type alone. The chain avoids needing such cloning: a lagging copy reuses the already generated future instead of invoking again.After the first update, the sequence lies in and is nonincreasing. The monotone convergence theorem for sequences gives a limit . The update is continuous on this interval, so passing to the limit givesPositivity forces . If an iterate reaches the root exactly, the constant tail gives the same conclusion. The Exact Newton error identity for a quadratic here is , also showing quadratic convergence once the error is small.
Follow the next reference for the desired level, stopping at the tail. This returns the genuine nodes in their linked list order, excluding both sentinel nodes.Write for the resulting sequence of nodes at level . The abstraction function isIt preserves repetitions, because distinct nodes may carry equal values. A suitable representation invariant requires the following:
def nodesAt(level: Int): List[Node] = {
require(0 <= level && level < NumLevels)
val out = scala.collection.mutable.ListBuffer.empty[Node]
var n = head.nexts(level)
while (n ne tail) {
out += n
n = n.nexts(level)
}
out.toList
}headandtailare distinct sentinel nodes with the specified extreme values; every node has anextsarray of lengthNumLevels.- For each level, following references from
headgives a finite acyclic chain ending attail, thennull; the data along that chain are nondecreasing. Genuine values lie strictly between the sentinel values. - Each is a subsequence of by node identity, so the relative order of equal-valued nodes agrees across levels. Every genuine node occurs in and on a contiguous initial collection of levels.
- A genuine node absent from a level has
nullin that level's slot. Tail slots are allnull; every other slot on a chain points to the next member of that chain.
Interpret After calls to
step as a positive increment, consistent with the increasing sequence and exclusive upper bound. State this precondition explicitly; a zero increment would not define the intended finite progression. Use a wider cursor to avoid integer overflow on the update after the last valid Int result.class RangeIter(lower: Int, upper: Int, step: Int) extends Iter[Int] {
require(step > 0)
private var current = lower.toLong
def hasNext: Boolean = current < upper.toLong
def next(): Int = {
require(hasNext)
val answer = current.toInt
current += step.toLong
answer
}
}next, the abstraction function is the sequence of values with , in increasing order. Repeated calls to hasNext do not change it; next removes precisely its first value. ThereforeIf lower >= upper, the represented sequence is empty immediately. The paper does not specify a descending-range convention; this implementation exposes its positive-step precondition rather than assigning one implicitly.A demand-driven filtering iterator needs one cached accepted value. Otherwise The representation invariant says that
hasNext would either lose an element or consume another accepted value every time it is queried.def filterIter[T](p: T => Boolean, it: Iter[T]): Iter[T] =
new Iter[T] {
private var buffered: Option[T] = None
private var finished = false
private def fill(): Unit = {
while (buffered.isEmpty && !finished) {
if (!it.hasNext) finished = true
else {
val x = it.next()
if (p(x)) buffered = Some(x)
}
}
}
def hasNext: Boolean = {
fill()
buffered.nonEmpty
}
def next(): T = {
fill()
require(buffered.nonEmpty)
val answer = buffered.get
buffered = None
answer
}
}buffered holds at most one accepted value. The represented sequence is the buffered value, if present, followed by the subsequence of the underlying remainder satisfying the predicate. Filling moves the next accepted value into the cache and discards only rejected values, so this abstract sequence is unchanged by hasNext. Clearing the cache in next removes its head. Thusnext works even when the client has not first called hasNext; exhaustion violates its stated precondition. As with ordinary iterator adapters, clients should give this wrapper exclusive consumption of it, and the predicate should give a stable answer for each element. One call may scan several rejected elements, but across a complete traversal each source element is consumed once. Cache storage is constant.Store characters in a mutable dynamic array. Its length is maintained by the collection, giving constant-time The representation invariant requires a nonnull private dynamic array containing a finite sequence of characters, with its internal collection invariant maintained by the library. The abstraction function isInsertion allows the end position and shifts the suffix right; deletion returns exactly the removed character and shifts the suffix left.
size.class DocImpl extends Doc {
private val text = scala.collection.mutable.ArrayBuffer.empty[Char]
def insert(x: Char, pos: Int): Unit = {
require(0 <= pos && pos <= text.length)
text.insert(pos, x)
}
def delete(pos: Int): Char = {
require(0 <= pos && pos < text.length)
text.remove(pos)
}
def read(pos: Int): Char = {
require(0 <= pos && pos < text.length)
text(pos)
}
def size: Int = text.length
}read leaves the abstract state unchanged. size equals the abstract sequence length in time complexity. Indexed reads are also constant time; insertion and deletion may take linear time, which the question permits.For a nonzero geometric sequence, substitute into the linear recurrence and cancel :The characteristic equation of a linear recurrence therefore has rootsThe zero sequence is a degenerate solution for any for which the displayed expression is defined. A nonzero sequence with cannot satisfy the recurrence at , since it would require .
The initial values of the two sequences agree: and . For , use the first-order recurrence relation at and :Therefore satisfies exactly the same derangement recurrence as . By strong induction, equality of the preceding two terms implies equality of the next term. ConsequentlyThe first-order recurrence relation therefore also counts derangements.
Use a history dynamic array and a cursor between elements. If the cursor is behind the history's end, The representation invariant is , with history exactly the prefix already consumed from the original source. The logical unread sequence is the history suffix starting at
next replays history; otherwise it pulls a new element from the source. prev moves the cursor left and returns the element crossed, so prev followed by next returns the same element twice and restores the cursor.def genBiIter[T](it: Iter[T]): BiIter[T] = new BiIter[T] {
private val history = scala.collection.mutable.ArrayBuffer.empty[T]
private var pos = 0
def hasPrev: Boolean = pos > 0
def hasNext: Boolean = pos < history.length || it.hasNext
def next(): T = {
if (pos < history.length) {
val v = history(pos); pos += 1; v
} else if (it.hasNext) {
val v = it.next()
history += v; pos += 1; v
} else {
throw new NoSuchElementException("BiIter.next")
}
}
def prev(): T = {
if (!hasPrev) throw new NoSuchElementException("BiIter.prev")
pos -= 1
history(pos)
}
}pos, followed by the source's remaining sequence. The logical backward history is the prefix before pos. Every operation preserves this model, including alternating backward and forward moves after source exhaustion.This bidirectional iterator uses storage after consuming distinct source elements. Replay and backward moves take constant time; appending has amortized time complexity under the usual dynamic array model. The input iterator must not be advanced separately.