Let be the time of the second occurrence of , whether or not it is adjacent to the first. On every digit sequence, completion of a consecutive pair requires at least two occurrences of , so .
The waiting time for the first has mean . Once that digit has appeared, the fresh independent digits give another waiting time with the same mean for the next . Thus , the mean of the corresponding negative binomial distribution. Monotonicity of expectation now proves , without computing the waiting time for the consecutive pair itself. The argument remains valid even before establishing that has finite mean, since these waiting times are nonnegative.
There is no forbidden pair in a sequence of length zero or one, so . For , divide acceptable sequences into two disjoint cases. If the first digit differs from , its probability is , and the remaining independent digits must avoid the pair. If the first digit is , the next must differ from , which has combined probability , and the remaining digits must avoid the pair. The boundary between this prefix and the remaining digits cannot create a forbidden pair, because the prefix ends in a digit other than . Consequently
The characteristic polynomial of a linear recurrence is , with distinct roots
Writing , the initial conditions give and . Therefore
For example, , since only one of the nine equally likely pairs is forbidden. This is the case with success probability of the avoidance recurrence for two consecutive successes.
Maintain the two largest entries of each segment, counting repeated values as separate entries. A singleton returns its value and a sentinel for its missing runner-up. Split a longer segment into two nonempty halves, recursively obtain and , and combine them by
For example, an implementation on an indexed sequence can use:
top2(lo, hi):
    if hi-lo == 1: return (a[lo], -infinity)
    mid = (lo+hi)//2
    (mL,sL) = top2(lo,mid)
    (mR,sR) = top2(mid,hi)
    if mL >= mR: return (mL, max(sL,mR))
    else:        return (mR, max(mL,sR))
The result is top2(0,n). The global maximum is one of the two child maxima. Once its side is identified, the global second maximum is either that side's runner-up or the other side's maximum; the displayed formula exhausts these possibilities. This proves the divide-and-conquer algorithm by induction on segment length. There are leaves and constant-cost combinations, so its time complexity is , with recursive stack space for balanced splits. A Maybe value can replace the formal sentinel for a generic ordered element type. If both largest entries are equal, both are returned; a second distinct value is a different specification.
The abstract FIFO queue state is a finite sequence , initially empty. Because the interface returns Int length, use the representable-size model . Its operations are:
trait Queue[A] {
  // State q: finite sequence of A; initially [].
  // Pre: length(q) < Int.MaxValue. Post: q = q0 ++ [x].
  def enqueue(x: A): Unit

  // Pre: q is nonempty. Post: return head(q0); q = tail(q0).
  def dequeue(): A

  // Post: q = [].
  def clear(): Unit

  // Post: q unchanged; return q.isEmpty.
  def isEmpty: Boolean

  // Post: q unchanged; return length(q).
  def length: Int
}
The unchanged-state clauses on the two queries are part of their postconditions. dequeue removes exactly the oldest remaining element, while clear discards all entries regardless of the old state. The size bound can be omitted in an unbounded mathematical model, but it must be reconciled with fixed-width lengths in an implementation.
Keep a head, a tail and a cached length:
private var first: QueueNode = null
private var last: QueueNode = null
private var size = 0
The representation invariant requires and a finite acyclic null-terminated linked list of exactly size nodes starting at first. When size == 0, both endpoints are null. Otherwise last is precisely the final reachable node and last.next == null.
The abstraction function maps the chain from first to last to its payload sequence. Initially all pointers are null and the cached size is zero, giving the empty abstract queue. A tail pointer makes append constant-time; the cached size makes the length query constant-time without traversing the chain.
Use the trait and node definition above. The reference to a “stack” in this part is a wording error: the declared class and operations implement a FIFO queue.
class ListQueue extends Queue[Int] {
  private var first: QueueNode = null
  private var last: QueueNode = null
  private var size = 0

  def enqueue(x: Int): Unit = {
    require(size < Int.MaxValue, "queue size limit")
    val fresh = new QueueNode(x, null)
    if (last == null) first = fresh
    else last.next = fresh
    last = fresh
    size += 1
  }

