mirror of
https://github.com/harivansh-afk/veet-code.git
synced 2026-04-15 03:00:48 +00:00
problems
This commit is contained in:
parent
76062021e9
commit
c548626d7f
13 changed files with 570 additions and 1 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -20,7 +20,6 @@ uv.lock
|
|||
*.swo
|
||||
|
||||
# Project specific
|
||||
problems/
|
||||
.solved.json
|
||||
|
||||
# OS
|
||||
|
|
|
|||
33
problems/easy/palindrome-checker/solution.py
Normal file
33
problems/easy/palindrome-checker/solution.py
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
"""
|
||||
Palindrome Checker
|
||||
|
||||
You're building a word game that awards bonus points for palindromes.
|
||||
Given a string, determine if it reads the same forwards and backwards,
|
||||
ignoring case and non-alphanumeric characters.
|
||||
|
||||
Example 1:
|
||||
Input: text = "A man, a plan, a canal: Panama"
|
||||
Output: True
|
||||
Explanation: "amanaplanacanalpanama" is a palindrome
|
||||
|
||||
Example 2:
|
||||
Input: text = "race a car"
|
||||
Output: False
|
||||
Explanation: "raceacar" is not a palindrome
|
||||
|
||||
Example 3:
|
||||
Input: text = " "
|
||||
Output: True
|
||||
Explanation: Empty after removing non-alphanumeric
|
||||
|
||||
Constraints:
|
||||
- Input is always a string
|
||||
- Ignore spaces, punctuation, and case
|
||||
- Empty string is considered a palindrome
|
||||
"""
|
||||
|
||||
|
||||
def is_palindrome(text: str) -> bool:
|
||||
"""Return True if text is a palindrome, False otherwise."""
|
||||
pass # Your implementation here
|
||||
|
||||
44
problems/easy/palindrome-checker/tests.py
Normal file
44
problems/easy/palindrome-checker/tests.py
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
"""Tests for palindrome-checker."""
|
||||
import pytest
|
||||
from solution import is_palindrome
|
||||
|
||||
|
||||
class TestBasicCases:
|
||||
"""Test basic functionality with typical inputs."""
|
||||
|
||||
def test_simple_palindrome(self):
|
||||
"""Test basic palindrome word."""
|
||||
assert is_palindrome("racecar") == True
|
||||
|
||||
def test_sentence_palindrome(self):
|
||||
"""Test palindrome with spaces and punctuation."""
|
||||
assert is_palindrome("A man, a plan, a canal: Panama") == True
|
||||
|
||||
def test_not_palindrome(self):
|
||||
"""Test non-palindrome string."""
|
||||
assert is_palindrome("hello") == False
|
||||
|
||||
|
||||
class TestEdgeCases:
|
||||
"""Test edge cases and boundary conditions."""
|
||||
|
||||
def test_empty_string(self):
|
||||
"""Test with empty input."""
|
||||
assert is_palindrome("") == True
|
||||
|
||||
def test_single_character(self):
|
||||
"""Test with single character."""
|
||||
assert is_palindrome("a") == True
|
||||
|
||||
def test_only_spaces(self):
|
||||
"""Test with only whitespace."""
|
||||
assert is_palindrome(" ") == True
|
||||
|
||||
def test_mixed_case(self):
|
||||
"""Test case insensitivity."""
|
||||
assert is_palindrome("RaceCar") == True
|
||||
|
||||
def test_numbers_in_string(self):
|
||||
"""Test with numbers."""
|
||||
assert is_palindrome("12321") == True
|
||||
|
||||
31
problems/easy/two-sum/solution.py
Normal file
31
problems/easy/two-sum/solution.py
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
"""
|
||||
Two Sum
|
||||
|
||||
You are a cashier at a busy store. A customer wants to pay exactly
|
||||
a target amount using exactly two items from their basket.
|
||||
|
||||
Given a list of item prices and a target total, find the indices
|
||||
of the two items that add up to the target.
|
||||
|
||||
Example 1:
|
||||
Input: prices = [2, 7, 11, 15], target = 9
|
||||
Output: [0, 1]
|
||||
Explanation: prices[0] + prices[1] = 2 + 7 = 9
|
||||
|
||||
Example 2:
|
||||
Input: prices = [3, 2, 4], target = 6
|
||||
Output: [1, 2]
|
||||
|
||||
Constraints:
|
||||
- 2 <= len(prices) <= 10^4
|
||||
- Each price is a positive integer
|
||||
- Exactly one solution exists
|
||||
"""
|
||||
|
||||
|
||||
def two_sum(prices: list[int], target: int) -> list[int]:
|
||||
"""Return indices of two prices that add up to target."""
|
||||
for i in range(len(prices)):
|
||||
for j in range(i+1, len(prices)):
|
||||
if prices[i] + prices[j] == target:
|
||||
return [i,j]
|
||||
35
problems/easy/two-sum/tests.py
Normal file
35
problems/easy/two-sum/tests.py
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
"""Tests for two-sum."""
|
||||
import pytest
|
||||
from solution import two_sum
|
||||
|
||||
|
||||
class TestBasicCases:
|
||||
"""Test basic functionality with typical inputs."""
|
||||
|
||||
def test_example_one(self):
|
||||
"""Test first example from problem description."""
|
||||
assert sorted(two_sum([2, 7, 11, 15], 9)) == [0, 1]
|
||||
|
||||
def test_example_two(self):
|
||||
"""Test second example from problem description."""
|
||||
assert sorted(two_sum([3, 2, 4], 6)) == [1, 2]
|
||||
|
||||
def test_adjacent_elements(self):
|
||||
"""Test when answer elements are adjacent."""
|
||||
assert sorted(two_sum([1, 2, 3, 4], 7)) == [2, 3]
|
||||
|
||||
|
||||
class TestEdgeCases:
|
||||
"""Test edge cases and boundary conditions."""
|
||||
|
||||
def test_same_value_twice(self):
|
||||
"""Test with duplicate values that sum to target."""
|
||||
assert sorted(two_sum([3, 3], 6)) == [0, 1]
|
||||
|
||||
def test_first_and_last(self):
|
||||
"""Test when answer is first and last elements."""
|
||||
assert sorted(two_sum([2, 4, 6, 8, 10, 7], 9)) == [0, 5]
|
||||
|
||||
def test_negative_numbers(self):
|
||||
"""Test with negative numbers in the list."""
|
||||
assert sorted(two_sum([-1, -2, -3, -4, -5], -8)) == [2, 4]
|
||||
47
problems/hard/lru-cache/solution.py
Normal file
47
problems/hard/lru-cache/solution.py
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
"""
|
||||
LRU Cache
|
||||
|
||||
You're building a caching layer for a database-heavy web application.
|
||||
To reduce load, implement a Least Recently Used (LRU) cache that
|
||||
automatically evicts the oldest unused entries when capacity is reached.
|
||||
|
||||
Example 1:
|
||||
cache = LRUCache(capacity=2)
|
||||
cache.put("a", 1)
|
||||
cache.put("b", 2)
|
||||
cache.get("a") # Returns 1 (a is now most recently used)
|
||||
cache.put("c", 3) # Evicts "b" (least recently used)
|
||||
cache.get("b") # Returns -1 (not found)
|
||||
cache.get("c") # Returns 3
|
||||
|
||||
Example 2:
|
||||
cache = LRUCache(capacity=1)
|
||||
cache.put("x", 10)
|
||||
cache.put("y", 20) # Evicts "x"
|
||||
cache.get("x") # Returns -1
|
||||
cache.get("y") # Returns 20
|
||||
|
||||
Constraints:
|
||||
- capacity >= 1
|
||||
- Keys are strings, values are integers
|
||||
- get() returns -1 if key not found
|
||||
- put() updates value if key exists (and marks as recently used)
|
||||
- Both get() and put() should be O(1) average time
|
||||
"""
|
||||
|
||||
|
||||
class LRUCache:
|
||||
"""Least Recently Used cache with O(1) operations."""
|
||||
|
||||
def __init__(self, capacity: int):
|
||||
"""Initialize cache with given capacity."""
|
||||
pass # Your implementation here
|
||||
|
||||
def get(self, key: str) -> int:
|
||||
"""Return value for key, or -1 if not found."""
|
||||
pass # Your implementation here
|
||||
|
||||
def put(self, key: str, value: int) -> None:
|
||||
"""Insert or update key-value pair, evicting LRU if needed."""
|
||||
pass # Your implementation here
|
||||
|
||||
86
problems/hard/lru-cache/tests.py
Normal file
86
problems/hard/lru-cache/tests.py
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
"""Tests for lru-cache."""
|
||||
import pytest
|
||||
from solution import LRUCache
|
||||
|
||||
|
||||
class TestBasicCases:
|
||||
"""Test basic functionality with typical inputs."""
|
||||
|
||||
def test_basic_put_get(self):
|
||||
"""Test basic put and get operations."""
|
||||
cache = LRUCache(2)
|
||||
cache.put("a", 1)
|
||||
cache.put("b", 2)
|
||||
assert cache.get("a") == 1
|
||||
assert cache.get("b") == 2
|
||||
|
||||
def test_eviction_lru(self):
|
||||
"""Test that least recently used is evicted."""
|
||||
cache = LRUCache(2)
|
||||
cache.put("a", 1)
|
||||
cache.put("b", 2)
|
||||
cache.get("a") # a is now most recent
|
||||
cache.put("c", 3) # b should be evicted
|
||||
assert cache.get("b") == -1
|
||||
assert cache.get("a") == 1
|
||||
assert cache.get("c") == 3
|
||||
|
||||
def test_update_existing_key(self):
|
||||
"""Test updating an existing key."""
|
||||
cache = LRUCache(2)
|
||||
cache.put("a", 1)
|
||||
cache.put("a", 10)
|
||||
assert cache.get("a") == 10
|
||||
|
||||
|
||||
class TestEdgeCases:
|
||||
"""Test edge cases and boundary conditions."""
|
||||
|
||||
def test_capacity_one(self):
|
||||
"""Test with capacity of 1."""
|
||||
cache = LRUCache(1)
|
||||
cache.put("a", 1)
|
||||
cache.put("b", 2)
|
||||
assert cache.get("a") == -1
|
||||
assert cache.get("b") == 2
|
||||
|
||||
def test_get_nonexistent(self):
|
||||
"""Test getting a key that doesn't exist."""
|
||||
cache = LRUCache(2)
|
||||
assert cache.get("missing") == -1
|
||||
|
||||
def test_put_updates_recency(self):
|
||||
"""Test that put on existing key updates recency."""
|
||||
cache = LRUCache(2)
|
||||
cache.put("a", 1)
|
||||
cache.put("b", 2)
|
||||
cache.put("a", 10) # a is now most recent
|
||||
cache.put("c", 3) # b should be evicted
|
||||
assert cache.get("b") == -1
|
||||
assert cache.get("a") == 10
|
||||
|
||||
def test_many_operations(self):
|
||||
"""Test a sequence of many operations."""
|
||||
cache = LRUCache(3)
|
||||
cache.put("a", 1)
|
||||
cache.put("b", 2)
|
||||
cache.put("c", 3)
|
||||
cache.get("a")
|
||||
cache.put("d", 4) # evicts b
|
||||
cache.put("e", 5) # evicts c
|
||||
assert cache.get("a") == 1
|
||||
assert cache.get("b") == -1
|
||||
assert cache.get("c") == -1
|
||||
assert cache.get("d") == 4
|
||||
assert cache.get("e") == 5
|
||||
|
||||
def test_get_updates_recency(self):
|
||||
"""Test that get updates the access order."""
|
||||
cache = LRUCache(2)
|
||||
cache.put("a", 1)
|
||||
cache.put("b", 2)
|
||||
cache.get("a") # touch a
|
||||
cache.put("c", 3) # evicts b, not a
|
||||
assert cache.get("a") == 1
|
||||
assert cache.get("b") == -1
|
||||
|
||||
49
problems/hard/rate-limiter/solution.py
Normal file
49
problems/hard/rate-limiter/solution.py
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
"""
|
||||
Rate Limiter
|
||||
|
||||
You're building an API gateway for a SaaS platform. To prevent abuse
|
||||
and ensure fair usage, you need to implement a rate limiter that tracks
|
||||
requests per user using a sliding window algorithm.
|
||||
|
||||
The limiter should allow at most `max_requests` per user within any
|
||||
`window_seconds` time period.
|
||||
|
||||
Example 1:
|
||||
limiter = RateLimiter(max_requests=3, window_seconds=60)
|
||||
limiter.allow_request("user1", timestamp=0) # True (1st request)
|
||||
limiter.allow_request("user1", timestamp=30) # True (2nd request)
|
||||
limiter.allow_request("user1", timestamp=45) # True (3rd request)
|
||||
limiter.allow_request("user1", timestamp=50) # False (limit reached)
|
||||
limiter.allow_request("user1", timestamp=61) # True (1st expired)
|
||||
|
||||
Example 2:
|
||||
limiter = RateLimiter(max_requests=2, window_seconds=10)
|
||||
limiter.allow_request("user1", timestamp=0) # True
|
||||
limiter.allow_request("user2", timestamp=0) # True (different user)
|
||||
limiter.allow_request("user1", timestamp=5) # True
|
||||
limiter.allow_request("user1", timestamp=8) # False
|
||||
|
||||
Constraints:
|
||||
- max_requests >= 1
|
||||
- window_seconds >= 1
|
||||
- Timestamps are non-negative integers (seconds)
|
||||
- Timestamps are non-decreasing per user
|
||||
- user_id is a non-empty string
|
||||
"""
|
||||
|
||||
|
||||
class RateLimiter:
|
||||
"""Sliding window rate limiter for API request throttling."""
|
||||
|
||||
def __init__(self, max_requests: int, window_seconds: int):
|
||||
"""Initialize with request limit and time window."""
|
||||
pass # Your implementation here
|
||||
|
||||
def allow_request(self, user_id: str, timestamp: int) -> bool:
|
||||
"""Return True if request allowed, False if rate limited."""
|
||||
pass # Your implementation here
|
||||
|
||||
def get_remaining(self, user_id: str, timestamp: int) -> int:
|
||||
"""Return remaining requests allowed for user at timestamp."""
|
||||
pass # Your implementation here
|
||||
|
||||
70
problems/hard/rate-limiter/tests.py
Normal file
70
problems/hard/rate-limiter/tests.py
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
"""Tests for rate-limiter."""
|
||||
import pytest
|
||||
from solution import RateLimiter
|
||||
|
||||
|
||||
class TestBasicCases:
|
||||
"""Test basic functionality with typical inputs."""
|
||||
|
||||
def test_allow_within_limit(self):
|
||||
"""Test requests within the limit are allowed."""
|
||||
limiter = RateLimiter(max_requests=3, window_seconds=60)
|
||||
assert limiter.allow_request("user1", 0) == True
|
||||
assert limiter.allow_request("user1", 30) == True
|
||||
assert limiter.allow_request("user1", 45) == True
|
||||
|
||||
def test_block_over_limit(self):
|
||||
"""Test requests over limit are blocked."""
|
||||
limiter = RateLimiter(max_requests=2, window_seconds=60)
|
||||
assert limiter.allow_request("user1", 0) == True
|
||||
assert limiter.allow_request("user1", 30) == True
|
||||
assert limiter.allow_request("user1", 45) == False
|
||||
|
||||
def test_multiple_users_independent(self):
|
||||
"""Test each user has independent limits."""
|
||||
limiter = RateLimiter(max_requests=1, window_seconds=60)
|
||||
assert limiter.allow_request("user1", 0) == True
|
||||
assert limiter.allow_request("user2", 0) == True
|
||||
assert limiter.allow_request("user1", 30) == False
|
||||
assert limiter.allow_request("user2", 30) == False
|
||||
|
||||
def test_get_remaining_basic(self):
|
||||
"""Test remaining count decreases with requests."""
|
||||
limiter = RateLimiter(max_requests=3, window_seconds=60)
|
||||
assert limiter.get_remaining("user1", 0) == 3
|
||||
limiter.allow_request("user1", 0)
|
||||
assert limiter.get_remaining("user1", 0) == 2
|
||||
|
||||
|
||||
class TestEdgeCases:
|
||||
"""Test edge cases and boundary conditions."""
|
||||
|
||||
def test_window_expiration(self):
|
||||
"""Test old requests expire from window."""
|
||||
limiter = RateLimiter(max_requests=2, window_seconds=60)
|
||||
assert limiter.allow_request("user1", 0) == True
|
||||
assert limiter.allow_request("user1", 30) == True
|
||||
assert limiter.allow_request("user1", 45) == False
|
||||
assert limiter.allow_request("user1", 61) == True
|
||||
|
||||
def test_single_request_limit(self):
|
||||
"""Test with limit of 1 request."""
|
||||
limiter = RateLimiter(max_requests=1, window_seconds=10)
|
||||
assert limiter.allow_request("user1", 0) == True
|
||||
assert limiter.allow_request("user1", 5) == False
|
||||
assert limiter.allow_request("user1", 11) == True
|
||||
|
||||
def test_new_user_full_allowance(self):
|
||||
"""Test new users start with full allowance."""
|
||||
limiter = RateLimiter(max_requests=5, window_seconds=60)
|
||||
limiter.allow_request("user1", 0)
|
||||
assert limiter.get_remaining("new_user", 20) == 5
|
||||
|
||||
def test_rapid_same_timestamp(self):
|
||||
"""Test multiple requests at same timestamp."""
|
||||
limiter = RateLimiter(max_requests=3, window_seconds=1)
|
||||
assert limiter.allow_request("user1", 0) == True
|
||||
assert limiter.allow_request("user1", 0) == True
|
||||
assert limiter.allow_request("user1", 0) == True
|
||||
assert limiter.allow_request("user1", 0) == False
|
||||
|
||||
33
problems/medium/group-transactions/solution.py
Normal file
33
problems/medium/group-transactions/solution.py
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
"""
|
||||
Transaction Grouper
|
||||
|
||||
You're building a financial dashboard for a budgeting app. Users want
|
||||
to see their spending grouped by category with totals, so they can
|
||||
understand where their money is going each month.
|
||||
|
||||
Example 1:
|
||||
Input: transactions = [
|
||||
{"amount": 50, "category": "food", "date": "2024-01-01"},
|
||||
{"amount": 30, "category": "food", "date": "2024-01-02"},
|
||||
{"amount": 100, "category": "transport", "date": "2024-01-01"}
|
||||
]
|
||||
Output: {"food": 80, "transport": 100}
|
||||
Explanation: food: 50+30=80, transport: 100
|
||||
|
||||
Example 2:
|
||||
Input: transactions = []
|
||||
Output: {}
|
||||
Explanation: No transactions means empty result
|
||||
|
||||
Constraints:
|
||||
- Each transaction has "amount" (positive int), "category" (str), "date" (str)
|
||||
- Categories are case-sensitive
|
||||
- Return categories in any order
|
||||
- Amount is always positive
|
||||
"""
|
||||
|
||||
|
||||
def group_transactions(transactions: list[dict]) -> dict[str, int]:
|
||||
"""Return dictionary mapping each category to its total amount."""
|
||||
pass # Your implementation here
|
||||
|
||||
58
problems/medium/group-transactions/tests.py
Normal file
58
problems/medium/group-transactions/tests.py
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
"""Tests for group-transactions."""
|
||||
import pytest
|
||||
from solution import group_transactions
|
||||
|
||||
|
||||
class TestBasicCases:
|
||||
"""Test basic functionality with typical inputs."""
|
||||
|
||||
def test_multiple_categories(self):
|
||||
"""Test grouping across different categories."""
|
||||
txns = [
|
||||
{"amount": 50, "category": "food", "date": "2024-01-01"},
|
||||
{"amount": 30, "category": "food", "date": "2024-01-02"},
|
||||
{"amount": 100, "category": "transport", "date": "2024-01-01"}
|
||||
]
|
||||
assert group_transactions(txns) == {"food": 80, "transport": 100}
|
||||
|
||||
def test_single_category(self):
|
||||
"""Test all transactions in one category."""
|
||||
txns = [
|
||||
{"amount": 10, "category": "food", "date": "2024-01-01"},
|
||||
{"amount": 20, "category": "food", "date": "2024-01-02"},
|
||||
{"amount": 30, "category": "food", "date": "2024-01-03"}
|
||||
]
|
||||
assert group_transactions(txns) == {"food": 60}
|
||||
|
||||
def test_single_transaction(self):
|
||||
"""Test with just one transaction."""
|
||||
txns = [{"amount": 25, "category": "entertainment", "date": "2024-01-01"}]
|
||||
assert group_transactions(txns) == {"entertainment": 25}
|
||||
|
||||
|
||||
class TestEdgeCases:
|
||||
"""Test edge cases and boundary conditions."""
|
||||
|
||||
def test_empty_list(self):
|
||||
"""Test with no transactions."""
|
||||
assert group_transactions([]) == {}
|
||||
|
||||
def test_case_sensitive_categories(self):
|
||||
"""Test that categories are case-sensitive."""
|
||||
txns = [
|
||||
{"amount": 10, "category": "Food", "date": "2024-01-01"},
|
||||
{"amount": 20, "category": "food", "date": "2024-01-02"}
|
||||
]
|
||||
result = group_transactions(txns)
|
||||
assert result == {"Food": 10, "food": 20}
|
||||
|
||||
def test_many_categories(self):
|
||||
"""Test with many different categories."""
|
||||
txns = [
|
||||
{"amount": 1, "category": "a", "date": "2024-01-01"},
|
||||
{"amount": 2, "category": "b", "date": "2024-01-01"},
|
||||
{"amount": 3, "category": "c", "date": "2024-01-01"},
|
||||
{"amount": 4, "category": "d", "date": "2024-01-01"}
|
||||
]
|
||||
assert group_transactions(txns) == {"a": 1, "b": 2, "c": 3, "d": 4}
|
||||
|
||||
32
problems/medium/word-frequency/solution.py
Normal file
32
problems/medium/word-frequency/solution.py
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
"""
|
||||
Word Frequency Counter
|
||||
|
||||
You're building a text analytics tool for a content marketing team.
|
||||
Given a block of text, return the top N most frequently used words,
|
||||
sorted by frequency (highest first), then alphabetically for ties.
|
||||
|
||||
Example 1:
|
||||
Input: text = "the quick brown fox jumps over the lazy dog the fox"
|
||||
n = 2
|
||||
Output: [("the", 3), ("fox", 2)]
|
||||
Explanation: "the" appears 3 times, "fox" appears 2 times
|
||||
|
||||
Example 2:
|
||||
Input: text = "hello world hello"
|
||||
n = 5
|
||||
Output: [("hello", 2), ("world", 1)]
|
||||
Explanation: Only 2 unique words, return all of them
|
||||
|
||||
Constraints:
|
||||
- Words are separated by whitespace
|
||||
- Case-insensitive (convert to lowercase)
|
||||
- Ignore punctuation attached to words
|
||||
- n >= 1
|
||||
- If fewer than n unique words exist, return all of them
|
||||
"""
|
||||
|
||||
|
||||
def top_words(text: str, n: int) -> list[tuple[str, int]]:
|
||||
"""Return top n words by frequency as list of (word, count) tuples."""
|
||||
pass # Your implementation here
|
||||
|
||||
52
problems/medium/word-frequency/tests.py
Normal file
52
problems/medium/word-frequency/tests.py
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
"""Tests for word-frequency."""
|
||||
import pytest
|
||||
from solution import top_words
|
||||
|
||||
|
||||
class TestBasicCases:
|
||||
"""Test basic functionality with typical inputs."""
|
||||
|
||||
def test_basic_frequency(self):
|
||||
"""Test basic word counting."""
|
||||
result = top_words("the quick brown fox jumps over the lazy dog the fox", 2)
|
||||
assert result == [("the", 3), ("fox", 2)]
|
||||
|
||||
def test_all_unique(self):
|
||||
"""Test when all words are unique."""
|
||||
result = top_words("one two three", 2)
|
||||
assert result == [("one", 1), ("three", 1)] or result == [("one", 1), ("two", 1)]
|
||||
|
||||
def test_single_word_repeated(self):
|
||||
"""Test with one word repeated."""
|
||||
result = top_words("hello hello hello", 1)
|
||||
assert result == [("hello", 3)]
|
||||
|
||||
|
||||
class TestEdgeCases:
|
||||
"""Test edge cases and boundary conditions."""
|
||||
|
||||
def test_empty_string(self):
|
||||
"""Test with empty input."""
|
||||
result = top_words("", 5)
|
||||
assert result == []
|
||||
|
||||
def test_n_greater_than_unique_words(self):
|
||||
"""Test when n exceeds unique word count."""
|
||||
result = top_words("hello world", 10)
|
||||
assert len(result) == 2
|
||||
|
||||
def test_case_insensitive(self):
|
||||
"""Test that counting is case-insensitive."""
|
||||
result = top_words("Hello HELLO hello", 1)
|
||||
assert result == [("hello", 3)]
|
||||
|
||||
def test_punctuation_ignored(self):
|
||||
"""Test that punctuation is stripped."""
|
||||
result = top_words("hello, world! hello.", 1)
|
||||
assert result == [("hello", 2)]
|
||||
|
||||
def test_alphabetical_tiebreaker(self):
|
||||
"""Test alphabetical ordering for same frequency."""
|
||||
result = top_words("cat bat ant", 3)
|
||||
assert result == [("ant", 1), ("bat", 1), ("cat", 1)]
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue