Python, Concept by Concept › Strings
Exercises: Strings
Core work is Exercises 1–10. Exercises 11–25 are More Practice, and Exercises 26–29 are optional Challenges. Define each named function and try every worked sample call.
Keep each exact function name and parameter. Return the promised value unless the specification says to print a report. Add a short purpose comment and use meaningful local names. The worked calls and expected outputs are text to guide your own checks.
Exercise 1: Badge Line
A club badge needs two initials, a three-character code piece, and the code length.
Specification: Define badge_line(first, last, code). Use position 0 from first and last. Use the slice code[2:5]. Return one string in the shape initials | piece | length. Build it with string concatenation, and use str(len(code)) for the final part.
Worked sample calls:
badge_line("Mira", "Stone", "AX742Q") -> "MS | 742 | 6"
badge_line("Leo", "Park", "ZZcat9") -> "LP | cat | 6"
badge_line("Nia", "Young", "12SUN") -> "NY | SUN | 5"
Real program
The real program reads a first name, last name, and badge code on separate lines with input().
How this is checked: Checked by tests that run your function badge_line.
Exercise 2: Clean a Route Label
A route board receives labels with spaces at the ends and underscores between words.
Specification: Define clean_route(text). Remove spaces from the ends, replace each underscore with a single space, and return the result in uppercase. Use only the taught string methods.
Worked sample calls:
clean_route(" north_gate " ) -> "NORTH GATE"
clean_route("moon_base") -> "MOON BASE"
clean_route(" red_fox_2 " ) -> "RED FOX 2"
Real program
The real program reads one route label with input().
How this is checked: Checked by tests that run your function clean_route.
Exercise 3: Palindrome Gate
A word gate opens when its text reads the same from both ends.
Specification: Define is_palindrome(text). Make a lowercase string with spaces replaced by empty text. Use exactly for i in range(len(cleaned) // 2). Compare cleaned[i] with cleaned[len(cleaned) - 1 - i]. Return False inside the loop on a mismatch, and return True after the loop.
Worked sample calls:
is_palindrome("Taco cat") -> True
is_palindrome("python") -> False
is_palindrome("Level") -> True
Real program
The real program reads one word or phrase with input().
How this is checked: Checked by tests that run your function is_palindrome.
Exercise 4: Classify a Character
A message checker labels each character as a vowel, consonant, or other character.
Specification: Define classify_char(ch). Lowercase ch. If it is in "aeiou", return "vowel". Elif it is in "abcdefghijklmnopqrstuvwxyz", return "consonant". Else return "other".
Worked sample calls:
classify_char("U") -> "vowel"
classify_char("m") -> "consonant"
classify_char("7") -> "other"
Real program
The real program reads one character with input().
How this is checked: Checked by tests that run your function classify_char.
Exercise 5: Mask the Vowels
A puzzle display hides vowels but leaves every other character unchanged.
Specification: Define mask_vowels(text). Start a new string as empty. Visit each character in text. If its lowercase form is in "aeiou", add "*" to the new string; else add the original character. Return the completed new string. Do not change the original string.
Worked sample calls:
mask_vowels("Rocket") -> "R*ck*t"
mask_vowels("SKY") -> "SKY"
mask_vowels("A-OK!") -> "*-*K!"
Real program
The real program reads one message with input().
How this is checked: Checked by tests that run your function mask_vowels.
Exercise 6: First Matching Position
A decoder needs the first position where a chosen character appears.
Specification: Define position(text, ch). Loop through range(len(text)). Return i inside the loop at the first position where text[i] == ch. Return -1 after the loop when no position matched. The return value is an integer.
Worked sample calls:
position("banana", "n") -> 2
position("cocoa", "o") -> 1
position("planet", "x") -> -1
Real program
The real program reads a text and a chosen character on separate lines with input().
How this is checked: Checked by tests that run your function position.
Exercise 7: Alphabet Scan Report
A word lab needs a printed table showing the total for every lowercase alphabet letter.
Specification: First define count_char(text, ch). Start an integer counter at 0, visit every character, add 1 when the character equals ch, and return the counter. Then define print_alphabet_scan(text). Lowercase text, print the heading letter | total, loop through "abcdefghijklmnopqrstuvwxyz", call count_char for each letter, and print each row with an f-string. Do not return the table.
Worked sample calls:
count_char("pepper", "p") -> 3
count_char("pepper", "z") -> 0
print_alphabet_scan("Bee") ->
letter | total
a | 0
b | 1
c | 0
d | 0
e | 2
f | 0
g | 0
h | 0
i | 0
j | 0
k | 0
l | 0
m | 0
n | 0
o | 0
p | 0
q | 0
r | 0
s | 0
t | 0
u | 0
v | 0
w | 0
x | 0
y | 0
z | 0
Real program
The real program reads one line of text with input().
How this is checked: Checked by tests that run your function count_char.
Exercise 8: Word Count
A launch report needs its number of words.
Specification: Define word_count(line). Add a purpose comment. Start a counter at 0 and increment it for each word in line.split(). Return the count; do not index the split result. Print the stand-in report with f"Words: {count}".
Worked sample calls:
word_count("rockets need fuel to fly") -> 5
print(f"Words: {word_count('rockets need fuel to fly')}") -> Words: 5
Real program
The real program reads one line of text with input().
How this is checked: Checked by tests that run your function word_count.
Exercise 9: Initials
A crew roster turns full names into badge initials.
Specification: Define initials(line). Add a purpose comment. For each word in line.split(), add word[0].upper() to a result string. Return the result. Here word is a string; do not index the split result.
Worked sample calls:
initials("grace brewster hopper") -> "GBH"
Real program
The real program reads one full name with input().
How this is checked: Checked by tests that run your function initials.
Exercise 10: Valid PIN
A lock accepts exactly four digit characters.
Specification: Define is_valid_pin(pin). Add a purpose comment. Use if len(pin) != 4: to return False, elif not pin.isdigit(): to return False, and else: to return True. Negative numbers are not accepted.
Worked sample calls:
is_valid_pin("4071") -> True
is_valid_pin("40a1") -> False
is_valid_pin("407") -> False
Real program
The real program reads one PIN as text with input().
How this is checked: Checked by tests that run your function is_valid_pin.
Exercise 11: More Practice: Longest Word
A headline editor needs the first longest word.
Specification: Define longest_word(line). Visit words with for word in line.split():, keep the first word whose length is strictly greater than the saved best, and return it. Use f"Longest: {word}" for the stand-in report. Use an empty string when the line has no words.
Worked sample calls:
longest_word("nova rover launch pad") -> "launch"
print(f"Longest: {longest_word('nova rover launch pad')}") -> Longest: launch
Real program
The real program reads one line of text with input().
How this is checked: Checked by tests that run your function longest_word.
Exercise 12: More Practice: Sentence Palindrome
A phrase checker ignores spaces and letter case.
Specification: Define is_sentence_palindrome(text). Remove spaces with replace, lowercase the result, then compare that cleaned string with its reversing slice [::-1]. Return the boolean.
Worked sample calls:
is_sentence_palindrome("Was it a car or a cat I saw") -> True
Real program
The real program reads one sentence with input().
How this is checked: Checked by tests that run your function is_sentence_palindrome.
Exercise 13: More Practice: Run-Length Encoding
A transmitter compresses each run of matching characters.
Specification: Define rle(text). Walk the string in order, count consecutive copies of the current character, and append that character plus str(count) when a run ends. Return the encoded string. For an empty input, return an empty string.
Worked sample calls:
rle("aaabcc") -> "a3b1c2"
Real program
The real program reads one line of text with input().
How this is checked: Checked by tests that run your function rle.
Exercise 14: More Practice: Atbash Cipher
An alphabet mirror swaps lowercase letters from opposite ends.
Specification: Define atbash(text). Set alphabet = "abcdefghijklmnopqrstuvwxyz". For each character, use if ch in alphabet: and append alphabet[25 - alphabet.find(ch)]; otherwise append ch unchanged. Keep capitals, spaces, and punctuation unchanged.
Worked sample calls:
atbash("abc xyz!") -> "zyx cba!"
atbash("Abc!") -> "Ayx!"
Real program
The real program reads one line of text with input().
How this is checked: Checked by tests that run your function atbash.
Exercise 15: More Practice: File Type
A file shelf labels Python and text filenames.
Specification: Define file_type(name). Use endswith and an if/elif/else chain: .py returns "python", .txt returns "text", and any other ending returns "other".
Worked sample calls:
file_type("game.py") -> "python"
file_type("notes.txt") -> "text"
file_type("image.png") -> "other"
Real program
The real program reads one filename with input().
How this is checked: Checked by tests that run your function file_type.
Exercise 16: More Practice: Word Triangle
A title grows one character per line.
Specification: Define word_triangle(word). Build and return a single string with rows word[:i] for i from 1 through len(word), separated by "\n". Do not leave a newline after the last row.
Worked sample calls:
word_triangle("CODE") -> "C\nCO\nCOD\nCODE"
Real program
The real program reads one word with input().
How this is checked: Checked by tests that run your function word_triangle.
Exercise 17: More Practice: Center Text
A display puts a title inside a fixed-width field.
Specification: Define center_text(text, width). Set left = (width - len(text)) // 2 and right = width - len(text) - left. Return " " * left + text + " " * right. Here the right padding is deliberate; do not strip it.
Worked sample calls:
center_text("gnat", 10) -> " gnat "
center_text("gnat", 9) -> " gnat "
Real program
The real program reads a text and a width on separate lines with input().
How this is checked: Checked by tests that run your function center_text.
Exercise 18: More Practice: Letter Spacer
A label puts a dash between its letters.
Specification: Define spaced(text). Use "-".join(text) and return the resulting string.
Worked sample calls:
spaced("ROBOT") -> "R-O-B-O-T"
Real program
The real program reads one word with input().
How this is checked: Checked by tests that run your function spaced.
Exercise 19: More Practice: Rotate Left
A code wheel moves its first letter to the end.
Specification: Define rotate_left(word). Return word[1:] + word[0] for a nonempty word.
Worked sample calls:
rotate_left("nova") -> "ovan"
Real program
The real program reads one nonempty word with input().
How this is checked: Checked by tests that run your function rotate_left.
Exercise 20: More Practice: Ends of a Word
A compact label shows the first and last few letters.
Specification: Define ends(word, k). Return word[:k] + "..." + word[-k:]. Use a positive k that is no larger than the word length.
Worked sample calls:
ends("telescope", 3) -> "tel...ope"
Real program
The real program reads a word and a positive k on separate lines with input().
How this is checked: Checked by tests that run your function ends.
Exercise 21: More Practice: Spam Check
A message filter looks for two warning words.
Specification: Define is_spammy(text). Lowercase the message, then return whether "win" in cleaned or "free" in cleaned.
Worked sample calls:
is_spammy("You WIN a prize") -> True
is_spammy("See you at noon") -> False
Real program
The real program reads one message with input().
How this is checked: Checked by tests that run your function is_spammy.
Exercise 22: More Practice: Common Letters
A puzzle keeps shared letters in first-word order.
Specification: Define common_letters(first, second). For each character in first, add it to the result only when it is in second and not already in the result. Return the result.
Worked sample calls:
common_letters("thunder", "under") -> "under"
Real program
The real program reads two words on separate lines with input().
How this is checked: Checked by tests that run your function common_letters.
Exercise 23: More Practice: Word Box
A word becomes the top, sides, and bottom of a frame.
Specification: Define word_box(word) for a word of at least two letters. Return the first row word, then each inside row word[i] + " " * (len(word) - 2) + word[-1 - i] for i from 1 to len(word) - 2, then the last row word[::-1]. Join rows with "\n" and leave no trailing spaces or final newline.
Worked sample calls:
word_box("CODE") -> "CODE\nO D\nD O\nEDOC"
Real program
The real program reads one word with input().
How this is checked: Checked by tests that run your function word_box.
Exercise 24: More Practice: First Vowel
A decoder needs the earliest vowel position.
Specification: Define first_vowel(text). Use for i in range(len(text)); return i immediately when text[i].lower() in "aeiou". Return -1 after the loop if none appears.
Worked sample calls:
first_vowel("rhythm and blues") -> 7
first_vowel("rhythm") -> -1
Real program
The real program reads one line of text with input().
How this is checked: Checked by tests that run your function first_vowel.
Exercise 25: More Practice: Has a Digit
A label checker stops at its first digit.
Specification: Define has_digit(text). Visit characters in order. Return True immediately at the first ch.isdigit(). Return False after the loop if no digit appears.
Worked sample calls:
has_digit("launch42") -> True
has_digit("nova") -> False
Real program
The real program reads one line of text with input().
How this is checked: Checked by tests that run your function has_digit.
Exercise 26: Alternating Case
A sign painter alternates uppercase and lowercase characters by position.
Specification: Define alternating_case(text). Start an empty result string. Loop through range(len(text)). Add text[i].upper() when i % 2 == 0; else add text[i].lower(). Return the completed string. Spaces and punctuation stay in their positions.
Worked sample calls:
alternating_case("python") -> "PyThOn"
alternating_case("moon base") -> "MoOn bAsE"
alternating_case("A1b2!") -> "A1B2!"
Real program
The real program reads one line of text with input().
How this is checked: Checked by tests that run your function alternating_case.
Exercise 27: Caesar Shift
A puzzle transmitter shifts letters forward and wraps around the alphabet.
Specification: First define position(alphabet, ch) with the same left-to-right search as Exercise 6: return i inside the loop for a match and -1 after the loop. Then define shift(message, k) for k >= 0. Set alphabet to "abcdefghijklmnopqrstuvwxyz", lowercase the message, and build a new string character by character. For each character, call position(alphabet, ch). If it returns -1, add the unchanged character. Else use (pos + k) % 26 and alphabet indexing to add the shifted letter. Return the new string.
Worked sample calls:
position("abcdefghijklmnopqrstuvwxyz", "q") -> 16
shift("Code 9!", 2) -> "eqfg 9!"
shift("XYZ", 3) -> "abc"
shift("stay", 0) -> "stay"
Real program
The real program reads a message and a shift amount on separate lines with input().
How this is checked: Checked by tests that run your functions position, shift.
Exercise 28: Word Wrap
A display fits whole words within a width.
Specification: Define wrap(line, width). Visit words with for word in line.split(): and build one current line plus a result string. The first word gets no leading space. Join a later word when len(current) + 1 + len(word) <= width; otherwise close the current line with "\n" and start a new line. A word longer than width sits alone. Return the wrapped string with no trailing newline.
Worked sample calls:
wrap("the quick brown fox jumps", 10) -> "the quick\nbrown fox\njumps"
Real program
The real program reads a line of text and a width on separate lines with input().
How this is checked: Checked by tests that run your function wrap.
Exercise 29: Safe Number
A numeric field may contain non-digits.
Specification: Define to_number(text). If text.isdigit() is true, return int(text); otherwise return -1. Negative text such as "-3" is not accepted.
Worked sample calls:
to_number("42") -> 42
to_number("4x") -> -1
to_number("-3") -> -1
Real program
The real program reads one number written as text with input().
How this is checked: Checked by tests that run your function to_number.