Generate each row of Pascal's triangle from its predecessor, padding at opposite ends before adding corresponding entries:
pascal :: Num a => [[a]]
pascal = iterate next [1]
  where
    next :: Num a => [a] -> [a]
    next row = zipWith (+) (0:row) (row ++ [0])
The boundary sums are the old endpoint plus zero, and the interior sums satisfy Pascal's rule. Induction on the iteration number therefore gives the rows of binomial coefficients. The outer lazy list is infinite, with each finite row available on demand. Instantiate a as Integer for exact arbitrarily large entries; bounded machine integers eventually overflow.
The completed identities are:
filter p . map f = map f . filter (p . f)

filter p . concat = concat . map (filter p)

zipWith f = (map (uncurry f) .) . zip
The first tests the predicate after the mapped function; the second filters each inner list. In the third, zip is curried: after one argument it still returns a function of a second list. The operator section (map (uncurry f) .) composes with that returned function. Applying both sides to xs and ys gives map (uncurry f) (zip xs ys). Omitting the section's extra composition level would not type-check.
The most general polymorphic type signatures and definitions are:
infixr 9 .

(.) :: (b -> c) -> (a -> b) -> a -> c
(f . g) x = f (g x)

zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith f (x:xs) (y:ys) = f x y : zipWith f xs ys
zipWith _ _ _ = []

uncurry :: (a -> b -> c) -> (a,b) -> c
uncurry f (x,y) = f x y
Function composition passes the result of the second function into the first. zipWith combines corresponding list elements and stops when either list ends. Uncurrying converts a function taking two successive arguments into one taking a pair. None of these operations needs a numeric or ordering constraint.
No: Stooge sort is not stable. Give equal keys distinct record identities and start with
The initial endpoint swap gives . The later two-element calls either see increasing keys or equal keys, so they make no swap. The two records with key 2 have reversed their original order, contradicting stable sorting. The example uses length three, where the intended current-length split is unambiguous.
Prefer the alternatives for large unrestricted arrays. Merge sort and heapsort have worst-case time, while insertion sort has worst-case time and can be much faster on nearly sorted data. The intended stooge sort has worst-case , so even insertion sort has the better worst-case exponent.
The first two give the stronger general asymptotic guarantee. Choices between them can depend on storage and stable sorting requirements; these considerations do not rescue Stooge sort's much larger work count.
The printed split uses while naming the current length . For the intended stooge sort, read that split as at every recursive call. Keeping one fixed original instead is not the standard algorithm and does not generally sort correctly.
The three recursive calls then each have length , and all other work is constant. Thus
A version of the master theorem sufficient here states: if with constants , fixed-size base cases and for some , then , provided the recursive sizes shrink above the base threshold. Apply it with to obtain
The rounded size is important for correctness; it does not change this asymptotic exponent.
A deterministic comparison sort on distinct keys must distinguish possible initial orders. Its binary comparison decision tree therefore has at least leaves: a leaf fixes one output ordering and cannot be correct for two different strict orders of the original records.
A binary tree of height has at most leaves, hence
This is the comparison sorting lower bound on the worst-case number of comparisons. Distinct keys have only two possible comparison outcomes, even if an implementation's comparator also supports equality. Algorithms exploiting numeric key values, such as counting sort, fall outside this model.
Build a max-heap, then repeatedly swap its root with the last element of the active prefix, shrink that prefix and restore heap order by heapify down. A zero-based implementation is
for i = floor(n/2)-1,...,0:
    siftDown(A,i,n)
for end = n-1,...,1:
    swap A[0],A[end]
    siftDown(A,0,end)
siftDown(A,i,end) repeatedly exchanges entry i with its larger child while the child lies below end and has a larger key. The suffix beyond end is already sorted and never touched again. For the specified input, key stages of heapsort are
StageActive max heapSorted suffix
Bottom-up heap construction
Extract 5, repair
Extract 4, repair
Extract 3, repair
Extract 2
The final array is . Bottom-up construction takes time because there are progressively fewer nodes at each greater subtree height; the extractions give worst-case time and constant auxiliary storage for iterative sifting.
Relative to the resulting DFS edge classification, a tree edge in depth-first search discovers a white vertex and becomes its parent edge. A forward edge in depth-first search goes to a proper descendant but is not that descendant's discovery edge. A back edge in depth-first search goes to an active ancestor, with a self-loop also counted as a back edge when such edges are allowed. A cross edge in depth-first search joins vertices with no ancestor-descendant relationship in the forest, such as different completed branches or different trees.
The definitions refer to directed edges; an undirected graph is normally classified only with tree and back edges, accounting for the reverse copy of a parent edge separately.
Maintain white, gray and black colors for undiscovered, active and completed vertices. A single traversal clock records DFS discovery and finishing times:
for v in V: color[v] = white; parent[v] = none
time = 0
visit(u):
    time = time+1; d[u] = time; color[u] = gray
    for v in adjacency[u]:
        if color[v] == white:
            parent[v] = u
            visit(v)
    color[u] = black; time = time+1; f[u] = time
for u in V:
    if color[u] == white: visit(u)
