Everything on the site.

Big-O notationAlgorithms · Count the steps in real loops, then compare n, n log n, n² and 2ⁿ on a live chart.RecursionAlgorithms · Watch frames push and pop on the call stack for factorial and Fibonacci.BFS vs DFSAlgorithms · A queue against a stack: draw a graph and see which order each search visits it in.Sorting algorithmsAlgorithms · Seven sorts on the same input, with comparison, swap and write counts side by side.Binary searchAlgorithms · Halve the range, probe the middle, repeat: with lo, mid and hi drawn on the array.Sets, relations and functionsDiscrete maths · Shade any set expression on a Venn diagram and test a relation for its properties.Proof by inductionDiscrete maths · Four worked proofs revealed one step at a time, and a broken one to diagnose.CombinatoricsDiscrete maths · An exact nPr and nCr calculator, and a Pascal’s triangle that shows its own addition rule.Boolean algebraDiscrete maths · The laws, De Morgan, and normal forms, with a truth-table generator built in.Finite-state machinesTheory · Build a DFA in a table, see it drawn, and run strings through it one symbol at a time.Domain theoryTheory · Why recursion needs least fixed points, and how CPOs, Scott continuity and powerdomains supply them.Truth table generatorTools · Expression in, truth table out: with DNF, CNF, a minimal form and LaTeX.Graph traversal visualiserTools · Draw a graph, then animate BFS, DFS and Dijkstra with the frontier shown.Recursion tree visualiserTools · Paste a recursive function or a recurrence and see its call tree and call count.Gradient descentML maths · Drag the starting point, set the learning rate, and watch it converge or blow up.Vectors and embeddingsML maths · Bend the plane with a 2×2 matrix and measure how close toy word vectors are.Softmax and cross-entropyML maths · Edit the logits and watch the probabilities, the loss and the gradient update live.Attention mechanismML maths · Q, K and V for three tokens, a live score heatmap, and the weighted sum of values.Formatting a CS paper in LaTeXLaTeX · Page limits, \documentclass, front matter, theorem environments and the bibliography.Camera-ready checklistLaTeX · Fonts embedded, PDF/A, copyright form, source bundle, and why final versions get rejected.LaTeX templatesLaTeX · Where the official classes live, plus a minimal article template you can copy.Boolean algebra calculatorTools · A Boolean expression simplifier that names the law used at every step.K-map solverTools · Fill in a Karnaugh map and see the groups, the minimal SOP and POS, and the essential terms.Logic gate simulatorTools · Wire up gates, flip the switches, and get the truth table and expression of your circuit.Regex to NFA converterTools · Type a regular expression and watch Thompson’s construction build its NFA, fragment by fragment.NFA to DFA converterTools · Enter an NFA or a regex and step through the subset construction, then minimise the DFA.DFA simulatorTools · Edit a DFA, run strings through it step by step, batch-test them and share the machine as a link.Regular expressions to automataTheory · Regex to NFA to DFA to minimal DFA, worked through on one example with every set shown.The halting problemTheory · Why no program can tell whether every program halts, with the paradox program played out.Pigeonhole principleDiscrete maths · n pigeons, k holes: why some hole gets ⌈n/k⌉, and the surprising things that follows from it.Dijkstra’s algorithmAlgorithms · Shortest paths with a priority queue: a worked table, a proof, and a graph you can redraw.Hash functionsAlgorithms · Keys in, buckets out: hash a word four ways, then watch chaining and probing handle collisions.Sorting algorithm visualizerTools · Up to seven sorts race on the same data, then step through any one of them line by line.LaTeX table generatorTools · Type or paste a table, merge cells, pick booktabs, and copy clean tabular code.Combination calculatorTools · Exact nCr with the cancelling shown, combinations with repetition, and a full list for small n.Permutation calculatorTools · nPr, nʳ, anagrams like MISSISSIPPI and round-table seatings, with exact working.AlgorithmsSection · Step-through visualisations of sorting, searching, recursion, graph traversal, Dijkstra’s algorithm, hash functions and Big-O growth, with pseudocode that follows along.Discrete mathsSection · Sets, relations and functions, proof by induction, counting, the pigeonhole principle and Boolean algebra, explained with worked examples and interactive checkers.TheorySection · Finite-state machines, regular expressions and automata, the halting problem, and the mathematical semantics of programming languages, explained from first principles.ML mathsSection · Gradient descent, vectors and embeddings, softmax and cross-entropy, and attention, each with a formula, a worked numeric example and a live version.ToolsSection · Free browser tools: truth tables, Boolean simplification, K-maps, logic gates, nCr and nPr, regex to NFA to DFA, sorting and graph visualisers, and LaTeX tables.LaTeXSection · How to format a CS conference or workshop paper in LaTeX, a camera-ready checklist, and a minimal template you can adapt.
Theory