  def dequeue(): Int = {
    require(first != null, "empty queue")
    val answer = first.value
    first = first.next
    size -= 1
    if (first == null) last = null
    answer
  }

  def clear(): Unit = {
    first = null
    last = null
    size = 0
  }

  def isEmpty: Boolean = size == 0
  def length: Int = size
}
Appending links the fresh node after the old tail, or establishes both endpoints when empty. Removing the head preserves the tail unless the final node was removed, in which case both endpoints become null. Clearing only discards the endpoint references; it need not visit or overwrite unreachable nodes. Thus all operations are in the usual pointer-operation/allocation cost model, with later garbage collection excluded from an individual operation's bound. The representation invariant and abstraction function show the specified sequence changes, including empty/singleton transitions.
A mutable character buffer supplies a cached length and constant-time indexed access:
class DocImp extends Doc {
  private val data = scala.collection.mutable.ArrayBuffer.empty[Char]

  def insert(pos: Int, ch: Char): Unit = {
    require(0 <= pos && pos <= data.length)
    require(data.length < Int.MaxValue)
    data.insert(pos, ch)
  }

  def delete(pos: Int): Char = {
    require(0 <= pos && pos < data.length)
    data.remove(pos)
  }

  def apply(pos: Int): Char = {
    require(0 <= pos && pos < data.length)
    data(pos)
  }

  def length: Int = data.length
}
The representation invariant is that data is a well-formed private dynamic array of at most Int.MaxValue characters. Its abstraction function is the buffer's character sequence. Initialization is empty; insertion and removal at the checked position implement exactly the required sequence edits, and the queries do not modify it.
length and indexing are because a dynamic array stores its used length and supports address arithmetic for indexed access. An insertion or deletion at position in a document of length shifts entries; insertion can additionally resize the backing storage, giving amortized time and worst-case for one operation. Deletion is with an additional constant term.
Building a document by appending the characters of a length- string costs amortized time, since geometric capacity growth copies a total of only entries. Thus this implementation does not have the quadratic append behavior of repeated immutable-string concatenation. A known final length can also be reserved in advance. The bounds use the usual amortized analysis of a dynamic array.[ref]
The missing preconditions are for insertion and for deletion and indexing. The inclusive endpoint permits appending; deletion or access at the length is invalid. Specify the initial state, for example , as well as the read-only frame conditions: indexing returns the indicated character and preserves , while length returns and preserves .
The insertion and deletion clauses already describe the new sequence, but their returned values and effects should be interpreted against the old state. For a machine-sized length, insertion also requires . These clauses complete the document abstract data type without prescribing one storage representation.
Map a pure, terminating function only when a value is demanded; use the adapters to obtain the cursor form with caching:
def map[T, U](f: T => U, it: Iter[T]): Iter[U] = new Iter[U] {
  def hasNext: Boolean = it.hasNext
  def next(): U = {
    require(it.hasNext, "empty iterator")
    f(it.next())
  }
}

def map[T, U](f: T => U, cur: Cursor[T]): Cursor[U] =
  asCursor(map(f, asIter(cur)))
