National University of Singapore · FACULTY OF COMPUTER SCIENCE

CS1010E Chap.1 Problem Solving with Programming

- one subject, every graph, every model, every mark
8 Chapters3-page Bible
Our own words - no uploaded lecturer files
Updated for this semester
Chapter 1 of 6 · CS1010E

Problem Solving with Programming

Where programming actually begins

Programming in CS1010E is framed as problem solving first and typing second. Before a single line of Python exists, you are expected to read a problem specification closely, decide what the inputs and outputs are, and design an algorithm that connects them. Only then is the algorithm translated into a program, and only after testing and debugging is that program trusted.

The course learning outcomes follow the same order: analyse a specification and produce an algorithmic solution, implement it with software tools, then trace, test and debug it, all while keeping a readable style and a modular structure.

An algorithm here means a well-defined computational procedure: a set of instructions that accepts some values as input and produces a value, or a collection of values, as output.

Four properties separate an algorithm from a vague recipe. Every step must be exact, meaning deterministic. The procedure must be effective, which covers correctness first and efficiency second. It must be general, working for any valid input rather than just the examples you tried. Finally it must terminate instead of running forever.

Two ways to write the same idea

Python is a multi-paradigm language.

In the declarative style you say what to compute, leaning on higher-order abstractions such as map, filter and reduce, and the program carries no changing state. In the imperative style you describe how to compute it, storing values in variables and updating them with statements inside sequence, branch and loop structures.

The course introduces the declarative style first because it handles most common problems, then turns to imperative techniques when finer control is needed.

Abstraction ties the two together. Once a small helper exists, such as a function that increments a value or one that finds a remainder, you call it without re-deriving how it works each time.

Breaking a problem into simpler abstractions and solving it incrementally is one of the core skills the course names, alongside testing, verification, debugging and sensible use of modern software tools.

Readability matters as much as a correct result.

A program is also a medium for conveying your design and reasoning to another person, so clear names, short comments that state inputs and expected outputs, and small well-named functions are part of the job rather than decoration.

Code that only its author can follow is hard to grade, hard to debug and hard to revise from later.

Why state changes deserve suspicion

The imperative style introduces a hazard the declarative style avoids: the order of assignments. When one statement overwrites a variable that a later statement still needs, the program can run cleanly and still return the wrong number.

Spotting this requires tracing variable values line by line and comparing the result with an answer you computed independently, which is exactly the habit the edit, run, compare and debug loop builds.

In this chapter

What this chapter covers

  • 01

    Definition of an algorithm as input to output

  • 02

    Exactness, effectiveness, generality and termination

  • 03

    Declarative style with map, filter and reduce

  • 04

    Imperative style with variables and loops

  • 05

    Abstraction through small helper functions

  • 06

    Edit, run, compare and debug cycle

  • 07

    Choosing test cases beyond the given samples

  • 08

    Statement order and the temporary variable fix

Worked example · free

Designing and testing a quotient function by repeated subtraction

Q [6 marks]. Design a Python function quot(a, b) that returns how many whole times b fits into a, for a non-negative integer a and a positive integer b, using only comparison, subtraction and addition. Express it declaratively as a conditional expression, trace quot(17, 5), and name three test cases that check generality. The step weighting shown here is an AskSia study allocation and is not a University marking scheme.
Figure 1.1.Figure 1.1. The four stages of computational problem solving. The dashed return arrow is the normal case, not a failure: most programs go round it several times. problem algorithm Python program test and debug what is asked input to output what or how expected vs actual fix, then rerun every case
Figure 1.1. The four stages of computational problem solving. The dashed return arrow is the normal case, not a failure: most programs go round it several times.
  • 2State the algorithm: if a is smaller than b, b fits zero times; otherwise it fits once more than it fits into a minus b.
  • 1Translate to Python: def quot(a, b): return 0 if a < b else 1 + quot(a - b, b).
  • 2Trace quot(17, 5) through 12, 7 and 2, where 2 is less than 5 and the chain stops.
  • 1Choose tests at the boundaries: a smaller than b, a an exact multiple of b, and a equal to 0.
