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.
Algorithms

What is a hash function? Explained with an interactive hash table

A hash function turns a key of any size, such as a word, a file or a number, into a fixed-size number called a hash. Hash tables use that number to find data in constant time on average; checksums, password storage and digital signatures use it too. This page explains what makes a hash function good, with a playground and a hash table you can fill yourself.

Interactive: Hash playground, collision calculator and hash-table labUpdated

What is a hash function?

A hash function hh maps keys from a large, often unbounded, set UU to a small fixed range of values:

h:U→{0,1,…,m−1}.h : U \to \{0, 1, \dots, m - 1\}.

For a hash table, mm is the number of buckets, perhaps a few thousand. For a general-purpose hash it is a power of two such as 2322^{32} or 2642^{64}, and the result is reduced modulo the table size afterwards. The word “hash” comes from chopping and mixing: a good hash function chops the key into pieces and mixes them so thoroughly that the result looks random, even though it is completely determined by the key.

Take the key "hello". The polynomial hash used by Java’s String.hashCode gives 99162322; the 32-bit FNV-1a hash gives 0x4f9f2cab. In a table of 16 buckets these land in buckets 2 and 11. Try your own keys:

Hash function playground

Hash functionHash valueBucket (mod m)Bits changed

“Bits changed” compares the hash of your key with the hash of the same key with its last character replaced by the next one (). A good hash changes about half its bits.

FNV-1a bits, with the bits that differ for highlighted

What makes a hash function good

  • Deterministic. The same key always gives the same hash. Without this, you could never find a key again after storing it.
  • Uniform. Keys should spread evenly over the mm buckets, so no bucket is crowded while others sit empty. Real keys are anything but random (names share prefixes, IDs are consecutive, prices end in 99), so the function has to break up these patterns.
  • Fast. A hash table is only fast if the hash is. Good non-cryptographic hashes process several bytes per CPU cycle.
  • Avalanche. Changing one bit of the key should change about half the bits of the hash, in an unpredictable pattern. The playground measures this: change the last letter of a key and count the bits that flip. The character-sum hash fails badly, the polynomial hash only disturbs a few low bits, and FNV-1a and SHA-256 flip about half.

Notice what is not required: a hash does not have to be reversible, and different keys are allowed to have the same hash. That second point is unavoidable, as the next section shows.

Simple hash functions

The division method

For an integer key, h(k)=k mod mh(k) = k \bmod m. It is a single instruction, but the choice of mm matters. If m=2pm = 2^p, the hash is just the lowest pp bits of the key, so keys that differ only in their high bits always collide. A prime mm not close to a power of two works much better. For example, 1234 mod 11=21234 \bmod 11 = 2.

The multiplication method

Multiply the key by a constant 0<A<10 < A < 1, keep the fractional part, and scale it to the table: h(k)=⌊m⋅(kA mod 1)⌋h(k) = \lfloor m \cdot (kA \bmod 1) \rfloor. Here the choice of mm no longer matters, so powers of two are fine. Knuth suggests A=(5−1)/2≈0.618A = (\sqrt{5} - 1)/2 \approx 0.618, which spreads consecutive keys out well; with m=10,000m = 10{,}000, the key 123456 lands in bucket 41. Real implementations do the same thing in integer arithmetic, with a multiply and a shift (“Fibonacci hashing”).

Polynomial string hashing

Treat the characters of a string s0s1…sn−1s_0 s_1 \dots s_{n-1} as digits in base bb:

h(s)=(∑i=0n−1si b n−1−i) mod M.h(s) = \Big(\sum_{i=0}^{n-1} s_i \, b^{\,n-1-i}\Big) \bmod M.

Computed with Horner’s rule, h←h⋅b+sih \leftarrow h \cdot b + s_i, it costs one multiply and one add per character. Unlike simply adding the characters, it depends on their order, so “stop”, “pots” and “tops” get different hashes. It is also rolling: the hash of a sliding window can be updated in constant time when one character leaves and another arrives, which is the trick behind the Rabin–Karp string-search algorithm.

