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 conceal x?
• 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 >);

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!

Comments? Octodon, , GitHub, Reddit, or drop me a line!