Skip to content

Commit f0adafc

Browse files
travisjneumanclaude
andcommitted
feat: add 30 coding challenges with solutions
15 beginner + 15 intermediate challenges covering core Python patterns. Each challenge has function stubs, type hints, test cases, and hints. Solutions in separate directory for self-checking. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 68a08f8 commit f0adafc

63 files changed

Lines changed: 3525 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

practice/challenges/README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Coding Challenges
2+
3+
Standalone coding challenges to sharpen your Python skills. Each challenge is a single file with a problem description, function stub, hints, and built-in tests.
4+
5+
## How It Works
6+
7+
1. **Read the docstring** at the top of each challenge file for the problem description and examples.
8+
2. **Implement the function** where it says `pass`.
9+
3. **Run the file** with `python <filename>.py` -- the built-in tests will tell you if your solution is correct.
10+
4. **Check the solution** in `solutions/` only after you have genuinely attempted the problem.
11+
12+
## Difficulty Levels
13+
14+
| Level | Description | Prereqs |
15+
| ---------------- | ---------------------------------------------------------------- | ------------------------------------------ |
16+
| **Beginner** | Core Python: variables, strings, lists, loops, conditionals | Level 0-2 of the curriculum |
17+
| **Intermediate** | Decorators, generators, classes, async, file I/O, data structures | Level 3-6 of the curriculum |
18+
19+
## Directory Structure
20+
21+
```
22+
challenges/
23+
README.md -- This file
24+
beginner/ -- 15 beginner challenges
25+
intermediate/ -- 15 intermediate challenges
26+
solutions/
27+
beginner/ -- Beginner solutions with explanations
28+
intermediate/ -- Intermediate solutions with explanations
29+
```
30+
31+
## Tips
32+
33+
- Read the entire docstring before writing any code.
34+
- Use the hint only if you are stuck for more than 5 minutes.
35+
- Run the tests frequently as you build up your solution.
36+
- If all tests pass but you are unsure why, trace through your code by hand with the example inputs.
37+
- Compare your passing solution to the provided solution -- there are often multiple valid approaches.
38+
39+
## Estimated Time
40+
41+
- Beginner challenges: 10-30 minutes each
42+
- Intermediate challenges: 30-60 minutes each
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"""
2+
Challenge: Swap Variables
3+
Difficulty: Beginner
4+
Concepts: variables, tuple unpacking, arithmetic tricks
5+
Time: 10 minutes
6+
7+
Swap two variables without using a temporary third variable.
8+
Return them as a tuple (b, a) where the values have been exchanged.
9+
10+
Examples:
11+
>>> swap(1, 2)
12+
(2, 1)
13+
>>> swap("hello", "world")
14+
('world', 'hello')
15+
"""
16+
17+
18+
def swap(a, b) -> tuple:
19+
"""Swap two values and return them as a tuple. Implement this function."""
20+
# Hint: Python supports simultaneous assignment with commas.
21+
pass
22+
23+
24+
# --- Tests (do not modify) ---
25+
if __name__ == "__main__":
26+
# Test 1: Basic integers
27+
assert swap(1, 2) == (2, 1), "Basic integer swap failed"
28+
# Test 2: Strings
29+
assert swap("hello", "world") == ("world", "hello"), "String swap failed"
30+
# Test 3: Same values
31+
assert swap(5, 5) == (5, 5), "Same value swap failed"
32+
# Test 4: Mixed types
33+
assert swap(42, "answer") == ("answer", 42), "Mixed type swap failed"
34+
print("All tests passed!")
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
"""
2+
Challenge: FizzBuzz
3+
Difficulty: Beginner
4+
Concepts: loops, conditionals, modulo operator, list building
5+
Time: 15 minutes
6+
7+
Given an integer n, return a list of strings from 1 to n where:
8+
- Multiples of 3 are replaced with "Fizz"
9+
- Multiples of 5 are replaced with "Buzz"
10+
- Multiples of both 3 and 5 are replaced with "FizzBuzz"
11+
- All other numbers are converted to their string representation
12+
13+
Examples:
14+
>>> fizzbuzz(5)
15+
['1', '2', 'Fizz', '4', 'Buzz']
16+
>>> fizzbuzz(15)[-1]
17+
'FizzBuzz'
18+
"""
19+
20+
21+
def fizzbuzz(n: int) -> list[str]:
22+
"""Return FizzBuzz sequence from 1 to n. Implement this function."""
23+
# Hint: Check divisibility by 15 (both) before checking 3 or 5 individually.
24+
pass
25+
26+
27+
# --- Tests (do not modify) ---
28+
if __name__ == "__main__":
29+
# Test 1: Small range
30+
assert fizzbuzz(5) == ["1", "2", "Fizz", "4", "Buzz"], "Small range failed"
31+
# Test 2: FizzBuzz at 15
32+
result = fizzbuzz(15)
33+
assert result[14] == "FizzBuzz", "FizzBuzz at 15 failed"
34+
assert result[2] == "Fizz", "Fizz at 3 failed"
35+
assert result[4] == "Buzz", "Buzz at 5 failed"
36+
# Test 3: Single element
37+
assert fizzbuzz(1) == ["1"], "Single element failed"
38+
# Test 4: Length check
39+
assert len(fizzbuzz(20)) == 20, "Length check failed"
40+
print("All tests passed!")
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"""
2+
Challenge: Reverse String
3+
Difficulty: Beginner
4+
Concepts: strings, loops, iteration, string building
5+
Time: 15 minutes
6+
7+
Reverse a string without using slice notation ([::-1]).
8+
You may use loops, recursion, or any other approach.
9+
10+
Examples:
11+
>>> reverse_string("hello")
12+
'olleh'
13+
>>> reverse_string("Python")
14+
'nohtyP'
15+
"""
16+
17+
18+
def reverse_string(s: str) -> str:
19+
"""Reverse a string without using [::-1]. Implement this function."""
20+
# Hint: Build a new string by iterating from the end, or use a loop to prepend characters.
21+
pass
22+
23+
24+
# --- Tests (do not modify) ---
25+
if __name__ == "__main__":
26+
# Test 1: Basic word
27+
assert reverse_string("hello") == "olleh", "Basic word failed"
28+
# Test 2: Palindrome
29+
assert reverse_string("racecar") == "racecar", "Palindrome failed"
30+
# Test 3: Empty string
31+
assert reverse_string("") == "", "Empty string failed"
32+
# Test 4: Single character
33+
assert reverse_string("x") == "x", "Single character failed"
34+
# Test 5: Spaces and punctuation
35+
assert reverse_string("hi there!") == "!ereht ih", "Spaces and punctuation failed"
36+
print("All tests passed!")
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"""
2+
Challenge: Count Vowels
3+
Difficulty: Beginner
4+
Concepts: strings, loops, membership testing, case handling
5+
Time: 10 minutes
6+
7+
Count the number of vowels (a, e, i, o, u) in a string.
8+
The count should be case-insensitive.
9+
10+
Examples:
11+
>>> count_vowels("hello")
12+
2
13+
>>> count_vowels("AEIOU")
14+
5
15+
"""
16+
17+
18+
def count_vowels(s: str) -> int:
19+
"""Count vowels in a string (case-insensitive). Implement this function."""
20+
# Hint: Convert to lowercase first, then check each character against "aeiou".
21+
pass
22+
23+
24+
# --- Tests (do not modify) ---
25+
if __name__ == "__main__":
26+
# Test 1: Basic word
27+
assert count_vowels("hello") == 2, "Basic word failed"
28+
# Test 2: All vowels
29+
assert count_vowels("AEIOU") == 5, "All vowels uppercase failed"
30+
# Test 3: No vowels
31+
assert count_vowels("rhythm") == 0, "No vowels failed"
32+
# Test 4: Empty string
33+
assert count_vowels("") == 0, "Empty string failed"
34+
# Test 5: Mixed case
35+
assert count_vowels("Beautiful Day") == 6, "Mixed case failed"
36+
print("All tests passed!")
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
"""
2+
Challenge: Palindrome Check
3+
Difficulty: Beginner
4+
Concepts: strings, two-pointer technique, case normalization
5+
Time: 15 minutes
6+
7+
Check if a string is a palindrome. Ignore case and non-alphanumeric characters.
8+
A palindrome reads the same forward and backward.
9+
10+
Examples:
11+
>>> is_palindrome("racecar")
12+
True
13+
>>> is_palindrome("A man, a plan, a canal: Panama")
14+
True
15+
>>> is_palindrome("hello")
16+
False
17+
"""
18+
19+
20+
def is_palindrome(s: str) -> bool:
21+
"""Check if a string is a palindrome (ignoring case and non-alphanumeric chars). Implement this function."""
22+
# Hint: First strip out non-alphanumeric characters and lowercase everything, then compare.
23+
pass
24+
25+
26+
# --- Tests (do not modify) ---
27+
if __name__ == "__main__":
28+
# Test 1: Simple palindrome
29+
assert is_palindrome("racecar") is True, "Simple palindrome failed"
30+
# Test 2: Sentence palindrome
31+
assert is_palindrome("A man, a plan, a canal: Panama") is True, "Sentence palindrome failed"
32+
# Test 3: Not a palindrome
33+
assert is_palindrome("hello") is False, "Not a palindrome failed"
34+
# Test 4: Empty string
35+
assert is_palindrome("") is True, "Empty string failed"
36+
# Test 5: Single character
37+
assert is_palindrome("a") is True, "Single character failed"
38+
# Test 6: Numbers and letters
39+
assert is_palindrome("Was it a car or a cat I saw?") is True, "Complex palindrome failed"
40+
print("All tests passed!")
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"""
2+
Challenge: Sum of Digits
3+
Difficulty: Beginner
4+
Concepts: integers, modulo, floor division, loops
5+
Time: 10 minutes
6+
7+
Given a non-negative integer, return the sum of its digits.
8+
Do not convert the integer to a string -- use arithmetic only.
9+
10+
Examples:
11+
>>> sum_of_digits(123)
12+
6
13+
>>> sum_of_digits(9999)
14+
36
15+
"""
16+
17+
18+
def sum_of_digits(n: int) -> int:
19+
"""Sum all digits of a non-negative integer using arithmetic. Implement this function."""
20+
# Hint: Use n % 10 to get the last digit and n // 10 to remove it.
21+
pass
22+
23+
24+
# --- Tests (do not modify) ---
25+
if __name__ == "__main__":
26+
# Test 1: Basic number
27+
assert sum_of_digits(123) == 6, "Basic number failed"
28+
# Test 2: All nines
29+
assert sum_of_digits(9999) == 36, "All nines failed"
30+
# Test 3: Zero
31+
assert sum_of_digits(0) == 0, "Zero failed"
32+
# Test 4: Single digit
33+
assert sum_of_digits(7) == 7, "Single digit failed"
34+
# Test 5: Large number
35+
assert sum_of_digits(10001) == 2, "Large number failed"
36+
print("All tests passed!")
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
"""
2+
Challenge: Find Maximum
3+
Difficulty: Beginner
4+
Concepts: lists, iteration, comparison, edge cases
5+
Time: 10 minutes
6+
7+
Find the maximum value in a list of numbers without using the built-in max() function.
8+
Raise a ValueError if the list is empty.
9+
10+
Examples:
11+
>>> find_max([3, 1, 4, 1, 5, 9])
12+
9
13+
>>> find_max([-5, -1, -8])
14+
-1
15+
"""
16+
17+
18+
def find_max(numbers: list[int | float]) -> int | float:
19+
"""Find the maximum value in a list without using max(). Implement this function."""
20+
# Hint: Start with the first element as your candidate, then compare against each remaining element.
21+
pass
22+
23+
24+
# --- Tests (do not modify) ---
25+
if __name__ == "__main__":
26+
# Test 1: Positive numbers
27+
assert find_max([3, 1, 4, 1, 5, 9]) == 9, "Positive numbers failed"
28+
# Test 2: Negative numbers
29+
assert find_max([-5, -1, -8]) == -1, "Negative numbers failed"
30+
# Test 3: Single element
31+
assert find_max([42]) == 42, "Single element failed"
32+
# Test 4: Mixed positive and negative
33+
assert find_max([-10, 0, 10]) == 10, "Mixed numbers failed"
34+
# Test 5: Empty list raises ValueError
35+
try:
36+
find_max([])
37+
assert False, "Empty list should raise ValueError"
38+
except ValueError:
39+
pass
40+
print("All tests passed!")
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"""
2+
Challenge: Remove Duplicates
3+
Difficulty: Beginner
4+
Concepts: lists, sets, order preservation, membership testing
5+
Time: 15 minutes
6+
7+
Remove duplicate values from a list while preserving the original order.
8+
The first occurrence of each value should be kept.
9+
10+
Examples:
11+
>>> remove_duplicates([1, 2, 2, 3, 1, 4])
12+
[1, 2, 3, 4]
13+
>>> remove_duplicates(["a", "b", "a", "c"])
14+
['a', 'b', 'c']
15+
"""
16+
17+
18+
def remove_duplicates(items: list) -> list:
19+
"""Remove duplicates from a list, preserving order. Implement this function."""
20+
# Hint: Use a set to track what you have already seen as you iterate.
21+
pass
22+
23+
24+
# --- Tests (do not modify) ---
25+
if __name__ == "__main__":
26+
# Test 1: Integers with duplicates
27+
assert remove_duplicates([1, 2, 2, 3, 1, 4]) == [1, 2, 3, 4], "Integer duplicates failed"
28+
# Test 2: Strings
29+
assert remove_duplicates(["a", "b", "a", "c"]) == ["a", "b", "c"], "String duplicates failed"
30+
# Test 3: No duplicates
31+
assert remove_duplicates([1, 2, 3]) == [1, 2, 3], "No duplicates failed"
32+
# Test 4: All duplicates
33+
assert remove_duplicates([5, 5, 5, 5]) == [5], "All duplicates failed"
34+
# Test 5: Empty list
35+
assert remove_duplicates([]) == [], "Empty list failed"
36+
print("All tests passed!")
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
"""
2+
Challenge: Word Frequency
3+
Difficulty: Beginner
4+
Concepts: strings, dictionaries, splitting, case normalization
5+
Time: 20 minutes
6+
7+
Count the frequency of each word in a text string. Words should be
8+
compared case-insensitively. Return a dictionary mapping lowercase
9+
words to their counts. Split on whitespace only.
10+
11+
Examples:
12+
>>> word_frequency("the cat and the dog")
13+
{'the': 2, 'cat': 1, 'and': 1, 'dog': 1}
14+
>>> word_frequency("Hello hello HELLO")
15+
{'hello': 3}
16+
"""
17+
18+
19+
def word_frequency(text: str) -> dict[str, int]:
20+
"""Count word frequencies in text (case-insensitive). Implement this function."""
21+
# Hint: Use .lower().split() to get normalized words, then build a dict with counts.
22+
pass
23+
24+
25+
# --- Tests (do not modify) ---
26+
if __name__ == "__main__":
27+
# Test 1: Basic sentence
28+
assert word_frequency("the cat and the dog") == {"the": 2, "cat": 1, "and": 1, "dog": 1}, "Basic sentence failed"
29+
# Test 2: Case insensitive
30+
assert word_frequency("Hello hello HELLO") == {"hello": 3}, "Case insensitive failed"
31+
# Test 3: Single word
32+
assert word_frequency("Python") == {"python": 1}, "Single word failed"
33+
# Test 4: Empty string
34+
assert word_frequency("") == {}, "Empty string failed"
35+
# Test 5: Multiple spaces
36+
result = word_frequency("a b a")
37+
assert result == {"a": 2, "b": 1}, "Multiple spaces failed"
38+
print("All tests passed!")

0 commit comments

Comments
 (0)