Ran Wei/CS Series/Module 01
中文
Computer Science Fundamentals — Ran Wei

Module 01: What is computation?

Turn a question into a contract, trace a search, explain why it works and count its work. Then locate that small computation within a running computer.

≈ 5 hours4 sessions3 labs8 exercises8 quiz questions

By the end you can

  • Distinguish a problem specification, an algorithm and a program.
  • State a search contract including empty, absent and duplicate cases.
  • Trace a linear search and explain its changing state.
  • Explain correctness, termination and comparison counts separately.
  • Recognise abstractions and the layers used to run a program.

Before you start

No earlier module or programming experience. Read the small Python notation guide before the labs. You need a browser, a text editor and Python 3.11 or later. No third-party packages are used.

Contents

Study plan

5 hours

Four sessions of 75 minutes. Times are estimates and include hands-on practice. Exercises 6–7 are optional extensions (25 extra minutes). Tick sessions to save progress in this browser.

1

Computation starts with a question

You have four books on a shelf and want to know where The Hobbit is. You could look along the shelf, read each title and stop when you find it. That simple activity contains the ingredients of computation: information, a precise question, a sequence of steps and a result.

Computation transforms information according to rules. The information can describe numbers, text, pictures, movements or relationships. A computer performs those rules using a physical machine; a person can carry out the same small computation with pencil and paper. Computer science studies how to represent problems, construct and analyse procedures, organise systems and understand what computation can and cannot achieve.

Programming is one way to express a procedure so a machine can execute it. Computer science also asks whether the procedure answers the right question, whether it always finishes, how much work it requires and how it fits into a larger system. These questions remain relevant when the programming language changes.

A question made precise

Our catalogue is an ordered list: ["Dune", "Foundation", "The Hobbit", "Dune"]. The question is: what is the index of the first title exactly equal to the target? Count positions from zero. For "The Hobbit", the answer is 2. For "Dune", it is 0. For "Solaris", we choose -1 to mean “absent”.

Notice the decisions already made: order matters, matching is exact, duplicates are possible, and missing books have an explicit result. “Find a book” did not specify any of those. Much of good computing begins with resolving such ambiguities.

Check your understanding

Does counting the books qualify as computation? State its input and output.

Worked solution

Yes. Input: the finite catalogue. Output: its number of entries. Increment a counter once per entry.

2

Specify inputs, outputs and assumptions

A problem specification states the required relationship between inputs and outputs. An algorithm is a procedure for achieving it. A program implements a procedure in a language with defined execution rules. There can be many algorithms for one problem and many programs implementing one algorithm.

PartOur search contract
InputA finite ordered list of titles and a target title.
AssumptionsTitles are strings. The list does not change during this search. Equality is exact and case-sensitive.
Output when presentThe smallest index whose title equals the target.
Output when absent-1, including when the list is empty.
Side effectsThe search does not modify the list.

The assumptions are preconditions: what must hold before the procedure runs. The promised output and unchanged input are postconditions: what must hold after it returns. Together they make a contract. Later modules will use contracts for data structures, network protocols and database transactions.

A sentinel needs care

Here -1 is a sentinel, a chosen value representing absence. Python also permits negative indexing: books[-1] reads the last book. Check whether a result is -1 before using it as an index. A future implementation might return None instead; that would be a different contract.

A library user might expect “dune” to match “Dune”. That would require a new matching rule, for example case-insensitive comparison. Do not quietly change the meaning while claiming the original contract still holds.

Check your understanding

What result is required for an empty catalogue? Is index 0 a missing result?

Worked solution

Return -1 for an empty catalogue. Index 0 is the first valid position in a nonempty catalogue.

3

Describe an algorithm and trace its state

Linear search checks items in their given order. In pseudocode, which expresses the steps without depending on a particular programming language:

FOR each position i, from first to last:
    IF title at i equals target:
        RETURN i
RETURN -1

The final return happens only after all items have been examined. The return inside the loop ends the entire search immediately. That immediate stop gives us the first matching index even when a title occurs twice.

The procedure has state: the information needed to describe where it is in its execution. Here the changing state is the current position and, when we measure work, the number of comparisons. A trace records that state step by step.