Each demanded output is the function applied to the corresponding input, preserving order and lazy access even for an infinite sequence. The cursor adapter caches its mapped current value, so repeated reads need not recompute f. Totality/purity of f is the usual assumption for the mathematical sequence-map postcondition; an exception-throwing or state-changing function would need additional behavioral clauses.
Both functions may be named map because their second parameter types differ, Iter[T] versus Cursor[T]. Method overloading selects the applicable signature; its distinction is not based solely on the return type.
Read and advance the cursor only when the iterator is asked for its next value:
def asIter[T](cur: Cursor[T]): Iter[T] = new Iter[T] {
  def hasNext: Boolean = cur.hasCurrent
  def next(): T = {
    require(cur.hasCurrent, "empty iterator")
    val answer = cur.current
    cur.next()
    answer
  }
}
The two abstract sequences are identical. A next call returns the old head and removes it, while hasNext only queries availability. No element is read at construction or during an availability test, and no later element is read while returning the current one. Thus the adapter is not too eager. The source's Cursor.current clause needs the implicit precondition that its sequence is nonempty; taking the head of an empty sequence is undefined. The checks above satisfy that requirement even without relying on the client convention.
Cache only a requested current element. Merely constructing the cursor, or asking whether it is nonempty, must not fetch a value from the iterator:
def asCursor[T](it: Iter[T]): Cursor[T] = new Cursor[T] {
  private var cached: Option[T] = None

  def hasCurrent: Boolean = cached.nonEmpty || it.hasNext

  def current: T = {
    if (cached.isEmpty) {
      require(it.hasNext, "empty cursor")
      cached = Some(it.next())
    }
    cached.get
  }

  def next(): Unit = {
    if (cached.nonEmpty) cached = None
    else {
      require(it.hasNext, "empty cursor")
      it.next()
      ()
    }
  }
}
The abstraction function for the adapter is it.seq when no value is cached and [cachedValue] ++ it.seq otherwise. Fetching current removes one underlying iterator value but saves it, so the cursor's abstract sequence is unchanged; repeated reads return the same value. Advancing either discards that cache or consumes one uncached iterator value. No following element is prefetched.
A too-eager implementation could call it.next() at construction, or fetch a new element immediately after every advance, even when the client never requests it. That can trigger unnecessary work or nontermination on a difficult stream. This lazy iterator-to-cursor adapter avoids both behaviors and checks the underlying access preconditions itself. The wrapped iterator is assumed to be used exclusively through the adapter; independent external consumption would invalidate the shared-state abstraction.
A single flag represents whether the only element remains:
def unitIter[T](t: T): Iter[T] = new Iter[T] {
  private var available = true
  def hasNext: Boolean = available
  def next(): T = {
    require(available, "empty iterator")
    available = false
    t
  }
}

def unitCursor[T](t: T): Cursor[T] = new Cursor[T] {
  private var available = true
  def hasCurrent: Boolean = available
  def current: T = {
    require(available, "empty cursor")
    t
  }
  def next(): Unit = {
    require(available, "empty cursor")
    available = false
  }
}
The abstract sequence is [t] while the flag is true and empty afterward. current leaves it unchanged; either advance consumes its sole element. Renaming both methods to unit would leave identical parameter signatures differing only in result type, which cannot define two such Scala overloads.
Prefer the first sequence whenever it is nonempty, otherwise delegate to the second:
def cat[T](t: Iter[T], u: Iter[T]): Iter[T] = new Iter[T] {
  def hasNext: Boolean = t.hasNext || u.hasNext
  def next(): T = {
    if (t.hasNext) t.next()
    else {
      require(u.hasNext, "empty iterator")
      u.next()
    }
  }
}