FNV-1a

FNV-1a processes one byte at a time: XOR the byte into the hash, then multiply by a fixed prime. For 32 bits, start from 0x811c9dc5 and multiply by 16777619 (0x01000193) each time, all modulo 2322^{32}. The multiplication spreads each byte’s influence into the higher bits, which is why its avalanche behaviour is much better than the polynomial hash’s. It is short, fast on small keys, and widely used inside compilers, databases and DNS servers. For long keys, modern hashes such as xxHash and SipHash process several bytes at once.

Collisions are unavoidable

A collision is two different keys with the same hash. When there are more possible keys than hash values, collisions must exist: this is the pigeonhole principle. There are infinitely many strings and only 2322^{32} 32-bit hashes, so infinitely many strings share each one.

Collisions also come much sooner than intuition suggests. Put nn keys into mm buckets at random. The chance that they all land in different buckets is

Pr⁡[no collision]=∏i=1n−1(1−im)≈e−n(n−1)/2m.\Pr[\text{no collision}] = \prod_{i=1}^{n-1}\Big(1 - \frac{i}{m}\Big) \approx e^{-n(n-1)/2m}.

This is the birthday problem: with m=365m = 365, only 23 people are needed for a 50.7% chance that two share a birthday, and with 50 people the chance is 97%. In general a collision becomes likely once nn reaches about m\sqrt{m}. For a 32-bit hash that is just 77,164 keys for even odds, which is why 32-bit hashes are fine for tables but useless as unique identifiers, and why cryptographic hashes use 256 bits.

Collision calculator

Assumes the hash spreads keys uniformly and independently at random. For very large m the exact product is replaced by the approximation 1 − e−n(n−1)/2m, which is accurate there.

Hash tables: chaining and open addressing

A hash table stores each key in the bucket its hash points to, so finding a key takes one hash computation and a look in one place, rather than a search through everything. Since collisions will happen, every hash table needs a strategy for them:

  • Separate chaining keeps a short list in each bucket. A collision simply adds the key to the list. Lookups scan one list, whose expected length is the load factor α=n/m\alpha = n/m.
  • Open addressing stores every key in the array itself. When the home slot is taken, it probes other slots in a fixed sequence until it finds a free one. Linear probing tries the next slot, then the next. Quadratic probing jumps by growing offsets (here 1, 3, 6, 10, … slots from home). Double hashing moves in steps whose size comes from a second hash of the key.

Fill the table below and switch strategies: the same keys are re-inserted each time. “Add keys that clash” adds numbers with the same remainder modulo mm, the worst case for any table.

Hash table lab

Collision strategy

