3.04 Strings

Source lesson: python/strings-intercepters

Learning Objective: Index and slice strings, clean and search text with string methods, and build new strings with concatenation, f-strings and .join(). Strings are immutable, so every step saves a new string instead of editing the old one.

Popcorn Hack 1: Extract the Hidden Message

Indexing and slicing only, no string methods. "SIGNAL" is at 2–7, "xxx" is at 8–10, so "CONFIRMED" runs from 11 to 19 and the slice stops at 20.

Code Runner Challenge

Popcorn Hack 1 - Extract the hidden message using indexing and slicing

View IPYNB Source
# CODE_RUNNER: Popcorn Hack 1 - Extract the hidden message using indexing and slicing
transmission = "xxSIGNALxxxCONFIRMEDxx77xxDELTA"

# TODO 1: "SIGNAL" starts at index 2 and is 6 characters long -> stop at 2 + 6 = 8
word_1 = transmission[2:8]
print("Word 1:", word_1)

# TODO 2: "CONFIRMED" starts right after "SIGNALxxx" (index 11) and is 9 characters long
word_2 = transmission[11:20]
print("Word 2:", word_2)

# TODO 3: negative slicing -> the last 5 characters
word_3 = transmission[-5:]
print("Word 3:", word_3)

# TODO 4: total characters in the full transmission
print("Total length:", len(transmission))

# TODO 5: every other character
print("Every other character:", transmission[::2])
Lines: 1 Characters: 0
Output
Click "Run" in code control panel to see output ...

Is any of the message still visible with a step of 2? Only scraps. The output is xSGAxxOFREx7xDLA: SGA is half of SIGNAL, OFRE is half of CONFIRMED, and DLA is half of DELTA. Every other character drops half of each word, so the hidden words can’t be read this way. You need the exact start and stop positions.

Popcorn Hack 2: Scrub and Search a Noisy Transmission

Every method returns a new string, so each result is saved into a new variable.

Code Runner Challenge

Popcorn Hack 2 - Clean and search a noisy transmission using string methods

View IPYNB Source
# CODE_RUNNER: Popcorn Hack 2 - Clean and search a noisy transmission using string methods
noisy = "   ...AGENT>>>Falcon---reports: the PACKAGE has ARRIVED!!!   "

# TODO 1: remove leading/trailing whitespace
trimmed = noisy.strip()
print("Trimmed:", repr(trimmed))

# TODO 2: remove every ">", "-", and "!" (one .replace() per character)
cleaned = trimmed.replace(">", "").replace("-", "").replace("!", "")
print("Cleaned:", cleaned)

# TODO 3: all-lowercase copy
lowered = cleaned.lower()
print("Lowered:", lowered)

# TODO 4: case-insensitive search
has_arrived = "arrived" in lowered
print("Contains 'arrived':", has_arrived)

# TODO 5: split on whitespace and count the words
words = cleaned.split()
print("Word count:", len(words))
Lines: 1 Characters: 0
Output
Click "Run" in code control panel to see output ...

Popcorn Hack 3: Build a Decoded Report

Code Runner Challenge

Popcorn Hack 3 - Build a decoded report using concatenation and formatting

View IPYNB Source
# CODE_RUNNER: Popcorn Hack 3 - Build a decoded report using concatenation and formatting
agent_name = "Falcon"
target_word = "MIDNIGHT"
confidence = 87  # a percentage, stored as an int
fragments = ["ALPHA", "SEVEN", "DELTA"]

# TODO 1: + concatenation
headline = "Agent " + agent_name + " intercepted: " + target_word
print(headline)

# TODO 2: confidence is an int, so convert it with str() before using +
confidence_line = "Confidence: " + str(confidence) + "%"
print(confidence_line)

# TODO 3: same line with an f-string (no str() needed)
confidence_line_fstring = f"Confidence: {confidence}%"
print(confidence_line_fstring)

# TODO 4: glue the list into one string
joined_fragments = "-".join(fragments)
print("Joined fragments:", joined_fragments)

# TODO 5: one final report line
final_report = f"REPORT: {headline} | {confidence_line} | Fragments: {joined_fragments}"
print(final_report)
Lines: 1 Characters: 0
Output
Click "Run" in code control panel to see output ...

Homework: Crack the Final Transmission

Uses all three skills on a CSV row: .strip() + .split(","), indexing into the list of fields, a slice (no method) to check the year, .replace() + .lower() + in to search the message, then f-strings to rebuild it as a Markdown table row and a JSON line.

Code Runner Challenge

Homework - Crack the Final Transmission using slicing, methods, and formatting

View IPYNB Source
# CODE_RUNNER: Homework - Crack the Final Transmission using slicing, methods, and formatting
raw_transmission = "  2026-09-15,GHOST,THE-EAGLE-LANDS-AT-DAWN,87  "

# TODO 1: strip the outer whitespace, then split the CSV row on commas
segments = raw_transmission.strip().split(",")
print("Segments:", segments)

# TODO 2: pull each field out by index
date = segments[0]
agent = segments[1]
message_code = segments[2]
confidence_str = segments[3]
print("Date:", date, "| Agent:", agent, "| Message code:", message_code, "| Confidence:", confidence_str)

# TODO 3: slicing (not a method) to confirm the year
year_check = date[0:4] == "2026"
print("Year check:", year_check)

# TODO 4: dashes -> spaces
message = message_code.replace("-", " ")

# TODO 5: case-insensitive search for "dawn"
found_dawn = "dawn" in message.lower()
print("Found 'dawn':", found_dawn)

# TODO 6: Markdown table row
markdown_row = f"| {date} | {agent} | {message} | {confidence_str}% |"
print("Markdown row:", markdown_row)

# TODO 7: JSON-style line (lowercase boolean for JSON)
json_line = "{" + f'"date": "{date}", "agent": "{agent}", "message": "{message}", "confidence": {confidence_str}, "contains_dawn": {str(found_dawn).lower()}' + "}"
print("JSON line:", json_line)
Lines: 1 Characters: 0
Output
Click "Run" in code control panel to see output ...

In the JSON line, the opening and closing braces are added as plain strings so they print literally, while the f-string’s single curly braces are the placeholders. The confidence goes in without quotes because it’s a number in JSON, and str(found_dawn).lower() turns Python’s True into JSON’s true.