def cat[T](t: Cursor[T], u: Cursor[T]): Cursor[T] = new Cursor[T] {
  def hasCurrent: Boolean = t.hasCurrent || u.hasCurrent
  def current: T = {
    if (t.hasCurrent) t.current
    else {
      require(u.hasCurrent, "empty cursor")
      u.current
    }
  }
  def next(): Unit = {
    if (t.hasCurrent) t.next()
    else {
      require(u.hasCurrent, "empty cursor")
      u.next()
    }
  }
}
Assume the two destructive inputs have noninterfering states; in particular, passing the same iterator twice does not create a replayable copy of its original sequence. Fresh independent iterators provide that behavior. Under this ownership condition, the abstraction function is always the concatenation t.seq ++ u.seq. Consumption from t removes the concatenation's head; once t is empty, consumption from u does so. Availability tests short-circuit, so an infinite first sequence never unnecessarily touches the second.
For finite lengths , under a client loop with one availability test and one advance per element, the iterator version directly invokes t.hasNext times, including the final false test. For a cursor client with one availability test, one current read and one advance per element, the corresponding count is . These count calls made by the shown adapters, not extra checks hidden inside arbitrary underlying methods. A client can repeat availability/current queries arbitrarily often, so no bound depending only on applies without such a client protocol.
Cache a permanent “first input exhausted” flag after the first negative test to avoid repeated queries to t while traversing u; this reduces the dependence to first-input queries under the same protocols. Availability caching can reduce additional repeated checks. The flag is sound because an iterator's consumed sequence does not spontaneously grow again.
Yes: the mutable specification omits important state and frame clauses. Queries do not explicitly preserve the receiver, so an implementation could clear its state during present, return an empty sequence, and satisfy the displayed coverage condition in the resulting state. Arithmetic does not explicitly preserve a distinct operand, so it could corrupt that operand as well as update the receiver. No initial value or independence requirement for copy is stated.
The missing old-state annotation on the other operand is particularly serious under reference aliasing. If other is the receiver, the printed addition equation becomes , which is impossible for a nonzero old count. Self-subtraction becomes rather than the intended zero; self-maximum admits arbitrarily increased counts. Specify instead, for every key,
with both operands evaluated in their pre-states. Queries preserve all states; updates change only the receiver's abstract value and preserve a distinct operand; copy produces an independent snapshot of the argument's pre-state. Specify an empty initial state and checked representable arithmetic, or use unbounded counts.
The fact that present may contain duplicates or zero-count keys is not itself a violation: the printed condition expressly requires only a support-covering sequence. An implementation may strengthen this to an exact, duplicate-free support. Efficiency also needs a cost model or explicit bounds if it is to be a formal guarantee rather than an informal aspiration.
Save the next pointer before redirecting it, then advance the two working heads. No node is allocated and the name/number fields are untouched.
def reverseBook(): Unit = {
  var prev: Node = null
  var cur = list
  while (cur != null) {
    val following = cur.next
    cur.next = prev
    prev = cur
    cur = following
  }
  list = prev
}
Let be the original sequence of node identities, not just their possibly equal field values. Write for the sequence currently headed by prev and for that headed by cur. A suitable loop invariant for in-place linked-list reversal is
with both working lists finite, acyclic, disjoint, together containing exactly the original nodes, and with every name and number unchanged. Here ++ means concatenation. Initially and . One iteration takes from the front of and replaces by . Since , the equation is preserved. Saving following before changing cur.next retains access to .
The loop variant is the length of , decreasing by one. At exit , so ; assigning the head establishes reversal. The empty and singleton cases work without a special branch. The abstraction function of the phone book ignores order, so it still maps every original name to its original number. All original node identities are reused, with running time and auxiliary space.
Figure 1.
In-place reversal preserves node identities while moving nodes from an untouched suffix into a reversed prefix
. Details.
A finite or infinite sequence of states in which for each consecutive pair. In infinite-path linear temporal logic semantics, paths are infinite; an initial path must also start in the specified initial set. Repeated states are allowed, unlike conventions for a simple path in a graph.
Peak of a sequence 2026-10-25
A peak of a sequence of real numbers is an index whose value is at least every later value. This is a condition on the entire tail, stronger than comparing only adjacent terms. Equality is allowed: every index of a constant sequence is a peak of a sequence.
Infinitely many peaks of a sequence, listed in increasing order of index, give a nonincreasing monotone subsequence. If only finitely many exist, every index beyond the last has a larger later term; repeatedly choosing one gives a strictly increasing monotone subsequence. This proves the monotone subsequence theorem.
A peak of a sequence of supplies a lower bound for all subsequent terms of . If both and have a peak of a sequence, the two selected values bound a common tail. Adding bounds for the finite initial segment proves that is a bounded sequence.
Perfect subsequence lemma 2026-10-14
Every infinite sequence in a well-quasi-ordering has an infinite subsequence all of whose earlier terms precede its later terms. Some term must have infinitely many later terms above it: otherwise choose each new index outside the finitely many upper-cone index sets of the terms already chosen, producing a bad sequence. Apply the same observation successively inside the infinite upper-cone subsequence. Each restriction preserves all earlier inequalities, proving the assertion.
A block determines a repeating sequence by setting for every integer . The inverse discrete Fourier transform gives this extension because each discrete Fourier mode satisfies . The extension explains why circular convolution wraps indices around the block. It specifies values at discrete indices; a continuous curve between samples requires an additional choice of interpolation.
Periodic sequence Created 2026-10-14 Updated 2026-10-20
A sequence indexed from zero with an integer period satisfying the displayed identity for all . Repeating a finite cycle is an example. The Cesàro mean article explains why its cumulative averages approach the one-cycle arithmetic mean.