AP CSP Pseudocode: The Complete Guide with Practice Problems (2026)
Share
AP CSP Pseudocode: The Complete Guide with Practice Problems (2026)
Master every symbol, keyword, and pattern that appears on the AP Computer Science Principles exam — with hard MCQ practice built in.
What You’ll Learn in This Guide
- Why College Board Pseudocode Trips Students Up
- The Complete Syntax Cheat Sheet
- College Board Pseudocode vs. Python
- Operators, Expressions & Assignment
- Conditionals: IF / ELSE IF / ELSE
- Loops: REPEAT TIMES vs REPEAT UNTIL
- Lists and List Procedures
- Procedures and RETURN
- Robot Grid Problems
- Hard MCQ Practice: 8 Questions
- Most Common Pseudocode Errors
Why College Board Pseudocode Trips Students Up
Here’s the uncomfortable truth: students who take AP CSP in Python, JavaScript, or Scratch all hit the same wall on exam day. The College Board writes every single algorithm question in its own pseudocode — not Python, not Java, not anything you coded with all year.
That pseudocode uses a left-pointing arrow (←) for assignment, angle brackets for list indexing, and specific keywords like REPEAT UNTIL that have no direct equivalent in most languages students know. If you have not drilled this syntax cold, you will misread questions under timed pressure.
The good news: the pseudocode is small. There are about a dozen keywords, three loop types, two Boolean operators, and one list structure. Once you own the reference table below, the logic of each question is the only thing left to solve.
The Complete Syntax Cheat Sheet
Print this out. Tape it above your desk. This is the only pseudocode on the AP CSP exam.
x ← INPUT()
NOT true → false
{ block }Executes block only if condition is true. Curly braces mark the block.
{ block }
ELSE
{ block }Two-branch selection. Exactly one branch executes.
{ block }Executes block exactly n times. n is fixed when the loop starts.
{ block }Checks condition AFTER each iteration. Loops while condition is FALSE; exits when condition becomes TRUE.
{ block }Iterates through each element in list, assigning it to item in sequence.
{ block }Defines a reusable procedure. Parameters are local to the procedure body.
College Board Pseudocode vs. Python
If you learned Python, this side-by-side comparison will be the fastest way to lock in the differences. Pay close attention to assignment, list indexing, and loop exit conditions — those are where most students lose points.
| Concept | Python | College Board Pseudocode |
|---|---|---|
| Assignment | x = 5 | x ← 5 |
| Equality check | x == 5 | x = 5 |
| Output | print(x) | DISPLAY(x) |
| First list index | myList[0] | myList[1] |
| Count-controlled loop | for i in range(5): | REPEAT 5 TIMES { } |
| Condition-controlled loop | while not done: | REPEAT UNTIL(done) { } |
| For-each loop | for item in myList: | FOR EACH item IN myList { } |
| Add to end of list | myList.append(val) | APPEND(myList, val) |
| List length | len(myList) | LENGTH(myList) |
| Logical NOT | not condition | NOT condition |
| Define a function | def name(params): | PROCEDURE name(params) { } |
| Return a value | return value | RETURN(value) |
| Remainder | a % b | a MOD b |
Operators, Expressions & Assignment
The assignment arrow is the most visually distinctive part of College Board pseudocode. Every variable gets its value through ←, and you should read it as “gets the value of.” The right side is fully evaluated first, then stored in the variable on the left.
This means you can write things like:
count ← count + 1
This reads “count gets the current value of count plus one” — a standard increment. The old value of count is used on the right side before the new value is stored.
MOD in Depth
The MOD operator returns the remainder from integer division. It is one of the most tested operators on the exam because of its usefulness in determining divisibility, cycling through values, and extracting digits.
// Is x even? IF(x MOD 2 = 0) { DISPLAY("even") } ELSE { DISPLAY("odd") } // Cycle through 0-4 (five positions) regardless of how large n grows position ← n MOD 5 // Last digit of a number lastDigit ← num MOD 10
Conditionals: IF / ELSE IF / ELSE
AP CSP pseudocode does not have a built-in ELSE IF keyword. Multi-branch logic is written by nesting an IF inside an ELSE block. This is an important distinction because the exam will show you nested structures and ask you to trace the exact path of execution.
IF(score ≥ 90) { DISPLAY("A") } ELSE { IF(score ≥ 80) { DISPLAY("B") } ELSE { DISPLAY("C or below") } }
When tracing a conditional, identify the first condition that evaluates to true. Once a branch executes, none of the other branches run — execution jumps to the code after the entire IF/ELSE structure.
(n ≥ 10) AND (n ≤ 20). Using OR here would be a logic error.
Loops: REPEAT TIMES vs. REPEAT UNTIL
There are two critical differences between the two loop types that the exam exploits constantly.
REPEAT n TIMES runs exactly n times. The count does not change based on what happens inside the loop. If n is 5, the block executes exactly 5 times, period.
REPEAT UNTIL(condition) checks its condition at the END of each iteration. This means the loop body always runs at least once, even if the condition starts out true. The loop continues while the condition is false and exits the moment the condition becomes true.
count ← 0 REPEAT 4 TIMES { count ← count + 1 } // count is now 4 DISPLAY(count) // Output: 4
count ← 0 REPEAT UNTIL(count = 4) { count ← count + 1 } // Stops when count reaches 4 DISPLAY(count) // Output: 4
REPEAT UNTIL(count = -1) while only incrementing count, it will never reach -1. The exam tests whether you can identify these broken loops.
FOR EACH in Practice
FOR EACH is the cleanest loop for processing every element of a list. The loop variable takes on each element’s value in order, from index 1 to the end.
scores ← [87, 94, 72, 88, 95] total ← 0 FOR EACH score IN scores { total ← total + score } average ← total / LENGTH(scores) DISPLAY(average) // Output: 87.2
Lists and List Procedures
Lists in College Board pseudocode are ordered, mutable, and 1-indexed. The four procedures — APPEND, INSERT, REMOVE, and LENGTH — are all tested on the exam, often in combination.
Tracing INSERT and REMOVE
INSERT and REMOVE shift elements, which changes the index of every element after the target position. This is a common source of off-by-one errors when students trace code.
letters ← ["A", "B", "C", "D"] // letters[1]="A", letters[2]="B", letters[3]="C", letters[4]="D" INSERT(letters, 2, "X") // "X" goes to index 2, B/C/D shift right // letters[1]="A", letters[2]="X", letters[3]="B", letters[4]="C", letters[5]="D" REMOVE(letters, 3) // "B" (now at index 3) is removed, C/D shift left // letters[1]="A", letters[2]="X", letters[3]="C", letters[4]="D" DISPLAY(letters[2]) // Output: X
Procedures and RETURN
A procedure is a named block of code that can be called by name. When a procedure includes a RETURN statement, it sends a value back to wherever it was called from and immediately stops executing. Any code after RETURN inside the procedure is unreachable.
PROCEDURE max(a, b) { IF(a > b) { RETURN(a) } RETURN(b) } result ← max(14, 9) DISPLAY(result) // Output: 14
DISPLAY(doSomething(10, 20)) where the procedure returns before reaching the second DISPLAY — tests exactly this concept.
Robot Grid Problems
Robot problems appear on almost every AP CSP exam. The robot is represented by a triangle pointing in the direction it faces. All four procedures manipulate the robot’s position or orientation, and you must mentally simulate each step.
The key rules: ROTATE_LEFT and ROTATE_RIGHT change direction but do NOT move the robot. MOVE_FORWARD moves exactly one square in the current facing direction. CAN_MOVE checks for walls before moving and is typically used in conditional logic.
// Move robot to a gray square while navigating around walls REPEAT UNTIL(CAN_MOVE(forward) = false) { MOVE_FORWARD() } ROTATE_RIGHT() MOVE_FORWARD()
Hard MCQ Practice: 8 Questions
Use the predict-first strategy: trace the code and form your answer before reading the choices. Then eliminate obviously wrong answers before selecting.
num ← 2
REPEAT UNTIL(num = 10)
{
IF(num MOD 2 = 0)
{
DISPLAY(num)
}
num ← num + 2
}
- A) The loop increments by 2 instead of 1, causing it to skip odd numbers.
- B) The condition
num MOD 2 = 0is never false for the values visited, making the IF check redundant, but the code still displays correct output. - C) The condition
num = 10causes the loop to exit before displaying 10, so 10 is never shown. - D) The REPEAT UNTIL loop will never execute because num begins at 2 and the condition
num = 10is false initially.
REPEAT UNTIL exits when the condition becomes TRUE. The condition is num = 10. The loop checks this condition at the END of each iteration. After displaying 8 and adding 2, num becomes 10. The condition is now true, so the loop exits WITHOUT executing the body again — 10 is never displayed. The fix is to change the condition to num > 10.
Eliminate trash first: Choice A is wrong because skipping odd numbers is intentional here — we want evens only. Choice D is wrong because REPEAT UNTIL checks the condition at the END, so the body always runs at least once. Choice B correctly identifies that the IF is redundant but incorrectly claims the output is correct — 10 is still missing.
PROCEDURE mystery(numList)
{
result ← 0
FOR EACH val IN numList
{
IF(val MOD 2 ≠ 0)
{
result ← result + val
}
}
RETURN(result)
}
Which of the following statements about mystery are true?I. Calling
mystery([2, 4, 6]) returns 0.II. Calling
mystery([1, 2, 3]) returns 6.III. The procedure sums all values in the list that are divisible by 2.
- A) I only
- B) I and II only
- C) II and III only
- D) I, II, and III
Evaluate each independently:
Statement I: mystery([2, 4, 6]) — All three values are even (MOD 2 = 0), so the condition MOD 2 ≠ 0 is never true. result stays 0. RETURN(0). TRUE.
Statement II: mystery([1, 2, 3]) — val=1: 1 MOD 2 = 1 ≠ 0, so result ← 0+1=1. val=2: even, skip. val=3: 3 MOD 2 = 1 ≠ 0, so result ← 1+3=4. Wait — result is 4, not 6. WAIT. Re-read: 1+3=4, not 6. Statement II claims the return is 6. FALSE.
Wait — re-check: 1 MOD 2 = 1 ≠ 0 ⇒ add 1. 3 MOD 2 = 1 ≠ 0 ⇒ add 3. Total = 1 + 3 = 4. Return is 4, not 6. Statement II is FALSE.
Statement III: The procedure sums values where val MOD 2 ≠ 0, which means values that are NOT divisible by 2 — i.e., ODD numbers. Statement III says it sums values divisible by 2. FALSE.
Only Statement I is true. Correct answer: A.
Note: This question was written with a deliberate trap in Statement II to force careful arithmetic. If you predicted "I only" before looking at choices, you got it right.
items ← [10, 20, 30, 40] temp ← items[1] items[1] ← items[4] items[4] ← items[1] DISPLAY(items)
- A) The variable
tempis assigned but never used, so the original value ofitems[1]is overwritten before it can be stored initems[4]. - B) The list index 4 is out of bounds because College Board pseudocode lists are 0-indexed.
- C) The DISPLAY statement will show the list before the swap completes.
- D) There is no error; the code correctly swaps the first and last elements.
Trace step by step: temp ← items[1] = 10. items[1] ← items[4] = 40. Now items[1] = 40. items[4] ← items[1] = 40 (but items[1] is NOW 40, not the original 10!). Result: items = [40, 20, 30, 40] — a copy, not a swap. The fix is to use temp: items[4] ← temp.
Eliminate trash: Choice B is wrong — College Board pseudocode uses 1-based indexing, so index 4 is valid for a 4-element list. Choice C is wrong — DISPLAY runs after all assignment lines complete. Choice D is wrong — there is definitely an error.
x ← 1
REPEAT UNTIL(x > 5)
{
IF(x MOD 3 = 0)
{
DISPLAY(x)
}
x ← x + 1
}
- A) 3
- B) 3 6
- C) 1 2 3 4 5
- D) Nothing is displayed.
Trace: x=1 (1 MOD 3=1, no display, x←2) → x=2 (2 MOD 3=2, no display, x←3) → x=3 (3 MOD 3=0, DISPLAY 3, x←4) → x=4 (4 MOD 3=1, no display, x←5) → x=5 (5 MOD 3=2, no display, x←6) → condition check: 6 > 5 is true, loop exits. Only "3" was displayed.
Choice B is wrong because the loop exits before x reaches 6 — 6 is never inside the loop body when x=6 because the condition is checked and exits immediately. This is the REPEAT UNTIL timing trap.
PROCEDURE checkValue(n)
{
IF(n < 0)
{
DISPLAY("negative")
RETURN(0)
}
IF(n = 0)
{
RETURN(0)
}
DISPLAY("positive")
RETURN(n * 2)
}
DISPLAY(checkValue(-3))
What is displayed when this code executes?
- A) negative
- B) negative 0
- C) negative positive 0
- D) 0
Trace: checkValue(-3) is called. n = -3. First IF: -3 < 0 is true. DISPLAY("negative") ⇒ outputs "negative". RETURN(0) ⇒ procedure sends back 0 and exits. Back in the outer DISPLAY: DISPLAY(checkValue(-3)) = DISPLAY(0) ⇒ outputs "0". Total output: "negative 0".
Choice A misses the outer DISPLAY of the returned value. Choice C incorrectly includes "positive" — RETURN exits before reaching that line. Choice D misses the DISPLAY("negative") inside the procedure.
data ← [5, 10, 15, 20, 25] INSERT(data, 3, 99) REMOVE(data, 1) APPEND(data, 0)Which of the following statements about the final state of
data are correct?I. The length of
data is 6.II.
data[1] equals 10.III.
data[3] equals 15.
- A) I only
- B) II only
- C) I and II only
- D) I, II, and III
Start: [5, 10, 15, 20, 25] (length 5).
INSERT(data, 3, 99): Insert 99 at index 3. Elements at 3+ shift right. Result: [5, 10, 99, 15, 20, 25] (length 6).
REMOVE(data, 1): Remove element at index 1 (which is 5). Remaining elements shift left. Result: [10, 99, 15, 20, 25] (length 5).
APPEND(data, 0): Add 0 to end. Result: [10, 99, 15, 20, 25, 0] (length 6).
I: Length = 6. TRUE. II: data[1] = 10. TRUE. III: data[3] = 15. TRUE. Wait — data is [10, 99, 15, 20, 25, 0], so data[3] = 15. TRUE. All three are true — answer is D.
Correction verified: I (length 6 = TRUE), II (data[1]=10 = TRUE), III (data[3]=15 = TRUE). Answer is D.
true if a number is between 1 and 100 inclusive, and false otherwise. Four student submissions are shown below. Which submission contains a logical error?
- A)
PROCEDURE inRange(n) { RETURN(n ≥ 1 AND n ≤ 100) } - B)
PROCEDURE inRange(n) { RETURN(NOT(n < 1 OR n > 100)) } - C)
PROCEDURE inRange(n) { RETURN(NOT(n < 1) AND NOT(n > 100)) } - D)
PROCEDURE inRange(n) { RETURN(NOT(n < 1 AND n > 100)) }
Test with n = 0 (should return false). Choice D: NOT(0 < 1 AND 0 > 100) = NOT(true AND false) = NOT(false) = TRUE. But 0 is out of range. Choice D incorrectly returns true for out-of-range values.
Choice A: n ≥ 1 AND n ≤ 100. For n=0: false AND true = false. Correct. For n=50: true. For n=101: false. Correct.
Choice B applies De Morgan’s Law correctly: NOT(n < 1 OR n > 100) = NOT(out of range). Correct.
Choice C: NOT(n < 1) AND NOT(n > 100) = (n ≥ 1) AND (n ≤ 100). Same as A. Correct.
The error in D is using AND inside the NOT when OR is needed. By De Morgan’s Law, NOT(a AND b) = NOT a OR NOT b, which is too permissive.
found ← false
i ← 1
REPEAT UNTIL(found OR i > LENGTH(myList))
{
IF(myList[i] = target)
{
found ← true
}
i ← i + 1
}
DISPLAY(found)
Which of the following best describes what this algorithm does?
- A) Displays true if every element in myList equals target, and false otherwise.
- B) Displays true if myList contains at least one element equal to target, and false otherwise.
- C) Displays the index of the first occurrence of target in myList, or false if not found.
- D) Displays true if myList contains exactly one element equal to target, and false otherwise.
The algorithm initializes found to false and searches through the list. The moment it finds one element equal to target, it sets found to true and the loop exits early (because found is now true, satisfying the REPEAT UNTIL condition). At the end, found is true if ANY element matched.
Choice A is wrong — the algorithm stops at the first match, not after checking all elements for equality. Choice C is wrong — found is Boolean, not an index. Choice D is wrong — the algorithm does not count occurrences; it just checks existence.
Most Common Pseudocode Errors on the AP Exam
After reviewing thousands of student answers in my 11 years of teaching, these are the mistakes that appear most often on AP CSP pseudocode questions.
Forgetting that lists start at index 1. Students who code in Python instinctively write myList[0]. In College Board pseudocode, that index does not exist for a standard list. Always add 1 when translating your mental model.
Misreading REPEAT UNTIL exit timing. The condition is checked AFTER the block runs. If you need to know whether a value is displayed, trace through the entire body before checking the exit condition for that iteration.
Using = for assignment in comparisons. In pseudocode, = means equality check inside conditions. Assignment uses ←. The exam will show you conditionals with = and you must read it as a test, not an assignment.
Assuming code after RETURN executes. RETURN is an immediate exit. Anything written in the procedure body below a RETURN is dead code. The exam tests this directly with DISPLAY statements placed after RETURN.
Confusing AND with OR in range checks. To be inside a range, a value must satisfy both conditions — AND. To be outside a range, it fails at least one — OR. Students who mix these up produce logic errors that only manifest on edge cases, which is exactly what the exam uses.
Not accounting for element shifting after INSERT and REMOVE. After INSERT or REMOVE, all indices after the target position change. Trace list state step by step rather than trying to track everything in your head at once.
Still Struggling with Pseudocode or Any AP CSP Topic?
My students score 5s at 3.6× the national average. One-on-one sessions are the fastest way to close gaps before exam day.