Mask Phone Number

Mask Phone Number

Write a function that masks all but the last four digits of a digit string, replacing the rest with *.

mask_phone_number(s)

s is a string of digits. Replace every digit except the last four with "*". If s has 4 or fewer digits, return it unchanged (nothing to mask).

Examples

mask_phone_number("5551234567")  // → "******4567"   (10 digits, last 4 kept)
mask_phone_number("123456")       // → "**3456"        (6 digits, last 4 kept)
mask_phone_number("1234")          // → "1234"          (exactly 4, nothing masked)

Walkthrough

Thinking it through

import re


def mask_phone_number(s):
    return re.sub(r"\d(?=\d{4})", "*", s)

This is the exact lookahead example from the patterns-and-groups lesson, put to use. The pattern \d(?=\d{4}) reads as: match a digit, but only if it's immediately followed by exactly 4 more digits — and importantly, the lookahead (?=\d{4}) doesn't consume those 4 digits, so they remain available to be checked (and not matched/replaced) as the scan continues.

Walk through "5551234567" (10 digits): the scan checks each position — is there a digit here, followed by at least 4 more digits? For the first 6 digits (555123), yes — each has at least 4 digits after it, so re.sub replaces all 6 with *. The last 4 digits (4567) each fail the lookahead (there aren't 4 more digits after them), so they're left untouched. Result: "******4567".

For "1234" (exactly 4 digits), no digit has 4 more digits following it — even the very first 1 only has 3 digits after it (234). So nothing matches the pattern, and re.sub returns the string unchanged, which is exactly the required "4 or fewer digits" behavior — no special-case code needed at all, since the lookahead naturally handles it.

main.py
Console
Press Run to execute your code, or Submit to test and complete this problem.