The halting problem, explained with Turing’s proof

The halting problem asks for a program that reads any program and its input and says whether it will eventually stop or run forever. Alan Turing proved in 1936 that no such program can exist. The proof fits in a few lines, and its consequences reach every compiler, linter and verification tool written since.

Interactive: Diagonal table and a “build a halting decider” challengeUpdated

The problem

Some programs obviously stop: print("hi"). Some obviously don’t: while true: pass. Many are hard to judge by eye. Here is a short one:

def collatz(n):
    while n != 1:
        n = n // 2 if n % 2 == 0 else 3 * n + 1

Started at 27 it stops after 111 steps, and at 97 after 118. Every starting value ever tried stops, but nobody has proved that every one does: whether this four-line loop halts for all positive nn is the Collatz conjecture, open since 1937. A general halting tester would settle it, and countless other open problems, at once.

The halting problem

Given the source code of a program PP and an input xx, decide whether PP eventually stops when run on xx.

A decider for it would be a program HH that always stops and answers correctly: H(P,x)=haltsH(P, x) = \text{halts} if P(x)P(x) stops, and H(P,x)=loopsH(P, x) = \text{loops} if it runs forever.

The claim is not that halting is hard to decide, or slow. It is that no program at all, however clever and however much time it is allowed for each answer, gives the right answer for every program and input. Problems like this are called undecidable.

Turing’s proof, step by step

The proof is by contradiction: assume a decider exists, and use it to build a program that it must get wrong.

Theorem: the halting problem is undecidable

No program HH decides, for every program PP and input xx, whether P(x)P(x) halts.

  1. Suppose, for contradiction, that H(P,x)H(P, x) exists: it always stops, and answers “halts” or “loops” correctly.
  2. Programs are text, so a program can be given its own source code as input. Using HH as a subroutine, write this program DD:
    def D(P):
        if H(P, P) == "halts":
            while True: pass     # loop forever
        else:
            return               # stop at once
    DD asks whether PP halts when fed itself, then does the opposite.
  3. Now run DD on its own source code. H(D,D)H(D, D) must return one of its two answers.
  4. If H(D,D)H(D, D) says “halts”, then D(D)D(D) takes the first branch and loops forever. So D(D)D(D) does not halt, and HH was wrong.
  5. If H(D,D)H(D, D) says “loops”, then D(D)D(D) takes the second branch and stops. So D(D)D(D) halts, and HH was wrong again.
  6. Either way HH gives a wrong answer on the input (D,D)(D, D), contradicting the assumption that it is always right. So no such HH exists. ■\blacksquare

Nothing in the argument depends on how HH works inside. Whatever program you propose as a halting decider, the construction produces a specific input on which it fails.

Why it is called a diagonal argument

List every program as P1,P2,P3,…P_1, P_2, P_3, \dots (programs are finite strings, so they can be listed). Make a table whose cell in row ii, column jj says whether PiP_i halts on input PjP_j. The program DD reads the diagonal and flips it: on input PiP_i it does the opposite of what PiP_i does on PiP_i. So DD differs from every PiP_i at the ii-th column and cannot be any row of the table. But DD is a program, so it must be a row. The contradiction shows the table cannot be computed. This is the same trick Cantor used in 1891 to show that the real numbers cannot be listed.

Try to build a halting decider

1. The diagonal table

Row = program, column = the input it is given. Suppose a decider H filled in every cell correctly. Click any cell to change H’s answer; D is built from the diagonal by flipping it.

Programon P₁on P₂on P₃on P₄on P₅
P₁
P₂
P₃
P₄
P₅
D

2. Ask H about D running on itself

