Greeting Formatter Class
An easy Python interview practice problem on DataDriven. Write the Python and run it against test cases, with instant feedback.
- Domain
- Python
- Difficulty
- easy
- Seniority
- L3
- Asked in
- Amazon
Problem
You're building a small text-cleanup utility as a class. Implement MessageFormatter with a method sort_by_case(text) that returns text regrouped so every lowercase letter comes first, then every uppercase letter, then everything else (digits, spaces, punctuation), with each character keeping the position it had within its own group. Also expose a top-level sort_by_case(text) that builds a MessageFormatter, runs the method, and returns the string; that driver is the graded entry point.
First impressions are formatted carefully.
Example 1
Input:
text = "hElLo"
Output:
"hloEL"
Example 2
Input:
text = "PyThOn"
Output:
"yhnPTO"
Worked solution and explanation
What this really is
Strip the 'formatter' costume and this is a stable three-way partition: lowercase, uppercase, everything else, with each character holding the position it had inside its own group. Anyone can bucket the characters. The tell is whether you keep them STABLE. Reach for a sort keyed on case and you scramble the within-group order the problem quietly demands, and it is just as easy to let the digits and spaces disappear into a letter bucket. The class-and-driver shape is the second half: the object does the work, but a plain top-level sort_by_case(text) is what gets graded, so the callable surface has to delegate cleanly.
Break it down
Step 1: Walk the text once
Make three empty lists and iterate the characters of text a single time. Appending as you go keeps each character in the order it appeared, which is exactly the stability the result needs.
Step 2: Classify each character
For each character, ask islower() first, then isupper(); anything that answers no to both (digits, spaces, punctuation) falls through to the third list. The order of the checks does not matter as long as non-letters have a home.
Step 3: Concatenate in case order
Join the three lists and concatenate them lowercase, then uppercase, then the rest. Building the strings once at the end with join avoids repeated string concatenation inside the loop.
Step 4: Expose the driver
The class does the work, but the grader calls the top-level sort_by_case(text). Have it construct a MessageFormatter, call its sort_by_case(text), and return the string, so the object design stays behind a plain callable surface.
The solution
class MessageFormatter:
def sort_by_case(self, text):
lower = []
upper = []
other = []
for char in text:
if char.islower():
lower.append(char)
elif char.isupper():
upper.append(char)
else:
other.append(char)
return ''.join(lower) + ''.join(upper) + ''.join(other)
def sort_by_case(text):
return MessageFormatter().sort_by_case(text)Common follow-up questions
- What if digits and punctuation should sit between the lowercase and uppercase runs instead of last? (Tests extending the partitioning to a different number of groups or a different group order.)
- How would you make this case-insensitive grouping while preserving each character's case? (Tests using a key that maps both cases to the same bucket while keeping the original casing.)
- What if the class should store the text and rewrite it in place? (Tests giving the class real state and a method that mutates it rather than returning a new string.)