Perl Weekly Challenge 185: MAC Address and Mask Code
These are some answers to the Week 185 of the Perl Weekly Challenge organized by Mohammad S. Anwar.
Task 1: MAC Address
You are given MAC address in the form i.e. hhhh.hhhh.hhhh
.
Write a script to convert the address in the form hh:hh:hh:hh:hh:hh
.
Example 1:
Input: 1ac2.34f0.b1c2
Output: 1a:c2:34:f0:b1:c2
Example 2:
Input: abc1.20f1.345a
Output: ab:c1:20:f1:34:5a
MAC Address in Raku
This is done in a hurry, less than 45 minutes before the deadline. There might be a better or simpler way to solve this task, but using a couple of regexes is so simple that I don’t see any reason to try something else.
for "1ac2.34f0.b1c2", "abc1.20f1.345a" -> $test {
$_ = $test;
s:g/\./:/;
s:g/(\w\w)(\w\w)/$0:$1/;
.say;
}
This script displays the following output:
$ raku ./mac-address.raku
1a:c2:34:f0:b1:c2
ab:c1:20:f1:34:5a
MAC Address in Perl
Also using two regexes in Perl:
use strict;
use warnings;
use feature qw/say/;
for my $test ("1ac2.34f0.b1c2", "abc1.20f1.345a") {
$_ = $test;
s/\./:/g;
s/(\w\w)(\w\w)/$1:$2/g;
say;
}
This script displays the following output:
$ perl ./mac-address.pl
1a:c2:34:f0:b1:c2
ab:c1:20:f1:34:5a
Task 2: Mask Code
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')
Mask Code in Raku
The idea is to iterate over the input string and use a regex substitution to replace alphanumeric characters with “x” four times.
I started this task trying to use only one counter ($count
), but quickly found that there are a number of edge cases where it would not work properly. So we need to manage separately the number of successful matches ($count
) and the place where to start the next search ($/.to
, i.e. the atom next to the last successful match).
Note that I initially used the \w
character class, but then changed it to <[\w] - [_]>
to remove the “_” (underscore) from it.
constant MAX = 4;
my @tests = <ab-cde-123 123.abc.420 3abc-0010.xy 1234567.a
a-1234-bc a.b.c.d.e.f 12__34567.a>;
for @tests -> $test {
my $count = 0;
my $result = $test;
my $pos = 0;
while $count < MAX {
$count++ if $result ~~ s:c($pos)/<[\w] - [_]>/x/;
$pos = $/.to;
}
say "$test\t => $result";
}
This script displays the following output:
$ raku ./mask-code.raku
ab-cde-123 => xx-xxe-123
123.abc.420 => xxx.xbc.420
3abc-0010.xy => xxxx-0010.xy
1234567.a => xxxx567.a
a-1234-bc => x-xxx4-bc
a.b.c.d.e.f => x.x.x.x.e.f
12__34567.a => xx__xx567.a
Mask Code in Perl
I used a different strategy in Perl: the input string is split into an array of characters in order to test each character individually.
use strict;
use warnings;
use feature qw/say/;
use constant MAX => 4;
my @tests = qw<ab-cde-123 123.abc.420 3abc-0010.xy 1234567.a
a-1234-bc a.b.c.d.e.f 12__34567.a>;
for my $test (@tests) {
my $result = "";
my $count = 0;
for my $char (split //, $test) {
if ($count < MAX and $char =~ /[A-Za-z0-9]/) {
$char = 'x';
$count++;
}
$result .= $char;
}
say "$test\t => $result";
}
Note that this program would not work the same way as the Raku program above for strings containing non-ASCII alphanumeric characters, but I don’t really care, since we have not been given any indication on how to manage non-ASCII Unicode characters. It would not be difficult to obtain the same behavior as the Raku program with something like this:
if ($count < MAX and $char =~ /[A-Za-z0-9]/ and $char ne '_') {
This script displays the following output:
$ perl ./mask-code.pl
ab-cde-123 => xx-xxe-123
123.abc.420 => xxx.xbc.420
3abc-0010.xy => xxxx-0010.xy
1234567.a => xxxx567.a
a-1234-bc => x-xxx4-bc
a.b.c.d.e.f => x.x.x.x.e.f
12__34567.a => xx__xx567.a
Wrapping up
The next week Perl Weekly Challenge will start soon. If you want to participate in this challenge, please check https://perlweeklychallenge.org/ and make sure you answer the challenge before 23:59 BST (British summer time) on October 16, 2022. And, please, also spread the word about the Perl Weekly Challenge if you can.
Leave a comment