Harbor Radio Digit Masking
A harbor radio log is shared with external partners, but some of the numeric identifiers inside each message need partial masking before the text leaves the operations room. The policy is simple to state but slightly awkward to implement: keep only the last three digits that appear anywhere in the message, and replace every earlier digit with *. Non-digit characters must stay exactly as they are.
The masking rule is based on the total digit sequence, not on separate number groups. That means you have to think about all digits in the message together. For example, "Dock 12 -> Crane 9087" contains the digits 1, 2, 9, 0, 8, 7. The last three are 0, 8, 7, so the masked result should be "Dock ** -> Crane *087".
If a message contains three digits or fewer, nothing should be hidden. A text like "Gate 404" stays "Gate 404". If there are no digits at all, the original message should come back unchanged.
This makes the task more than a quick replacement. Whether a digit should stay visible depends on how many digits appear later in the string, so the solution needs a little bookkeeping before it can decide what to mask.
Example Input & Output
Only the final three digits in the whole message remain visible.
There are only three digits total, so nothing is masked.
A message with no digits should be returned unchanged.
Algorithm Flow

Solution Approach
The main challenge here is that you cannot decide whether to hide a digit just by looking at that single character in isolation. A digit is visible only if it belongs to the last three digits in the whole message. That means the code needs global context.
One clean way to handle that is with two passes. In the first pass, count how many digits appear in the message. In the second pass, walk through the characters again and decide, for each digit, whether it falls before or inside the final three-digit window.
That logic can be written like this:
The variable seen tracks how many digits have already been processed from left to right. If the current digit still lies before the final three, it becomes *. Otherwise it stays visible. Because non-digit characters are copied straight into the result, the message keeps its original punctuation, spacing, arrows, and labels.
You could also solve the same problem from right to left by reversing through the string and keeping the first three digits you encounter in that direction. That approach works too, but the two-pass left-to-right version is often easier to read because the masking rule is spelled out directly using counts.
So the key idea is not a special string method. It is recognizing that the masking decision depends on the total number of digits in the message, which naturally pushes the solution toward counting plus conditional rebuilding. That is what gives this challenge its medium difficulty: the string is still simple, but the decision rule reaches beyond one character at a time.
Best Answers
def mask_radio_digits(message):
keep = 3
result = list(message)
for i in range(len(message) - 1, -1, -1):
if message[i].isdigit():
if keep > 0:
keep -= 1
else:
result[i] = "*"
return "".join(result)Comments (0)
Join the Discussion
Share your thoughts, ask questions, or help others with this Challenge.