The outer loop makes a depth-first search forest even when the directed graph is disconnected. Each vertex is entered once and each directed adjacency entry is inspected once. Thus an adjacency list representation gives time and auxiliary storage, including the worst-case recursive stack. Sorting neighbors to impose a particular visit order would be additional work.
Let be the best sum of a segment ending at position , allowing the empty segment with sum zero. The maximum subarray problem recurrence is
An optimal nonempty segment ending at extends the best suffix ending at , or starts fresh; a negative suffix cannot help. Keep its start index and record endpoints whenever a new overall best is found:
suffix = 0; best = 0
start = 0; bestLeft = 0; bestRight = 0
for i = 0,...,n-1:
    suffix = suffix + A[i]
    if suffix < 0:
        suffix = 0; start = i+1
    if suffix > best:
        best = suffix
        bestLeft = start; bestRight = i+1
return A[bestLeft:bestRight]
The half-open endpoint interval is empty initially, so empty input and all-negative input correctly return an empty segment. The invariant identifies the best nonnegative suffix and the best segment in the scanned prefix, proving correctness. This is Kadane's algorithm, using time and auxiliary space, excluding the returned slice. The displayed example yields sum , from the segment .
For a connected, weighted, undirected graph, grow a tree from any root . For every vertex outside the tree, store the cheapest edge currently connecting it to the tree, not its source-path distance:
for v in V: key[v] = infinity; parent[v] = none
key[r] = 0
Q = indexed min-priority-queue containing all vertices
while Q is not empty:
    u = extract-min(Q)
    if parent[u] != none: output edge (parent[u],u)
    for each edge {u,v} of weight w with v still in Q:
        if w < key[v]:
            key[v] = w
            parent[v] = u
            decrease-key(Q,v,w)
The maintained key chooses the minimum-weight edge crossing the cut between the tree and remaining vertices. The minimum spanning tree cut property makes that edge safe; induction therefore preserves the existence of a minimum spanning tree containing all selected edges. This proves why Prim's algorithm is greedy and correct. With adjacency lists and a binary heap its time is . For a disconnected graph, starting another component when the minimum key is infinity produces a minimum spanning forest instead of claiming that a spanning tree exists.
Dynamic programming defines subproblem optima and combines their stored answers through a recurrence. It is useful when optimal substructure and overlapping subproblems allow repeated work to be shared. Several alternative choices can be compared before an optimum is selected.
A greedy algorithm instead commits to a locally selected choice and does not later reconsider it. To be correct, its choice needs a justification such as an exchange argument or a safe-cut property, beyond merely having optimal substructure. Neither method is automatically applicable to every optimization problem. Prim's algorithm illustrates a justified greedy choice; the maximum-segment recurrence below illustrates dynamic programming.
Use minimum-hop shortest paths by minimizing the lexicographic order pair : total weight first, number of edges second. Extend a pair across an edge of weight by adding , and compare the full pair in both the priority queue and relaxation:
for v in V: key[v] = (infinity,infinity)
key[s] = (0,0)
Q = indexed min-priority-queue containing all vertices, keyed by key
while Q is not empty:
    u = extract-min(Q)
    if key[u].distance == infinity: break
    for each edge (u,v) of weight w with v still in Q:
        candidate = (key[u].distance + w, key[u].hops + 1)
        if candidate <lex key[v]:
            key[v] = candidate
            decrease-key(Q,v,candidate)
for v in V: best[v] = key[v].hops
All weights are positive, so extending a path strictly increases its first component. The usual Dijkstra's algorithm settled-label proof therefore applies to these ordered pairs: no path through a not-yet-settled vertex can later improve an extracted minimum. Among equal minimum weights, the secondary component selects the fewest edges. Merely breaking extraction ties by vertex name would not implement this objective.
With a binary heap and adjacency lists, the bound is , with extra storage. Unreachable vertices have best = infinity. In the paper's example, the resulting pairs in order are , so the requested edge counts are .
Bellman–Ford permits negative edge weights, and can detect a reachable negative-weight cycle. The usual settled-label Dijkstra's algorithm requires nonnegative weights for its correctness argument. Negative edges are not themselves a problem for Bellman–Ford when no relevant negative cycle exists.
Every finite distance label is the weight of a discovered directed walk, so it can never underestimate a finite shortest-path distance. After complete passes, each label is at most the cost of every source-to-vertex path using at most edges. To prove that assertion, consider such a path's last edge : after the previous pass, already has a label no greater than the prefix cost, and the current pass relaxes that last edge. In-place improvements can only make the label smaller, preserving the assertion.
When no negative-weight cycle is reachable, any repeated-vertex portion of an optimal walk can be removed without increasing its cost. Some shortest path therefore has at most edges. The two bounds meet after that many passes, proving correctness. If a complete pass makes no change, all edge relaxation inequalities already hold and further passes cannot improve anything. A further strict relaxation after passes implies a reachable negative cycle by the same simple-path bound.

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!
We have two killer features:
  1. 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-calculus
    Articles 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/derivative
  2. 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.
    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.
  3. https://raw.githubusercontent.com/ourbigbook/ourbigbook-media/master/feature/x/hilbert-space-arrow.png
  4. Infinitely deep tables of contents:
    Figure 6.
    Dynamic article tree with infinitely deep table of contents
    .
    Descendant pages can also show up as toplevel e.g.: ourbigbook.com/cirosantilli/chordate-subclade
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