Computer Science lessons & courses
69 lessons · 16 learning paths · free, quiz-checked, no signup required
The foundations beneath the stack: how computers represent data, schedule work, and move bits. Timeless material that outlives any particular framework.
Learning paths
Search Relevance: From BM25 to Hybrid
Vector search did not replace keyword search; production search runs both, because they fail in opposite places. This path builds relevance engineering from the ground up: the inverted index and the analysis decisions baked into it, BM25 and its saturation arithmetic, hybrid retrieval with reciprocal rank fusion, and the evaluation machinery, judgment sets, NDCG, position bias, that tells you whether any of it actually got better.
Formal Verification: Proving a Program Correct
Testing samples inputs; a proof covers all of them. Three traditions do this and each hits a different wall. Deductive proof turns a program into a relation between assertions, and stalls at the loop invariant no machine can supply. Type-level encoding makes wrong programs unwritable, and pays with a language that rejects some correct ones. Model checking searches every state exhaustively, and is bounded by how many there are. The path ends with two systems that were actually verified, and what they cost.
Floating Point: Why Your Numbers Are Wrong
Every floating point operation is correctly rounded to about sixteen digits, and results are still wrong in the first digit. This path explains how both are true: the guarantee is per-operation and relative, which means subtracting nearly equal numbers promotes error from insignificant to dominant without introducing any. It covers the representation, the cancellation patterns worth recognising, how to compare and test, and finally how to tell whether an inaccurate answer is your bug or the problem's nature.
Probabilistic Data Structures: Answers Without the Data
Answering set questions exactly costs memory proportional to the data, and that is a lower bound rather than an inefficiency. Sketches give up exactness in a specific, chosen direction and get constant memory in return. This path builds the three that run modern infrastructure: Bloom filters for membership, HyperLogLog for distinct counts in twelve kilobytes, and count-min for frequency. It ends on the property that actually explains their ubiquity, which is not the space saving.
Computer Graphics: Rasterisation and Ray Tracing
Every renderer answers one question first: at this pixel, which surface is visible? There are two ways to answer it, and almost everything else about a graphics system follows from which one it picked. This path builds the transform chain, then rasterisation as a distributed sort with a depth buffer, then ray tracing as a search through a spatial hierarchy. The last lesson explains why the two coexist, and lets you predict which effects will be cheap, which will be faked, and what the artefacts will look like.
The Limits of Computation: What No Program Can Do
Some things are not slow to compute, they are impossible, and the boundary is sharp enough to prove in a few lines. This path climbs the ladder of machines one memory model at a time: finite states and the counting argument that defeats them, then a stack, then an unbounded tape. At the top the limit stops being about memory and becomes the halting problem, generalised by Rice to every semantic property at once. The last lesson spends that result on why every type checker and verifier must choose which way to be wrong.
Dynamic Programming and Greedy: Knowing Which One Applies
Both techniques replace exponential search with something polynomial, and both fail on problems without the right structure. This path builds the recognition skill rather than a catalogue of recurrences: optimal substructure and where it breaks, choosing a state and deriving the running time from it, the exchange argument and the matroid theorem that says exactly when greedy is guaranteed, and a decision procedure to run on a problem you have never seen before.
Differentiable Rendering: Running Graphics Backwards
If a renderer is differentiable, recovering a 3D scene from a photograph becomes gradient descent. This path builds that idea properly: the rendering equation and why Monte Carlo path tracing is the only way to evaluate it, the visibility discontinuities that make naive autodiff return silently zero gradients for geometry, the adjoint and path-replay methods that made the backward pass affordable, and why the remaining difficulties are about the problem being ill-posed rather than about the gradients.
Core Data Structures: Hash Tables, Trees, Heaps, and Tries
Four structures cover most of what production code actually needs, and each exists because the others cannot answer one particular question. This path builds them from the mechanism up: why a hash table's constant lookup costs you all ordering, why sorted input destroys an unbalanced tree and what a rotation repairs, why a heap keeps only enough order to surface the smallest item, and why routers and autocomplete need a trie. You will finish able to pick the right one from the question being asked.
How CPUs Actually Work: Pipelines, Caches, and Performance
Two processors at the same clock speed can differ several-fold in real work done, and the reason is never the clock. This path builds the model that explains it: how a pipeline overlaps instructions and what a mispredicted branch costs, how a core issues several instructions per cycle and reorders them, why a DRAM access is roughly sixty times an L1 hit, and how the roofline model tells you whether optimising arithmetic is worth any effort at all. You will finish able to predict which loop is faster and say why.
Information Theory and Compression
Shannon proved in 1948 that information has a hard, measurable limit, and nearly every file, stream and disk you touch is built on that result. This path works through it. You will learn what entropy really measures and why cross-entropy is the loss function that trains language models, how Huffman and arithmetic coding approach the compression floor, where lossy formats like JPEG and AAC actually discard information and why that is a deliberate tradeoff, and how error-correcting codes let data survive a noisy channel.
How Computer Networks Actually Work
A request leaves your browser and arrives somewhere across the world in tens of milliseconds. This path follows it the whole way down. You will learn how headers nest as a packet is built, why MTU mismatches cause the classic bug where small requests work and large ones hang, how routers choose a path by longest prefix match and how a BGP mistake can take a network off the internet, how TCP turns an unreliable network into an ordered stream and what congestion control is really negotiating, and why HTTP/3 abandoned TCP for QUIC.
How Operating Systems Actually Work
Every program runs on top of a kernel making decisions for it: which thread gets the CPU, which pages stay in memory, when a write really reaches disk. This path opens that layer up. You will learn what a process actually is and what a context switch costs, how virtual addresses become physical ones through page tables and the TLB, what happens when code crosses into kernel mode and why that crossing is expensive, and how the page cache and fsync decide whether your data survives a crash. It closes on containers as ordinary kernel features rather than magic.
Digital Twins: Virtual Replicas of the Physical World
A digital twin is a virtual replica of a specific physical asset, kept in sync by live data so you can predict, optimize, and experiment safely in software. This cursus builds the concept precisely: what a twin is and how it differs from a plain simulation, what it is made of (physics and data-driven models, the sensor and data layer, and the types from component to process scale), and where it pays off, predictive maintenance, manufacturing, energy, and more, alongside an honest look at the data, drift, cost, and security challenges.
How hackers get in (and how to stop them)
A practical, example-driven tour of security from basics to advanced. Start by thinking like an attacker and following a real breach through its five stages, then dig into the human layer of phishing and passwords, then the technical layer where web apps get hacked with real code for SQL injection and XSS, and finally the defender's playbook of least privilege, zero trust, detection, and response. Every attack is paired with its concrete defense.
System Design Fundamentals
Ten lessons covering the building blocks every backend engineer needs to reason about scale. Move from traffic-shaping and caching through the hard tradeoffs of distributed data, then up to architectural styles that decide how teams ship.
All Computer Science lessons
Measuring Relevance: Judgments, NDCG, and the Click Trap
Search quality arguments end when there is a number, and begin again over whether the number is honest. This lesson builds offline evaluation from its atoms: a judgment set, precision and recall at k, MRR for known-item queries, and NDCG computed by hand for graded relevance. Then the online half: clicks, position bias, and why the top result gets clicked even when it is wrong.
Lexical Meets Vector: Hybrid Search and Rank Fusion
Vector search did not replace keyword search, because the two fail in opposite places: BM25 cannot see that laptop and notebook mean the same thing, and embeddings cannot see that SKU-4471-B is not approximately anything. This lesson maps the two failure surfaces, then builds the production answer: run both retrievers and fuse the rankings, with reciprocal rank fusion done by hand.
BM25: How Lexical Relevance Is Actually Computed
Matching finds candidates; scoring orders them, and the ordering is the product. This lesson builds BM25, the default ranking function of Lucene, Elasticsearch and OpenSearch, from its three ingredients: rare terms count more, repeated terms saturate, and long documents get discounted. With the formula, the two tuning knobs, and the saturation curve computed by hand.
The Inverted Index, and Why Analysis Decides Everything
Search does not scan documents; it looks up precomputed answers. This lesson builds the inverted index from first principles, then covers the pipeline that feeds it: tokenization, normalisation, stemming and synonyms, and why an analysis mistake made at index time cannot be fixed at query time. Includes the classic failure where a product SKU becomes unfindable.
What Has Actually Been Verified, and What It Cost
Two landmark systems carry machine-checked proofs of real code: a C compiler and an operating system kernel. Their published effort figures give the honest price of full verification, and their trusted computing bases show exactly what a proof still leaves unproved. This lesson uses both to decide where verification pays.
Model Checking: Exhaustive Search Instead of Proof
The third tradition supplies no invariants and writes no proofs. It builds the set of states a system can reach and checks the property against all of them, which is decidable when that set is finite. This lesson covers what it buys, the state explosion that limits it, and the techniques that made it usable anyway.
Types as Propositions: Making Wrong Programs Unwritable
The other tradition does not prove a program correct after writing it. It designs a type that only correct programs inhabit, so the compiler's ordinary check is the proof. This lesson builds the correspondence between types and logic, shows what dependent types add, and covers the price the approach charges.
What a Proof of Correctness Actually Is
Testing samples inputs; a proof covers all of them. The machinery is a logic in which programs are statements about how they change what is true. This lesson builds Hoare triples, works a proof by hand, and identifies the one step that cannot be automated and is therefore where the work is.
Conditioning and Stability: Whose Fault Is the Error
Two different things can make a numerical answer inaccurate: the problem may amplify any input perturbation, or the algorithm may introduce its own. They are separate quantities, one belongs to the problem and one to the code, and only the second is fixable. This lesson separates them and shows what follows.
Comparing Floats, and Testing Code That Uses Them
Equality fails on floats, and both standard replacements fail too: absolute tolerance breaks at scale, relative tolerance breaks near zero. This lesson works through why each fails, what the combined form actually does, and how to choose a tolerance from the problem rather than copying a magic constant.
Cancellation: Where the Digits Actually Go
Every operation is correctly rounded, yet results can be wrong in the first digit. The reason is that subtracting nearly equal numbers is exact and still catastrophic: it does not create error, it promotes error that was already there. This lesson builds that mechanism and the summation techniques that recover the lost accuracy.
How a Float Is Stored, and What That Rules Out
Floating point is not a slightly inaccurate version of real numbers. It is a finite set of values, spaced logarithmically, with exact rules. This lesson builds the IEEE 754 layout, shows why 0.1 cannot be represented, and derives the one error bound that every later result depends on.
Count-Min, and Why Sketches Compose
The count-min sketch estimates how often an item occurred using a fixed grid of counters, and it never underestimates. This lesson builds it, states the error bound that makes it usable, shows where it is useless, and ends on the property shared by all three structures that explains why they run distributed systems.
HyperLogLog: Counting Distinct Items in Kilobytes
Counting distinct items exactly needs memory proportional to the count. HyperLogLog answers the same question in a fixed twelve kilobytes, for cardinalities into the billions, by measuring an improbable event rather than storing anything. This lesson builds that idea from the leading-zeros intuition up.
Bloom Filters: Membership in a Bit Array
A Bloom filter answers set membership using a bit array and a handful of hash functions, with no items stored anywhere. This lesson builds it, derives the sizing formula that trades memory against false positives, explains exactly why deletion is impossible, and covers the variants that buy it back.
The Bargain: Bounded Memory for Bounded Error
Answering set questions exactly costs memory proportional to the data, which fails once the data does not fit. Probabilistic data structures accept a quantified error in exchange for memory that stays constant. This lesson establishes what that trade buys, and why the shape of the error matters more than its size.
Sort or Search: Why Both Pipelines Survive
The two renderer architectures are not competing implementations of the same idea. One sorts fragments for a single viewpoint, the other searches for a hit along an arbitrary ray. Reading them that way explains which effects are cheap in each, why production renderers combine them, and what a hybrid actually buys.
Ray Tracing and the Cost of Asking Anywhere
Ray tracing takes the opposite loop: for each pixel, find the geometry it hits. That buys visibility queries from any point in any direction, which is what shadows and reflections need. It also costs a scene-wide data structure, and the quality of that structure decides whether the renderer is usable.
Rasterisation: Edge Functions and the Z-Buffer
Rasterisation walks the geometry and asks which pixels each triangle covers. Two ideas make that fast enough for real time: a coverage test that is three linear functions, and a depth buffer that resolves visibility without sorting anything. This lesson builds both and shows why the design maps onto parallel hardware.
From Scene to Pixel: The Transform Chain
Every renderer answers one question first: at this pixel, which surface is visible? Getting there means moving geometry through five coordinate spaces. This lesson builds that chain, explains why a fourth coordinate is not a trick, and shows where depth precision quietly goes wrong.
What Undecidability Costs Real Tools
Rice's theorem closes every interesting question a type checker, linter or verifier wants to answer, yet those tools exist and work. They work by choosing which way to be wrong. This lesson covers the sound and unsound bargains, the provable approximation in pointer analysis, and the option of leaving Turing completeness behind on purpose.
The Halting Problem and the Shape of the Proof
Once memory stops being the constraint, a different kind of limit appears. No program can decide whether an arbitrary program halts, and the proof fits in eight lines. This lesson builds that argument, separates deciding from merely recognising, and shows how one impossibility result propagates to every other question worth asking.
Adding a Stack, Then a Tape
Finite memory fails on anything that must be counted, so add memory and watch what each purchase buys. A stack buys nesting and nothing more. An unbounded tape buys everything, and two entirely different formalisms invented in the same year turn out to buy exactly the same thing.
Finite Memory and What It Cannot Recognise
A machine with a fixed number of states can recognise a surprising amount, and then hits a wall that no amount of cleverness moves. This lesson builds the finite automaton, shows that regular expressions are the same thing in different notation, and proves by counting that balanced parentheses are out of reach.

