Fifty days from a bit to the bare machine
I build systems for a living, and for years I worked one layer above the machine — fluent in the APIs, vague on what ran underneath. This is me closing that gap in public. Every topic is taught at four levels: how you write it, what it means, what the bytes actually do, and what it costs.
Each day stands alone and assumes nothing. If a page mentions a method you have not met, that page explains it — including the parts most references call obvious. Python is the primary language, Rust is the one that makes memory explicit, and ARM64 assembly appears for reading rather than writing. Hardware throughout is Apple silicon.
Practice questions sit at the end of every day with their answers revealable in place. Solutions to the coding problems are published once I have actually solved them — not before.
Representation
Days 1–7How anything is stored. Bits, integers, floats, text — and a single variable followed all the way down to its address in memory.
01Bits, bytes & endianness
Binary, octal and hex from first principles. Every bitwise operator with worked column arithmetic, the idiom table, two's-complement tricks, and why byte order exists.
Integers & two's complement
Why negation is invert-plus-one, where overflow is undefined, and how CPython stores an integer with a thousand digits.
Floating point & IEEE 754
Sign, exponent, mantissa — and why 0.1 + 0.2 is not 0.3 in any language you will ever use.
Text, Unicode & UTF-8
Code points versus encodings, the continuation-byte scheme, and why the length of an emoji depends on who you ask.
A variable, all the way down
One assignment followed from name to namespace to object header to the bytes at an address — in Python, in Rust, and in assembly.
References, ownership & aliasing
Pointers, Python's reference semantics, and the borrow checker as a memory tutor that refuses to compile until you understand.
Arrays versus linked structures
Why contiguous memory beats pointer-chasing often enough to overturn the complexity on paper. Cache lines, introduced early.
Data structures
Days 8–15Every structure from its memory layout up, including what CPython's list and dict actually do underneath.
Dynamic arrays & amortized analysis
Three proofs that append is O(1) amortized, and the real growth formula CPython uses.
Hashing & collisions
What a hash function owes you, why collisions are unavoidable, and the cliff at high load factor.
CPython's dict & set
The compact layout that made insertion order a language guarantee, perturbed probing, and hash randomisation.
Linked structures, deques, stacks
Why Python's deque is a list of blocks rather than a list of nodes, and the monotonic stack as a competitive staple.
Trees, BSTs & balancing
The invariant, the degeneration, the rotations — and traversal in O(1) space.
B-trees & disk-oriented structures
Why databases count fetches rather than comparisons, and what that does to the shape of a tree.
Heaps & priority queues
A complete tree with no pointers at all, and the proof that building one is linear.
Tries, union-find & graph layout
Prefix lookup independent of dictionary size, near-constant merging, and the memory arithmetic that settles list versus matrix.
Algorithms core
Days 16–23Complexity derived rather than memorised. Sorting with its lower-bound proof, binary search, recursion, dynamic programming.
Complexity, rigorously
O, Θ and Ω as three different claims. Amortized analysis three ways. Why constants still decide real performance.
Sorting & the lower bound
Merge, quick, and the decision-tree proof that no comparison sort can beat n log n.
Timsort & beating n log n
Run detection and galloping — and the conditions under which counting and radix sort win outright.
Binary search & invariants
Commit to a half-open interval and off-by-ones stop happening. Then searching the answer space instead of the array.
Recursion & the Master theorem
What a call actually costs, all three cases of the theorem, and why Python has no tail calls.
Dynamic programming: state design
Designing the state is the step people skip. Memoization versus tabulation and their different space profiles.
DP: grids, knapsack, bitmask
Edit distance, the loop direction that breaks 0/1 knapsack, and subset DP at 2ⁿ states.
Greedy & exchange arguments
When a local choice is provably global — and how to tell before writing the wrong solution.
Graphs & search
Days 24–28Traversal, shortest paths, spanning trees, flow, and pruned search.
Traversal, topological sort, cycles
BFS and DFS by memory profile, ordering by dependency, and three-colour cycle detection.
Shortest paths
Dijkstra and the exact step where a negative edge breaks its invariant. Bellman-Ford, Floyd-Warshall, 0-1 BFS.
Spanning trees & flow
The cut property, then max-flow min-cut and bipartite matching as a flow problem in disguise.
Backtracking & pruning
Search as a tree you cut. Constraint ordering, and meet-in-the-middle halving the exponent.
Contest simulation I
Timed, unassisted, ramping to hard. The value is the editorial afterwards.
Strings
Days 29–33Pattern matching from KMP to Aho-Corasick and suffix arrays — plus what Python's own string methods really run.
String matching: KMP and Z
The failure function, why no character is examined twice — and what CPython's find actually uses instead.
Rolling hashes & many patterns
Rabin-Karp, Boyer-Moore's skipping, and Aho-Corasick searching thousands of patterns in one pass.
Suffix arrays & LCP
Construction by sorting-doubling, and the problems the pair unlocks.
Python's text toolkit, inside
Every string method and the algorithm behind it. Why the regex engine backtracks, and what Unicode normalisation fixes.
Segment trees, Fenwick, sparse tables
Range queries chosen by query pattern rather than habit, with lazy propagation.
Data & SQL
Days 34–40The relational model, query planning, join algorithms, indexes, transactions, and how rows sit on disk.
The relational model
Declare what, let the planner decide how. Normal forms by the anomaly each one removes.
SQL mechanics
Joins, correlated subqueries that are accidentally quadratic, recursive CTEs, and window functions.
How a query executes
Parse, plan, optimise, execute — and reading the gap between estimated and actual rows.
Join algorithms
Nested loop, hash join, sort-merge. Why join order matters more than join algorithm.
Indexes
The left-prefix rule, covering indexes, and the half people skip: every index slows every write.
Transactions & isolation
Each anomaly mapped to the level that prevents it. MVCC, and why consistent lock ordering fixes deadlocks.
Storage engines
Pages, tuple headers, the write-ahead log, and why analytics moved to columnar.
The machine
Days 41–47Bytecode to ARM64, cache and pipeline, allocators, concurrency, and the kernel boundary.
How code actually runs
Source to bytecode to the eval loop; source to LLVM to ARM64. Why a JIT needs warmup.
Reading ARM64 assembly
Registers, load/store, the calling convention — then a loop mapped instruction by instruction.
Cache, pipeline, prediction
Real latencies, the 64-byte line, and two identical-complexity programs an order of magnitude apart.
Memory management & allocators
Free lists and fragmentation, refcounting plus cycle collection, and RAII enforced by a compiler.
Threads, races & locks
What a data race is at the instruction level, what the GIL actually protects, and the four deadlock conditions.
Atomics, ordering & async
Compare-and-swap, why the CPU reorders your stores, and why one blocking call freezes an event loop.
I/O, syscalls & the kernel
What crossing into the kernel costs, why buffering exists, and how one thread watches ten thousand sockets.
Synthesis
Days 48–50Profiling, and a capstone on a system running in production.
Profiling & the optimisation ladder
Measure first. Then complexity, structure, batching, caching, idiom, native code — parallelism last.
Contest simulation II
Comprehensive, timed, hardest calibration, including a query-design problem.
Capstone
A real service profiled, its genuine bottleneck fixed, and the reasoning written from complexity down to syscall count.