The rule is quot(a, b) = 0 when a < b, otherwise 1 + quot(a - b, b), written in Python as return 0 if a < b else 1 + quot(a - b, b). Tracing quot(17, 5): 17 is not less than 5, so the result is 1 + quot(12, 5); 12 gives 1 + quot(7, 5); 7 gives 1 + quot(2, 5); and 2 is less than 5, so quot(2, 5) is 0. Adding back up gives 1 + 1 + 1 + 0 = 3. The procedure terminates because a drops by b, a positive amount, on every call until it falls below b. For generality, quot(4, 5) should return 0 (smaller than the divisor), quot(15, 5) should return 3 (exact multiple, where the stopping test must use a < b rather than a <= b) and quot(0, 3) should return 0. Running all four calls in Python gives 3, 0, 3 and 0, matching the hand-computed expectations.
Sia tip — Before running quot, write the expected value of every test call beside it, then compare: quot(15, 5) must give 3, and getting 2 means the stopping test is off by one.
Glossary

Key terms

Algorithm
A well-defined computational procedure made of instructions that takes input values and produces an output value or set of values.
Exactness
The property that every step of an algorithm is deterministic, so the same state always leads to the same next action.
Effectiveness
The requirement that an algorithm gives the correct expected output and, secondly, does so efficiently with minimal resources.
Generality
The property that an algorithm produces the expected output for any valid input, not only for sample cases.
Termination
The guarantee that an algorithm finishes after a finite number of steps instead of running forever.
Declarative Paradigm
A programming style that states what to compute using higher-order abstractions such as map, filter and reduce, without changing program state.
Imperative Paradigm
A programming style that describes how to compute a result by storing values in variables and updating them with statements.
Abstraction
Reduces complexity by hiding unnecessary details behind a named operation, so the caller can focus on the main problem.
FAQ

Problem Solving with Programming FAQ

Is an algorithm the same thing as a program?

No. An algorithm is the designed procedure, and a program is its translation into a language a machine can execute. One algorithm can be written as several different Python programs, declarative or imperative, and each translation still has to be tested separately.

Why does a correct-looking loop return the wrong number without any error?

Python only reports errors it can detect, such as bad syntax or an invalid operation. If a variable is overwritten before a later statement reads its old value, every operation is still legal, so the loop finishes normally and hands back a wrong but believable result.

Is hard coding the sample answers ever acceptable in assignments?

No. Returning fixed outputs for the published inputs is penalised, and it breaks the generality property because any unseen input gets a meaningless answer. Tasks are graded mainly on correctness, which means the logic has to hold for inputs beyond the samples you were given.

Should I learn map, filter and reduce before loops?

The course deliberately starts with the declarative style because it covers most common problems with less state to track. Loops and other imperative techniques arrive later, when you need finer control over how the computation proceeds step by step.

How many test cases should I write for a small function?

Enough to touch every branch and every boundary. A practical minimum is one ordinary case, one case at each edge of the valid input range, and one case per distinct outcome the function can return, each with its expected value written down before running.

Study strategy

Exam move

Take any short procedure from this chapter and check it against the four properties out loud: exact, effective, general, terminating. Then rewrite one imperative loop with its two assignments swapped, predict the new output by tracing variable values on paper, and run it in Python to confirm your trace.

Working through Problem Solving with Programming in CS1010E? Sia is AskSia’s AI Computer Science tutor — ask any CS1010E Problem Solving with Programming question and get a clear, step-by-step explanation grounded in how CS1010E is taught and assessed. Read this chapter free, then take your hardest questions to Sia.

A+Everything unlocked
Unlocks this Bible + all 21 of your National University of Singapore subjects - and 1,000+ Bibles across every Australian university.
Sia - your CS1010E tutor, unlimited, worked the way the exam marks it
The full 3-page Bible + practice bank with worked solutions
Chrome extension - sync your LMS so Sia knows your deadlines
Bilingual EN / Chinese on every Bible and every Sia answer
$0.99 Trial
30-day money-back · cancel in one tap · how it works