Learning Goals
3 minBy the end of this lesson you can:
- Translate a short English brief into a working Python function in under five minutes.
- Recognise which Level 1 tool fits each problem (string method, list method, loop, condition, function).
- Decide when to stop polishing and move on — "works and tested" is the bar, not "perfect".
The Rules
3 minOpen speed_round.py. Set a timer for 40 minutes (4 minutes per problem). Three rules:
- Don't plan. Read the brief, type something straight away, fix as you go. Planning is a luxury for slower problems.
- Use the test at the bottom. Each problem comes with one assertion you can paste in. If it passes silently, you're done. If it raises
AssertionError, fix and retry. - If stuck for more than 4 minutes, skip. Mark with
TODOand move on. Come back at the end.
Aim for 7/10 by the timer. 9/10 is excellent. 10/10 means you're ready for the capstone.
assert to testassert expression does nothing if the expression is true, and raises AssertionError if it's false. assert square(3) == 9 silently passes when your function is right and crashes loudly when it's wrong. Cheap unit tests, built into the language.
The Ten Problems
40 minProblem 1 · add(a, b)
Return the sum of two numbers.
# Test assert add(2, 3) == 5 assert add(-1, 1) == 0
Problem 2 · last_letter(word)
Return the last letter of word. Use a slice or negative index.
# Test assert last_letter("python") == "n" assert last_letter("a") == "a"
Problem 3 · is_even(n)
Return True if n is even, else False.
# Test assert is_even(0) == True assert is_even(7) == False assert is_even(-4) == True
Problem 4 · count_vowels(text)
Return how many vowels (a, e, i, o, u — any case) are in text.
# Test assert count_vowels("hello") == 2 assert count_vowels("PYTHON") == 1 assert count_vowels("xyz") == 0
Problem 5 · shout(text)
Return text uppercase with three exclamation marks at the end.
# Test assert shout("hi") == "HI!!!" assert shout("nasi lemak") == "NASI LEMAK!!!"
Problem 6 · biggest(nums)
Return the largest item in a non-empty list. Don't use the built-in max.
# Test assert biggest([3, 1, 4, 1, 5, 9, 2, 6]) == 9 assert biggest([-7, -3, -10]) == -3 assert biggest([42]) == 42
Problem 7 · reverse(text)
Return text spelled backwards. One-line slice from PY-L1-24.
# Test assert reverse("malam") == "malam" assert reverse("hello") == "olleh" assert reverse("") == ""
Problem 8 · average(nums)
Return the average of a list of numbers. Return 0 for an empty list.
# Test assert average([10, 20, 30]) == 20 assert average([1, 2, 3, 4]) == 2.5 assert average([]) == 0
Problem 9 · count_word(text, word)
Return how many times word appears in text. Case-insensitive. Use the string method .count() after lower-casing both sides.
# Test assert count_word("Selamat datang ke Selamat Hub", "selamat") == 2 assert count_word("hello world", "x") == 0 assert count_word("AaAaA", "a") == 5
Problem 10 · fizz_buzz_list(n)
Return a list of strings — for each i from 1 to n inclusive, the FizzBuzz value (as in PY-L1-34 event 10).
# Test assert fizz_buzz_list(5) == ["1", "2", "Fizz", "4", "Buzz"] assert fizz_buzz_list(15)[-1] == "FizzBuzz" assert fizz_buzz_list(0) == []
You should be on Problem 6 or 7. If you're still on Problem 3, you might be over-thinking — most of these are 1-3 line functions. Use the smallest tool that works.
Worked Reference Solutions
5 minTry them yourself first. Only open this section after you've attempted all ten (or run out of time). The point is not to copy — it's to compare your approach to a fast one.
Show all ten reference solutions
def add(a, b): return a + b def last_letter(word): return word[-1] def is_even(n): return n % 2 == 0 def count_vowels(text): n = 0 for ch in text.lower(): if ch in "aeiou": n = n + 1 return n def shout(text): return text.upper() + "!!!" def biggest(nums): answer = nums[0] for x in nums: if x > answer: answer = x return answer def reverse(text): return text[::-1] def average(nums): if len(nums) == 0: return 0 return sum(nums) / len(nums) def count_word(text, word): return text.lower().count(word.lower()) def fizz_buzz_list(n): result = [] for i in range(1, n + 1): if i % 15 == 0: result.append("FizzBuzz") elif i % 3 == 0: result.append("Fizz") elif i % 5 == 0: result.append("Buzz") else: result.append(str(i)) return result
Most of these are 1-4 lines. The longest is fizz_buzz_list at 11 lines, and even that's mostly the four branches of the FizzBuzz if. The skill being trained today is not cleverness — it's economy of motion. Pick the right tool, type it, test it, move on.
Self-Check & Reflect
5 minOpen your timer's log if it had one, otherwise estimate. Answer in your head:
- How many did you finish before the timer? Score: __ / 10
- How many were "working but ugly" — would you rewrite if you had time? That's actually a healthy sign.
- Which one took you the longest? Why — was it new vocabulary, or did you take the long path?
If you scored under 5/10: re-read PY-L1-31 (list helpers) and PY-L1-23 (string methods) before the capstone — most of today's problems are direct calls to those.
Bonus · The Eleventh Problem
8 minFor students with time left. Combine two of your earlier functions to solve this:
Problem 11 · biggest_average(lists)
Given a list of lists of numbers, return the average of the list with the biggest sum. Use your biggest and average from earlier (or call them by composition).
# Test assert biggest_average([[1, 2], [10, 20], [3]]) == 15 # (sums are 3, 30, 3 — biggest sum is 30 from [10,20], average is 15)
Show one possible solution
def biggest_average(lists): best_sum = sum(lists[0]) best_list = lists[0] for lst in lists: if sum(lst) > best_sum: best_sum = sum(lst) best_list = lst return average(best_list)
The classic "find the best" pattern, but tracking two things at once — the best sum so far and the list that produced it. Once you have the winning list, just call your own average on it. Composition is the lesson — your toolbox is the language.
Recap
3 minCode Wars is over. Three rounds, three angles on the same skill — read code (bug hunt), trace code (predict the output), write code (speed round). The common thread is calmness: most Level 1 problems are 1-5 lines of body, and over-thinking is the biggest blocker. Each of today's ten problems was a direct call to a tool you've had for weeks — slicing, %, the in operator, .count(), .upper(), a for-loop with an accumulator. Tomorrow we start the three-part Number Guesser, which is the warm-up for the Level 1 capstone.
Vocabulary Card
- micro-problem
- A coding task small enough to solve in a few minutes. The atom of practice.
assert- A statement that silently passes if its condition is true, and crashes with
AssertionErrorif false. Cheap inline tests. - tool selection
- Choosing the smallest Level 1 feature (built-in, method, operator) that solves the problem. Often the difference between 2 lines and 20.
- economy of motion
- The discipline of doing only what the problem requires, no more, and moving to the next one promptly.
- composition
- Solving a bigger problem by chaining your own smaller functions. Today's bonus is a textbook example.
Homework
4 minTwo short jobs tonight. One reflection, one prep.
- Re-run your
speed_round.pytomorrow morning with all your solutions in place. Time it cold — how long does it take to read all 10 and confirm every assertion passes? If it's under 5 minutes, you've cemented the muscle. - Write a brand-new
my_speed.pywith three more problems of your own (with assertions). Inspiration: anagram check, biggest digit of an integer, count words longer than 4 letters. Save the solutions in a separatemy_speed_solutions.pyso you (or a classmate) can re-attempt blind.
Bring both files. PY-L1-45 starts the Number Guesser — three lessons that lead directly into the Level 1 capstone.
Sample · my_speed.py
# my_speed.py — three more micro-problems. # P1 · anagram(a, b) — True if a and b are anagrams (case-insensitive) # Test # assert anagram("listen", "silent") == True # assert anagram("hello", "world") == False # P2 · biggest_digit(n) — return the largest digit of a positive integer # Test # assert biggest_digit(394) == 9 # assert biggest_digit(7) == 7 # assert biggest_digit(11111) == 1 # P3 · count_long(words) — how many strings in the list have len > 4? # Test # assert count_long(["roti", "rendang", "teh", "satay"]) == 2 # assert count_long([]) == 0
Good practice problems are short, have crisp test data, and only need ideas you've already met. Anagram is PY-L1-25, biggest digit is PY-L1-24 + a loop, count-long is PY-L1-31 with a filter. None of them needs anything you don't know — that's exactly the "reinforce, don't introduce" aim of a speed-round set.