Learning Goals
3 minBy the end of this lesson you can:
- Take two messy user inputs and clean them with
.strip().lower().replace(" ", ""). - Use
sorted(word)to turn a string into an alphabetical list of letters, and explain whysorted("listen") == sorted("silent"). - Wrap the whole thing in a
while Trueloop so the player can keep checking pairs until they typequit.
Warm-Up
5 minQuick puzzle. Two words are anagrams if they use the same letters, just shuffled. Look at each pair and decide yes or no:
RAINandIRANNASIandSANIMAKANandKAMANRAJAandJARI
Show the answers
The first three are anagrams — same four letters in a different order. The last pair isn't: RAJA has two A's, but JARI only has one. Counting letters matters.
The cheat code that humans use is to sort the letters in your head: R,A,I,N sorted is A,I,N,R; I,R,A,N sorted is also A,I,N,R. Same sorted list → anagram. That's exactly the trick we'll teach Python today.
.strip().lower() from PY-L1-23 (clean the input), and the built-in sorted() — a new one — that hands back a list of letters in A→Z order.
New Concept · sorted() on a String
12 minWhat sorted() does
sorted() is a built-in that takes any sequence — a list, a tuple, or a string — and returns a brand-new list with the items in order. Letters come out in alphabetical order, lowercase before uppercase:
print(sorted("nasi")) # → ['a', 'i', 'n', 's'] print(sorted("sani")) # → ['a', 'i', 'n', 's']
The two calls produced exactly the same list — because the two words share the same letters. That's the whole anagram test in one line:
sorted("listen") == sorted("silent") # True
Why a list, not a string?
sorted() always gives back a list, even when you feed it a string. sorted("nasi") is ['a', 'i', 'n', 's'], not "ains". We don't mind — we're only comparing two of them with ==, and two lists with the same items in the same order are equal.
Clean before you compare
If the player types " Listen " and "SILENT", those are obviously anagrams to a human. But to Python, the spaces and the capitals make them unequal. Clean both sides the same way before sorting:
a = " Listen ".strip().lower() # "listen" b = "SILENT".strip().lower() # "silent" print(sorted(a) == sorted(b)) # True
Drop the spaces inside, too
For phrase anagrams like "dorm itory" vs "dirty room", the spaces would still mess up the count. .replace(" ", "") from PY-L1-23 strips every space, not just the ones at the ends:
raw = "Dirty Room" clean = raw.strip().lower().replace(" ", "") print(clean) # → "dirtyroom"
Three methods chained on one line — read it left-to-right, each one runs on whatever the previous one produced.
Anagram check = clean both sides the same way, then sorted(a) == sorted(b). Three short lines, no special library, works on any pair of words.
Worked Example · Build the Detective
15 minStep 1 · Ask for two words
first = input("Word 1: ") second = input("Word 2: ") print(first, second)
Run it. Type Listen and Silent. It echoes them back exactly as typed. That's the boring half — capturing the input.
Step 2 · Clean each word
Chain .strip().lower().replace(" ", "") on each input. This makes spaces, capital letters, and accidental leading/trailing whitespace all stop mattering:
first = input("Word 1: ").strip().lower().replace(" ", "") second = input("Word 2: ").strip().lower().replace(" ", "") print(first, second)
Try it with " Listen " and "SILENT". The print now shows listen silent — both lowercase, both stripped.
Step 3 · Sort and compare
One if, two outcomes. Use sorted() on each cleaned word and compare with ==:
if sorted(first) == sorted(second): print("✅ Anagram!") else: print("❌ Not an anagram.")
Step 4 · Loop until quit
Wrap the lot in a while True loop (callback from PY-L1-20 and the while lesson PY-L1-12). Break out when the player types quit for word 1:
Code
# anagram_detective.py — sniff out anagrams print("🕵️ Anagram Detective. Type 'quit' to stop.") while True: first = input("Word 1: ").strip().lower().replace(" ", "") if first == "quit": break second = input("Word 2: ").strip().lower().replace(" ", "") if sorted(first) == sorted(second): print("✅ Anagram!") else: print("❌ Not an anagram.") print("Case closed. Goodbye.")
Sample run
🕵️ Anagram Detective. Type 'quit' to stop. Word 1: Listen Word 2: SILENT ✅ Anagram! Word 1: nasi Word 2: sani ✅ Anagram! Word 1: raja Word 2: jari ❌ Not an anagram. Word 1: quit Case closed. Goodbye.
Anagram-style checks are the bones of word games (Scrabble, Wordle helpers), of spell-checkers, and of a surprising amount of cryptography exercises. The pattern — normalise, then compare a sorted form — comes back forever.
Try It Yourself
14 minThree tasks. Type, run, only peek at the hint if you're truly stuck.
Set a = "rail" and b = "liar". Print whether they are anagrams using a single if/else on sorted(a) == sorted(b).
Hint
a = "rail" b = "liar" if sorted(a) == sorted(b): print("Yes — anagram.") else: print("Nope.")
Expected output: Yes — anagram.. Try changing b to "lair" too — also an anagram of "rail".
Ask the player for two words with input(). Before comparing, chain .strip().lower() on each. Print Anagram! or Not an anagram.. Test it with " Listen " and "SILENT" — the messy version should still come back as an anagram.
Hint
a = input("Word 1: ").strip().lower() b = input("Word 2: ").strip().lower() if sorted(a) == sorted(b): print("Anagram!") else: print("Not an anagram.")
Without the .strip().lower(), the trailing space and the capital S would make Python say they're different. Cleaning both sides the same way is the rule.
Modify task 2 so it also accepts phrases with spaces — "dorm itory" vs "dirty room". Hint: add .replace(" ", "") to the cleaning chain on each side.
Hint
a = input("Phrase 1: ").strip().lower().replace(" ", "") b = input("Phrase 2: ").strip().lower().replace(" ", "") if sorted(a) == sorted(b): print("Anagram!") else: print("Not an anagram.")
Try it with "Dirty Room" and "Dormitory" — true anagram. Also try "school master" and "the classroom" — works for any pair where every letter (ignoring spaces and case) lines up.
Mini-Challenge · Faiz's Wrong-Answer Detector
8 minFaiz wrote his own anagram checker, but it keeps saying things are anagrams when they're not. Read the script, spot the two bugs, and fix them.
# faiz_anagram.py — buggy
a = input("Word 1: ")
b = input("Word 2: ")
if len(a) == len(b):
print("Anagram!")
else:
print("Not an anagram.")Test it with RAIN and IRAN — it says anagram (lucky). Test with RAIN and STOP — it also says anagram. Test with " Listen " and "SILENT" — depending on capitals and spaces, it might say either.
- Bug 1. Comparing
len()only checks that the words are the same length, not the same letters. Replace withsorted(a) == sorted(b). - Bug 2. No cleaning, so capitals and spaces still matter. Add
.strip().lower()to both inputs.
Show one possible fix
# faiz_anagram.py — fixed a = input("Word 1: ").strip().lower() b = input("Word 2: ").strip().lower() if sorted(a) == sorted(b): print("Anagram!") else: print("Not an anagram.")
Bug 1 is the headline mistake: equal length is necessary, but not sufficient. RAIN and STOP are both four letters, but they share no letters at all. Bug 2 is the "same hygiene on both sides" rule from PY-L1-23 — clean inputs the moment they arrive.
Recap
3 minAnagrams are about which letters, not the order they appear in. Python's sorted() built-in turns any word into a list of its letters in alphabetical order, and two anagrams always produce the same sorted list. Combine it with the cleaning chain from PY-L1-23 — .strip().lower().replace(" ", "") — and you can build a detective that ignores messy input and just compares the letters that matter. Wrap it in a while True loop with a quit escape and you've got a real little game.
Vocabulary Card
- anagram
- A word or phrase made by rearranging the letters of another —
LISTEN↔SILENT. sorted(seq)- A built-in that returns a new list with the items of
seqin ascending order. Strings come out as a list of single-character strings. - built-in function
- A function that ships with Python — you don't need to
importit.print,len,input,sortedare all built-ins. - normalise
- To clean two pieces of data the same way so they can be compared fairly — usually
.strip().lower(). - method chaining
- Calling several methods in a row on one value, like
raw.strip().lower().replace(" ", ""). Reads left to right.
Homework
4 minCreate a new file anagram_pairs.py — a batch checker that reads pairs from a list and prints a mini-report.
- At the top of the file, store a list of four pairs as 2-element lists, e.g.
pairs = [["listen", "silent"], ["nasi", "sani"], ["raja", "jari"], ["dorm itory", "dirty room"]]. - Loop through the list with a
forloop (callback from PY-L1-16). For each pair, clean both sides with.strip().lower().replace(" ", ""). - If the sorted forms match, print
✅ <pair> are anagrams.. Otherwise print❌ <pair> are NOT anagrams.. Use an f-string or just+joining. - At the end, print a one-line tally — how many pairs were anagrams, using a counter you incremented inside the loop.
Bring anagram_pairs.py next class. In PY-L1-26 we start the biggest move of Level 1 — turning patterns like this into reusable functions with def.
Sample · anagram_pairs.py
# anagram_pairs.py — batch anagram checker pairs = [ ["listen", "silent"], ["nasi", "sani"], ["raja", "jari"], ["dorm itory", "dirty room"], ] hits = 0 for pair in pairs: a = pair[0].strip().lower().replace(" ", "") b = pair[1].strip().lower().replace(" ", "") if sorted(a) == sorted(b): print("✅", pair[0], "and", pair[1], "are anagrams.") hits = hits + 1 else: print("❌", pair[0], "and", pair[1], "are NOT anagrams.") print("Anagram pairs found:", hits, "out of", len(pairs))
The shape is exactly the Detective from class, minus the input() and plus a for loop. The two real ideas are: (1) reuse the cleaning chain so messy strings still count, and (2) keep a running counter outside the loop so you can summarise at the end.