S3Q2 · Ubbi Dubbi - Add "ub"/"dub" Alternately Before Vowels¶
⚡ Quick Reference
Type: File-in, stdout-out
Core idea: read the file, iterate character by character, insert "ub" before odd-numbered vowels and "dub" before even-numbered vowels. Counter continues across lines.
import tempfile, sys
_, filename = tempfile.mkstemp(prefix="case")
with open(filename, 'w') as f:
f.write(sys.stdin.read())
vowels = set("aeiou")
count = 0
with open(filename, 'r') as f:
for line in f:
result = []
for ch in line:
if ch in vowels:
count += 1
prefix = "ub" if count % 2 == 1 else "dub"
result.append(prefix + ch)
else:
result.append(ch)
print("".join(result), end="")
Key rules:
- Odd vowel count → prefix "ub" | Even vowel count → prefix "dub"
- Counter is global - continues across lines
- Preserve spaces, newlines, and all non-vowel characters exactly
- Use end="" in print since newlines are already part of the line
Problem Statement¶
Problem (File I/O → stdout)
Read a file of lowercase text. Before each vowel, insert "ub" (odd-numbered vowel) or "dub" (even-numbered vowel). Print the result preserving all formatting.
Example:
hello world
pyhton is good
hubelldubo wuborld
pythdubon ubis gduboubod
Tracing the example¶
Vowel counter is global across both lines:
Line 1: "hello world"
| Char | Vowel? | Count | Prefix | Output |
|---|---|---|---|---|
h |
❌ | - | - | h |
e |
✅ | 1 (odd) | ub |
ube |
l |
❌ | - | - | l |
l |
❌ | - | - | l |
o |
✅ | 2 (even) | dub |
dubo |
|
❌ | - | - | |
w |
❌ | - | - | w |
o |
✅ | 3 (odd) | ub |
ubo |
r |
❌ | - | - | r |
l |
❌ | - | - | l |
d |
❌ | - | - | d |
\n |
❌ | - | - | \n |
Line 1 output: hubelldubo wuborld ✓
Line 2: "pyhton is good" (counter continues at 3)
| Char | Vowel? | Count | Prefix | Output |
|---|---|---|---|---|
p,y,h,t |
❌ | - | - | pyht |
o |
✅ | 4 (even) | dub |
dubo |
n |
❌ | - | - | n |
|
❌ | - | - | |
i |
✅ | 5 (odd) | ub |
ubi |
s |
❌ | - | - | s |
g |
❌ | - | - | g |
o |
✅ | 6 (even) | dub |
dubo |
o |
✅ | 7 (odd) | ub |
ubo |
d |
❌ | - | - | d |
Line 2 output: pythdubon ubis gduboubod ✓
Solution approaches¶
import tempfile
import sys
_, filename = tempfile.mkstemp(prefix="case")
with open(filename, 'w') as f:
f.write(sys.stdin.read())
vowels = set("aeiou")
count = 0
with open(filename, 'r') as f:
for line in f:
result = []
for ch in line:
if ch in vowels:
count += 1
result.append(("ub" if count % 2 == 1 else "dub") + ch)
else:
result.append(ch)
print("".join(result), end="")
import tempfile
import sys
_, filename = tempfile.mkstemp(prefix="case")
with open(filename, 'w') as f:
f.write(sys.stdin.read())
vowels = set("aeiou")
count = 0
output = []
with open(filename, 'r') as f:
text = f.read()
for ch in text:
if ch in vowels:
count += 1
if count % 2 == 1: # odd → "ub"
output.append("ub" + ch)
else: # even → "dub"
output.append("dub" + ch)
else:
output.append(ch)
print("".join(output), end="")
Read the entire file at once and process as a single string - newlines are preserved as \n characters.
import tempfile, sys
_, filename = tempfile.mkstemp(prefix="case")
with open(filename, 'w') as f:
f.write(sys.stdin.read())
vowels = "aeiou"
count = [0] # mutable for closure
def replace_vowel(ch):
count[0] += 1
return ("ub" if count[0] % 2 == 1 else "dub") + ch
with open(filename) as f:
text = f.read()
result = "".join(replace_vowel(ch) if ch in vowels else ch for ch in text)
print(result, end="")
Key takeaways¶
Global counter across lines
The vowel counter must persist across all lines - don't reset it at the start of each line. A counter initialised before the file loop and incremented per vowel handles this correctly.
print(line, end="") preserves newlines
When iterating for line in f, each line already ends with \n. Using print(..., end="") prevents print from adding a second newline, keeping the output formatting intact.
set("aeiou") for O(1) vowel lookup
Storing vowels as a set makes the membership check ch in vowels O(1) instead of O(5). For a string scan, this is a minor but good habit.