PositionTitleEquals The Hobbit?Next action
0DuneNoAdvance
1FoundationNoAdvance
2The HobbitYesReturn 2

The fourth title is never inspected in this run. Predict a trace before running code: doing so forces you to distinguish what you expect from what the program actually does.

Interactive: step through linear search

    Try three experiments. Search for Dune and explain why index 3 is never reached. Search for Solaris and count the comparisons. Select the empty catalogue and explain why returning -1 requires no title comparisons. The demonstration shows the final “list exhausted” step separately; that step is not a title comparison.

    Check your understanding

    Trace a search for Foundation. Which positions are inspected?

    Worked solution

    Inspect 0, then 1. Return 1 after two comparisons; do not inspect 2 or 3.

    4

    Why it is correct, why it finishes, what it costs

    Examples show particular executions. An argument about the procedure covers every input satisfying the contract. We will develop formal proofs later; a short reasoning pattern is enough here.

    Correctness: what stays true?

    Just before we inspect position i, none of the earlier positions contains the target. This is a loop invariant, a statement preserved as the loop advances. It is initially true because there are no earlier positions at index 0. If the current title does not match, adding that title to the inspected prefix preserves the statement. If it matches, the invariant tells us that no earlier match exists, so returning i satisfies the contract. If the list is exhausted, every title was unequal, so returning -1 satisfies the contract.

    Termination: what makes progress?

    For a list with n entries, each unsuccessful iteration advances one position. The number of uninspected entries decreases by one and cannot decrease forever below zero. A match ends the search even sooner. A finite list that remains unchanged therefore guarantees termination.

    Cost: count a defined operation

    Choose one title-equality check as the operation to count. For a nonempty list, a first-position match costs one comparison. A last-position match or an absent target costs n comparisons. An empty list costs zero comparisons. Doubling the number of entries doubles the worst-case comparison count.

    This count is a model, not elapsed time. Comparing two long strings may require examining many characters; a title comparison is not necessarily constant-time when title length varies. The computer, implementation and data also affect seconds on a clock. Module 05 develops these distinctions and introduces Big O. Here, specify the operation and count it accurately.

    Three separate questions

    Does it return the required answer? Does it finish? How much work does it do? A fast wrong answer is still wrong, and a correct answer promised by an infinite loop never arrives.

    Check your understanding

    Why is the empty catalogue compatible with the invariant argument?

    Worked solution

    There are no earlier matches and no entries left to inspect. Every entry is a nonmatch because there are no entries, so -1 is correct.

    5

    Abstraction and the layers of a computer

    An abstraction exposes the properties needed for a task while hiding other details. Treating the catalogue as an ordered list lets us reason about positions without knowing how a particular machine stores strings. Treating search as a function lets another part of a program use the result without repeating the search steps.

    An abstraction must retain what matters. If we replace the ordered list with a collection that has no meaningful order, “first index” loses its meaning. If we keep only titles and discard authors, we cannot answer an author query without adding information.

    1. Problem and applicationA user asks where a title appears in the catalogue.
    2. Algorithm and programLinear search describes the steps; Python expresses them as executable code.
    3. Language implementationThe Python runtime executes operations on lists and strings.
    4. Operating systemManages processes, memory and access to files or devices.
    5. HardwareCPU instructions operate on data stored in memory.
    A simplified view of the layers involved in running our program. These are responsibilities, not a claim that every operation calls every layer. Modules 09–11 examine the boundaries in detail.

    When you run a script, the CPU does not directly understand a book title or the English phrase “find the first match”. A language implementation and machine instructions connect that meaning to physical operations. You can learn to reason about the search before learning all those mechanisms.

    The same separation helps with faults. A requirement might ask for the wrong matching rule; the algorithm might skip index 0; the program might place return -1 inside the loop; the environment might fail to open a file. Identify the responsibility that failed before changing the code.

    Check your understanding

    Can a titles-only abstraction answer who wrote each book? Why?

    Worked solution

    Not in general. Author information was not retained. Add it to the representation or obtain it from another source.

    6

    Common misconceptions

    MisconceptionWhat to check instead
    “Computation is only arithmetic.”Searching text and following a route also transform information according to rules.
    “An algorithm is a Python file.”Distinguish the procedure from its language-specific implementation.
    “It worked once, so it is correct.”Check edge cases and reason about all valid inputs.
    “Index zero means not found.”Zero is a valid position. Our missing sentinel is -1.
    “Four titles means four comparisons.”An early match stops the search; the actual cost depends on the target.
    “All bugs belong in the algorithm.”Separate requirements, procedure, implementation and environment.
    7

    Set up the labs

    Use Python 3.11 or later, a text editor and a terminal. The labs use only Python's standard features; no packages or datasets are needed. Download each script below or copy its code into a file with the same name. In a terminal opened in that folder, run python lab1_trace.py. On Windows, py -3 lab1_trace.py is another option. On systems where Python is named python3, use that command.

    A quoted value such as "Dune" is a string; square brackets hold a list. for repeats the indented block. enumerate supplies an index and an item. if selects a block when a condition is true. == compares values; = assigns a value to a name. Indentation is part of Python's syntax. The labs introduce only the notation needed here; Module 03 teaches programming systematically.

    8

    Lab 1 — Read an execution trace

    Goal: connect pseudocode, state and actual execution. Time: 30 minutes. First predict which lines will print. Then run the script and compare your prediction with the captured output.

    Download lab1_trace.py

    """Module 01, Lab 1: trace a search, one comparison at a time."""
    
    books = ["Dune", "Foundation", "The Hobbit", "Dune"]
    target = "The Hobbit"
    found = -1
    
    for index, title in enumerate(books):
        print(f"inspect {index}: {title}")
        if title == target:
            found = index
            break
    
    print(f"result: {found}")
    
    Captured output
    inspect 0: Dune
    inspect 1: Foundation
    inspect 2: The Hobbit
    result: 2
    

    found = -1 sets the absent result before searching. break exits the loop after a match; the final print still runs. The f before a quoted string lets the print include values inside braces.

    1. Change the target to Dune, then Solaris. Write the predicted traces before running.
    2. Set books = []. Explain why the loop body does not run.
    3. Remove break and search for Dune. Why does the result become 3? Which part of the contract fails?
    4. Restore the original code. Explain the difference between “exit this loop” and “return from this function”.
    Lab discussion

    Dune inspects only index 0; Solaris inspects all four indices and keeps the result -1. An empty list produces only result: -1. Without the break, both occurrences of Dune update found, so the last occurrence wins. That violates the first-match contract. A break leaves the loop; a return leaves the function that contains it.

    9

    Lab 2 — Turn the contract into checks

    Goal: test empty, missing, boundary and duplicate cases. Time: 35 minutes. A def block defines a function. A return supplies its result and ends that call. assert stops the script if its condition is false. Run normally, without Python's -O option, which disables assertions.

    Download lab2_contract.py

    """Module 01, Lab 2: make a contract executable with examples."""
    
    
    def find_first(items, target):
        """Return the first matching index, or -1 if target is absent."""
        for index, item in enumerate(items):
            if item == target:
                return index
        return -1
    
    
    cases = [
        ([], "Dune", -1),
        (["Dune"], "Dune", 0),
        (["Dune"], "Solaris", -1),
        (["Dune", "Solaris"], "Solaris", 1),
        (["Dune", "Solaris", "Dune"], "Dune", 0),
    ]
    
    for items, target, expected in cases:
        actual = find_first(items, target)
        assert actual == expected, (items, target, expected, actual)
        print(f"{items!r}, {target!r} -> {actual}")
    
    print("5 cases passed")
    
    Captured output
    [], 'Dune' -> -1
    ['Dune'], 'Dune' -> 0
    ['Dune'], 'Solaris' -> -1
    ['Dune', 'Solaris'], 'Solaris' -> 1
    ['Dune', 'Solaris', 'Dune'], 'Dune' -> 0
    5 cases passed
    
    1. Explain why the five cases exercise different parts of the contract.
    2. Add (["Dune"], "dune", -1) to confirm exact, case-sensitive matching.
    3. Move return -1 inside the loop, immediately after the if block. Predict which checks will fail or which result will change, then run.
    4. Repair the function. Add a check that the input list is unchanged after a call.
    Lab discussion

    The cases cover an empty list, the first position, an absent target, the last position and duplicate titles. With return -1 inside the loop, an empty list falls through and returns None; the first assertion fails. A later-position match is also missed because the search returns after its first nonmatch. To check mutation, save before = items.copy(), call the function and check assert items == before. Passing these examples is useful evidence, but the invariant argument is what covers every valid input.

    10

    Lab 3 — Measure work, not clock speed

    Goal: distinguish input size from work in a particular run. Time: 35 minutes. This script returns a pair: result and comparison count. range(size) produces integers from zero up to, but excluding, size; list collects them. The same equality-search procedure applies to numbers. += 1 increases a counter by one.

    Download lab3_cost.py

    """Module 01, Lab 3: count comparisons instead of timing the computer."""
    
    
    def search_with_cost(items, target):
        comparisons = 0
        for index, item in enumerate(items):
            comparisons += 1
            if item == target:
                return index, comparisons
        return -1, comparisons
    
    
    for size in [0, 1, 4, 8, 16]:
        items = list(range(size))
        missing_index, missing_cost = search_with_cost(items, -1)
        first_index, first_cost = search_with_cost(items, 0)
        print(f"n={size:2}: absent={missing_cost:2}, first={first_cost:2}")
        assert missing_index == -1 and missing_cost == size
        assert first_index == (0 if size else -1)
        assert first_cost == (1 if size else 0)
    
    Captured output
    n= 0: absent= 0, first= 0
    n= 1: absent= 1, first= 1
    n= 4: absent= 4, first= 1
    n= 8: absent= 8, first= 1
    n=16: absent=16, first= 1
    
    1. Predict both counts for a list of length 32.
    2. Add a last-position target using size - 1. For size 0, the target remains absent.
    3. Search for the middle position of a 16-entry list: target 8. Why are there nine comparisons?
    4. State the best and worst comparison counts for a nonempty list. Explain why elapsed time alone would not establish those formulas.
    Lab discussion

    For size 32, absent costs 32 comparisons and first costs 1. Last costs size for a nonempty list and 0 for an empty one. Index 8 is the ninth position because counting begins at zero. Best is 1 and worst is n for n greater than zero. Timing depends on many machine and data details; these exact counts follow from the procedure.

    11

    Exercises with worked solutions

    Try each question before opening its solution. ★ means a direct application; ★★ combines ideas; ★★★ asks you to change the contract or construct an argument.

    Exercise 1 — Specify a counting problem★8 min

    Write a contract for counting occurrences of a target title, including an empty list and duplicates.

    Worked solution

    Input: a finite, unchanged list of strings and a target string. Output: the number of entries exactly equal to the target, a nonnegative integer. Empty input returns 0. Duplicates each contribute one. The list is not modified.

    Exercise 2 — Trace a duplicate★8 min

    Search [A, B, A] for A under our first-match contract. List inspected indices and the returned result. How would a last-match contract differ?

    Worked solution

    Inspect only 0 and return 0. A last-match search must examine the remaining entries; a full forward scan updating the result at each match would return 2 after three comparisons.

    Exercise 3 — Repair an early return★★10 min

    A search returns -1 immediately after the first nonmatch. Give a failing input and explain the repair, including empty input.

    Worked solution

    [A, B] with target B fails: A is unequal, but B was never examined. Move the absent return after the loop so it runs only when all entries have been checked. This also returns -1 for an empty list instead of falling through to None.

    Exercise 4 — Count exact work★★10 min

    A list has 12 entries. How many comparisons find a first match at index 7? How many establish absence? What if the list is empty?

    Worked solution

    Index 7 requires 8 comparisons (indices 0–7). Absence requires 12. An empty list requires 0. These count equality checks, not all machine instructions.

    Exercise 5 — Explain the invariant★★★12 min

    Give the initialisation, preservation and exit arguments for: before inspecting i, no earlier index contains the target.

    Worked solution

    Initially i=0 has no earlier positions. After a nonmatch at i, all positions before i+1 are nonmatches. On a match, no earlier match exists, so i is minimal. On exhaustion, all entries are nonmatches. Finite length and advancing positions establish termination separately.

    Exercise 6 — Find the abstraction loss★★10 min

    You replace the catalogue by its entry count alone. Which queries can it answer: how many entries, where is Dune, or which title is first?

    Worked solution

    Only the number of entries. Many different catalogues have the same count, so the count cannot recover either title identity or order. An abstraction is appropriate relative to the question being asked.

    Exercise 7 — Change the matching rule★★★15 min

    Specify and implement a first-match search for ASCII titles ignoring letter case. Which checks should change?

    Worked solution

    Require ASCII strings and compare item.lower() == target.lower() inside the same loop; keep the absent return after the loop. Now [Dune] with target dune returns 0. Empty, absent and duplicate tests remain necessary. The existing exact-match contract has changed; text matching beyond ASCII needs more careful rules.

    def find_first_ascii_ignore_case(items, target):
        for index, item in enumerate(items):
            if item.lower() == target.lower():
                return index
        return -1
    
    assert find_first_ascii_ignore_case(["Dune"], "dune") == 0
    assert find_first_ascii_ignore_case([], "dune") == -1

    Exercise 8 — Locate a fault★★12 min

    Classify these faults: the requested matching rule is wrong; pseudocode skips index 0; return -1 is indented inside the loop; the script file cannot be opened.

    Worked solution

    Respectively: specification, algorithm, implementation and environment. Check the contract with its user, repair the procedure, repair the code's control flow, or check the command and file path. A fault can involve multiple layers, but this distinction guides the first investigation.

    12

    Self-check quiz

    Choose an answer to see feedback. The score counts answered questions; reset to try again. If scripts are disabled, open the answer key below.

    1

    Which statement specifies a problem rather than an algorithm?

    2

    What does our search return on an empty list?

    3

    Where is the first Dune in [Dune, Foundation, Dune]?

    4

    How many equality comparisons establish absence in 9 entries?

    5

    Which fact ensures this search terminates?

    6

    What does passing five tests establish?

    7

    Why check a returned -1 before indexing a Python list?

    8

    What must an ordered-list abstraction retain?

    Answer key
    1. A — It describes the required result without prescribing the steps.
    2. B — The contract uses -1 for absence, including an empty list.
    3. C — Positions start at zero, and the algorithm stops at the first match.
    4. B — All nine entries must be compared. The final return is not a title comparison.
    5. A — Remaining work decreases to zero; the target may be absent.
    6. C — Tests provide evidence about cases; the invariant argument covers valid inputs generally.
    7. B — Our sentinel convention and Python's indexing rule have different meanings.
    8. A — First-match search needs order and item equality, not those physical details.
    13

    Guided reading

    Read the official Python introduction to lists and the sections on for statements, range, break and defining functions. Focus on the constructs used in the labs; you can skip the other control-flow features for now.

    Write down why an empty list causes zero loop iterations, why range excludes its endpoint and what return does. Then explain how those language rules support our search algorithm. The distinction between a language rule and a problem requirement is the purpose of this reading.

    14

    Review and the next step

    You can now turn a vague search request into a contract, trace a procedure, explain its first-match property, show why it terminates and count its comparisons. You have also located that computation within the layers of a running computer.

    Close the page and reproduce the pseudocode from memory. Trace an empty list, a duplicate match and an absent title. Explain which assumption makes the termination argument work. If one explanation is uncertain, revisit that section before checking off your last session.

    The next module is Representing information: how bits encode integers and text, and why some numbers cannot be represented exactly. The course overview links to all 14 modules.

    15

    Key terms

    TermMeaning in this module
    ComputationTransformation of information according to rules.
    SpecificationThe required relationship between input and output.
    Algorithm / programA procedure / an implementation in a programming language.
    State / traceCurrent execution information / a sequence recording it.
    ContractPreconditions and postconditions for an operation.
    InvariantA property preserved at a chosen point through iterations.
    TerminationThe procedure eventually finishes.
    AbstractionA model exposing relevant properties while hiding details.
    SentinelA chosen value representing a special outcome such as absence.