Computer Science › Foundations of Computer Science
The four pillars of computational thinking — decomposition, pattern recognition, abstraction, and algorithm design — and why they're a way of thinking, not a way of coding.
Breaking a problem into an ordered sequence of unambiguous steps before writing a single line of real code, using a toy grid-world/robot example to separate algorithmic thinking from syntax.
Naming a piece of memory to hold a value, and the primitive types (int, float, bool, str) every program is built from.
Why floating-point numbers are an approximation of the reals, not the reals themselves, and what that means for equality checks and accumulated error.
Combining values and operators into expressions, and the difference between mathematical equality and assignment's 'store the result here'.
Branching a program's execution with if/elif/else based on a boolean condition.
Repeating a block of code with while and for, and the loop invariants that keep a repeated computation correct.
Measuring how a program's actual running time grows as its input grows, by timing it and by counting its operations.
Describing an algorithm's growth rate independent of any specific machine, using Big-O to bound its worst case.
Storing an ordered, growable sequence of values in a list, and the difference between a mutable list and an immutable value like a number or string.
A first pass at sorting: comparing simple quadratic sorts (bubble/selection/insertion) against a divide-and-conquer sort (merge sort), and why the comparison matters once Big-O is on the table.
Storing key-value pairs for near-constant-time lookup by key instead of by position, backed by a hash table.
An immutable, fixed-size sequence — when to reach for a tuple instead of a list, and how tuple unpacking reads cleaner than manual indexing.
Two variables can point at the same mutable list in memory — mutating through one changes what the other sees, unless you clone instead of alias.
Wrapping a block of logic behind a name so a caller can use it without knowing how it works inside — the mechanism behind computational thinking's abstraction pillar.
A function that solves a problem by calling itself on a smaller version of the same problem, bottoming out at a base case.
Applying recursion to a value's shape — walking a nested list or a string letter-by-letter — rather than to a shrinking number.
Writing test cases before you trust a function, and a systematic process for isolating a bug instead of guessing at print statements.
Raising and catching exceptions for conditions a caller must handle, and assertions for conditions that should never happen at all.
Passing data into a function and getting a result back out — parameter binding, default values, and what a function returns when it doesn't say.
Treating a function itself as a value — assigning it to a variable, passing it as an argument, or writing one inline as a lambda.
Solving equations no closed form covers by successive approximation — exhaustive guess-and-check first, then bisection search cutting the search space in half each step.
Reading a value from the user and printing a result back — the smallest possible feedback loop a program can have.
Part of the Computer Science curriculum.
The four pillars of computational thinking — decomposition, pattern recognition, abstraction, and algorithm design — and why they're a way of thinking, not a way of coding.
Breaking a problem into an ordered sequence of unambiguous steps before writing a single line of real code, using a toy grid-world/robot example to separate algorithmic thinking from syntax.
Naming a piece of memory to hold a value, and the primitive types (int, float, bool, str) every program is built from.
Why floating-point numbers are an approximation of the reals, not the reals themselves, and what that means for equality checks and accumulated error.
Combining values and operators into expressions, and the difference between mathematical equality and assignment's 'store the result here'.
Branching a program's execution with if/elif/else based on a boolean condition.
Repeating a block of code with while and for, and the loop invariants that keep a repeated computation correct.
Measuring how a program's actual running time grows as its input grows, by timing it and by counting its operations.
Describing an algorithm's growth rate independent of any specific machine, using Big-O to bound its worst case.
Storing an ordered, growable sequence of values in a list, and the difference between a mutable list and an immutable value like a number or string.
A first pass at sorting: comparing simple quadratic sorts (bubble/selection/insertion) against a divide-and-conquer sort (merge sort), and why the comparison matters once Big-O is on the table.
Storing key-value pairs for near-constant-time lookup by key instead of by position, backed by a hash table.
An immutable, fixed-size sequence — when to reach for a tuple instead of a list, and how tuple unpacking reads cleaner than manual indexing.
Two variables can point at the same mutable list in memory — mutating through one changes what the other sees, unless you clone instead of alias.
Wrapping a block of logic behind a name so a caller can use it without knowing how it works inside — the mechanism behind computational thinking's abstraction pillar.
A function that solves a problem by calling itself on a smaller version of the same problem, bottoming out at a base case.
Applying recursion to a value's shape — walking a nested list or a string letter-by-letter — rather than to a shrinking number.
Writing test cases before you trust a function, and a systematic process for isolating a bug instead of guessing at print statements.
Raising and catching exceptions for conditions a caller must handle, and assertions for conditions that should never happen at all.
Passing data into a function and getting a result back out — parameter binding, default values, and what a function returns when it doesn't say.
Treating a function itself as a value — assigning it to a variable, passing it as an argument, or writing one inline as a lambda.
Solving equations no closed form covers by successive approximation — exhaustive guess-and-check first, then bisection search cutting the search space in half each step.
Reading a value from the user and printing a result back — the smallest possible feedback loop a program can have.