ETOOBUSY 🚀 minimal blogging for the impatient
PWC185 - Mask Code
TL;DR
On with TASK #2 from The Weekly Challenge #185. Enjoy!
The challenge
You are given a list of codes in many random format.
Write a script to mask first four characters (a-z,0-9) and keep the rest as it is.
Example 1
Input: @list = ('ab-cde-123', '123.abc.420', '3abc-0010.xy') Output: ('xx-xxe-123', 'xxx.xbc.420', 'xxxx-0010.xy')
Example 2
Input: @list = ('1234567.a', 'a-1234-bc', 'a.b.c.d.e.f') Output: ('xxxx567.a', 'x-xxx4-bc', 'x.x.x.x.e.f')
The questions
Just a few annoyances…
- confirmation: are we using
x
to concealx
? - What if there are not enough characters to mask?
The solution
There are times for clever solutions that take a smart regular expression and provide a way to impress the others.
There are other times where you can’t come up with any, so you just decide to go one character at a time and call it a day. Which, to be honest, I find super-clever because, you know, readability.
So, as we’re going for readability here, I’ll call also insecure week
and get rid of strict
and warnings
again, just because I like living
on the edge.
#!/usr/bin/env perl
say for mask_code(qw< ab-cde-123 123.abc.420 3abc-0010.xy
1234567.a a-1234-bc a.b.c.d.e.f >);
sub mask_code {
state $is_target = { map { $_ => 1 } ('0' .. '9', 'a' .. 'z') };
map {
my $copy = $_;
my ($i, $I, $n) = (0, length($copy), 0);
while ($n < 4 && $i < $I) {
if ($is_target->{substr $copy, $i, 1}) {
substr $copy, $i, 1, 'x';
++$n;
}
++$i;
}
$copy;
} @_;
}
I’m not sure whether I’m prematurely optimizing here with the test
about applicable characters using a state
hash reference. I mean, a
regular expression would have worked fine too:
if (substr($copy, $i, 1) =~ m{[a-z0-9]}mxs) { ...
Anyway, life is full of decisions.
Translation to Raku made me trip over a flat
, once again. I really
need to remember to tidy up my flat.
#!/usr/bin/env raku
use v6;
sub MAIN {
.put for mask-code(< ab-cde-123 123.abc.420 3abc-0010.xy
1234567.a a-1234-bc a.b.c.d.e.f >);
}
sub mask-code (@list) {
state %is-target = ('0' .. '9', 'a' .. 'z').flat.map: * => 1;
@list.map: -> $s is copy {
my ($i, $I, $n) = (0, $s.chars, 0);
while $n < 4 && $i < $I {
if %is-target{$s.substr($i, 1)} {
++$n;
$s.substr-rw($i, 1) = 'x';
}
++$i;
}
$s;
};
}
As a final suggestion… don’t do like me.
use strict
.
use warnings
.
Stay safe!