Whole numbers are used as their own hash; words are hashed with FNV-1a. The home bucket is h(k) mod m.

    Worked example: eight keys, eleven slots

    Insert 12, 44, 13, 88, 23, 94, 11, 39 into a table of size 11 with h(k)=k mod 11h(k) = k \bmod 11. Their home buckets are 1, 0, 2, 0, 1, 6, 0, 6.

    • With chaining, the non-empty buckets are 0: 44 → 88 → 11; 1: 12 → 23; 2: 13; 6: 94 → 39. The longest chain has 3 keys, so the worst lookup compares against 3 keys; the average over stored keys is lower.
    • With linear probing, each collision pushes a key into the next free slot, so the keys form one solid run: slots 0–7 hold 44, 12, 13, 88, 23, 11, 94, 39. Inserting 11 (home 0) needs 6 probes. This growing run is primary clustering: any key that hashes anywhere into the run makes it longer.

    How full can a table get?

    Under the assumption that the hash is uniform, the expected number of probes depends only on the load factor α\alpha. For a lookup of a key that is not present:

    Strategyα = 0.5α = 0.75α = 0.9Formula
    Chaining1.51.81.91+α1 + \alpha
    Linear probing2.58.550.512(1+1(1−α)2)\tfrac12\big(1 + \tfrac{1}{(1-\alpha)^2}\big)
    Double hashing2.04.010.011−α\tfrac{1}{1-\alpha}

    Chaining degrades gently and can even run above α=1\alpha = 1. Open addressing gets slow as the table fills, linear probing fastest of all, so real implementations resize: when α\alpha passes a threshold (often 0.75 for chaining, 0.5–0.875 for open addressing), allocate a table about twice the size and re-insert every key. A single resize costs O(n)O(n), but because the size doubles, the cost averaged over all insertions is still O(1)O(1). Linear probing remains popular anyway: probing neighbouring slots is very cache-friendly, which often outweighs the extra probes.

    Note the word expected. If many keys share a hash, every operation degrades to O(n)O(n). Attackers can exploit this by sending keys chosen to collide, so web servers and language runtimes use a seeded hash such as SipHash, whose secret random seed makes collisions impossible to predict from outside.

    Cryptographic hash functions

    A cryptographic hash function such as SHA-256 has to survive a deliberate attacker, not just ordinary data. It must be:

    • preimage-resistant: given a hash, it is infeasible to find any input that produces it;
    • second-preimage-resistant: given one input, it is infeasible to find a different input with the same hash;
    • collision-resistant: it is infeasible to find any two inputs with the same hash.

    Collisions still exist, by the pigeonhole principle, but with 256 output bits the birthday bound puts a generic search at around 21282^{128} evaluations, far beyond any computer. That makes the hash usable as a fingerprint: to check that a downloaded file is intact, compare its SHA-256 with the published one. Cryptographic hashes are also the basis of digital signatures, Git commit IDs and blockchains. MD5 and SHA-1 are now broken in this sense: practical collisions have been found, so they must not be used where an attacker could choose the input.

    The price is speed. SHA-256 is many times slower than FNV-1a or xxHash, so hash tables use a fast non-cryptographic hash, and security-sensitive code uses a cryptographic one.

    Storing passwords Never store passwords, and never store a plain fast hash of them. A fast hash lets an attacker who steals the database try billions of guesses per second. Store a salted hash from a deliberately slow password-hashing function such as Argon2, scrypt or bcrypt. The salt, a random value stored next to each hash, makes identical passwords hash differently and defeats precomputed tables. The slowness, tunable by a cost parameter, makes each guess expensive.

    Where hash functions are used

    • Dictionaries and sets in almost every language (Python’s dict, Java’s HashMap, C++’s unordered_map) are hash tables.
    • Deduplication and caching: hash each item and compare the hashes before comparing whole items.
    • Checksums: CRCs catch accidental corruption in network packets and archives; cryptographic hashes also catch deliberate tampering.
    • Probabilistic data structures: Bloom filters test set membership in a few bits per item, and HyperLogLog counts distinct items in a few kilobytes, both by hashing.
    • Distributed systems: consistent hashing decides which server stores which key, so that adding a server moves only a small fraction of the keys.

    Hashing turns up in other algorithms on this site too. A Big-O analysis of a hash table’s O(1)O(1) operations is an expected bound over the hash’s randomness, unlike binary search’s guaranteed O(log⁡n)O(\log n). And Dijkstra’s algorithm typically keeps its distances in a hash map keyed by vertex.

    References

    1. T. H. Cormen, C. E. Leiserson, R. L. Rivest and C. Stein, Introduction to Algorithms, 4th ed., MIT Press, 2022. Chapter 11, “Hash tables”.
    2. D. E. Knuth, The Art of Computer Programming, Vol. 3: Sorting and Searching, 2nd ed., Addison-Wesley, 1998. Section 6.4.
    3. J. L. Carter and M. N. Wegman, “Universal classes of hash functions”, Journal of Computer and System Sciences 18(2), 1979. doi:10.1016/0022-0000(79)90044-8
    4. “Fowler–Noll–Vo hash function”, Wikipedia.