D(x) asks H whether x halts on x, then does the opposite. What should H answer for D(D)?

    What “program” means here

    Turing made “program” precise with his machines: a finite control reading and writing symbols on an unbounded tape. The result holds for any model of computation that is as powerful, which includes every general-purpose programming language with unbounded memory. By the Church–Turing thesis, anything we would call an algorithm can be written as such a machine, so the halting problem has no algorithmic solution, full stop.

    The unbounded memory matters. A finite-state machine, or a real computer with a fixed amount of memory, has finitely many configurations. Run it long enough and it either stops or repeats a configuration, after which it loops forever. So halting is decidable for finite machines in principle; the catch is that a machine with a gigabyte of memory has 28×2302^{8 \times 2^{30}} configurations, and waiting for a repeat is hopeless in practice.

    Rice’s theorem: almost everything is undecidable

    Once one problem is known to be undecidable, others follow by reduction: if a decider for problem BB could be used to decide halting, then BB is undecidable too. For example, “does PP ever print the word done?” is undecidable: given PP and xx, build a program that runs P(x)P(x) silently and then prints done. It prints done exactly when P(x)P(x) halts.

    Rice’s theorem (1953) Every non-trivial property of what a program computes is undecidable. “Non-trivial” means some programs have the property and some don’t; “what it computes” means the property depends only on the program’s input–output behaviour, not on how its code is written.

    So no algorithm decides, for all programs, whether a program returns 0 on every input, whether two programs compute the same function, whether a program ever divides by zero, or whether it is a virus. Properties of the text, such as “does the source contain a loop?” or “does it use more than 100 lines?”, are decidable: they are not about behaviour.

    What this means for real tools

    Undecidability does not make program analysis useless. It means every analysis has to give something up, and good tools choose carefully what:

    • Over-approximate. A type checker or static analyser may reject some correct programs (false alarms) so that it never accepts an incorrect one. When a compiler warns that a variable “may be used uninitialised” in code you know is fine, this is why.
    • Under-approximate. Testing and bug-finding tools report only real problems but can miss some.
    • Restrict the language. Total languages, used in proof assistants, only allow recursion that provably terminates, so every program halts. They give up some programs to get the guarantee.
    • Answer “don’t know”. Termination provers prove that many real programs halt, and give up on the rest. A time-out is an honest third answer.

    Common misconceptions

    “So we can never tell whether a program halts.”
    For a particular program we often can, by proof. The theorem only says no single algorithm works for all programs.
    “Just run it and see.”
    Running it answers “halts” when it halts, but if it hasn’t stopped yet you never learn whether it will. This gives a semi-decision procedure: the halting set is recognisable (computably enumerable) but not decidable. Its complement, “runs forever”, is not even recognisable.
    “A faster computer or quantum computer would help.”
    No. The proof makes no assumption about speed. Quantum computers compute the same functions as classical ones, just sometimes faster.
    “The proof is a trick about self-reference that never matters in practice.”
    Self-reference is only the tool for the proof. Through reductions, the same limit applies to ordinary questions about ordinary programs, as Rice’s theorem shows.

    Related results

    • Gödel’s incompleteness theorem (1931) is a close cousin: any consistent formal system strong enough for arithmetic has true statements it cannot prove. If it could prove every true “PP does not halt” statement, we could decide halting by searching for proofs.
    • The Busy Beaver function, the most steps any halting nn-state Turing machine can take, grows faster than any computable function, because computing it would solve the halting problem.
    • Hilbert’s tenth problem, whether a polynomial equation has integer solutions, was shown undecidable in 1970 by reducing halting to it.

    References

    1. A. M. Turing, “On computable numbers, with an application to the Entscheidungsproblem”, Proceedings of the London Mathematical Society s2-42(1), 1937 (read 1936). doi:10.1112/plms/s2-42.1.230
    2. H. G. Rice, “Classes of recursively enumerable sets and their decision problems”, Transactions of the American Mathematical Society 74(2), 1953. doi:10.1090/S0002-9947-1953-0053041-6
    3. M. Sipser, Introduction to the Theory of Computation, 3rd ed., Cengage, 2012. Chapters 4 and 5.
    4. “Halting problem”, Wikipedia.