Perl Weekly Challenge 185.
My solutions (task 1 and task 2 ) to the The Weekly Challenge - 185.
Task 1: MAC Address
Submitted by: Mohammad S Anwar
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
Assuming the input is correct, I can first split into three four-digit
hexadecimal numbers, split each number into its individual digits,
join them in pairs and join the pairs back together with ‘:’. Using pairs
from List::Util
the result is the following one-liner:
perl -MList::Util=pairs -E '
say "$_ -> ", join ":", map {join "", @$_} pairs map {split ""} split /\./, $_ for @ARGV
' 1ac2.34f0.b1c2 abc1.20f1.345a
Results:
1ac2.34f0.b1c2 -> 1a:c2:34:f0:b1:c2
abc1.20f1.345a -> ab:c1:20:f1:34:5a
The full code adds some checking.
1 # Perl weekly challenge 185
2 # Task 1: MAC Address
3 #
4 # See https://wlmb.github.io/2022/10/03/PWC185/#task-1-mac-address
5 use v5.36;
6 use List::Util qw(all pairs);
7 use experimental "try";
8 die "Usage: $0 S1 [S2...]\nto convert strings Sn from hhhh.hhhh.hhhh to hh:hh:hh:hh:hh:hh"
9 unless @ARGV;
10 for (@ARGV) {
11 try {
12 my @quads=split /\./;
13 die "Expected 3 parts" unless @quads==3;
14 die "Expected 4-hex-digit parts" unless all {m/[0-9a-f]{4}/} @quads;
15 say "$_ -> ", join ":", map {join "", @$_} pairs map {split ""} @quads;
16 }
17 catch ($m) {
18 say "Failed for $_: $m";
19 }
20 }
Example:
./ch-1.pl 1ac2.34f0.b1c2 abc1.20f1.345a 1ac2.34f0 1ac2.34f0.b1c gac2.34f0.b1c2
Results:
1ac2.34f0.b1c2 -> 1a:c2:34:f0:b1:c2
abc1.20f1.345a -> ab:c1:20:f1:34:5a
Failed for 1ac2.34f0: Expected 3 parts at ./ch-1.pl line 14.
Failed for 1ac2.34f0.b1c: Expected 4-hex-digit parts at ./ch-1.pl line 15.
Failed for gac2.34f0.b1c2: Expected 4-hex-digit parts at ./ch-1.pl line 15.
Task 2: Mask Code
Submitted by: Mohammad S Anwar
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')
I split the inputs into individual characters, substitute them by x if
they are in the class [a-z0-9]
, stoping at four substitutions, and
then I join then together. Any other character, such as punctuation
characters, are passed without change. This is done by the following one-liner.
perl -E '
for(@ARGV){$n=0; say "$_ -> ", join "", map {$n<4 && ($n+=s/[A-Za-z0-9]/x/); $_} split ""}
' 'ab-cde-123', '123.abc.420', '3abc-0010.xy' '1234567.a', 'a-1234-bc', 'a.b.c.d.e.f'
I could have used tr///
instead of s///
. I admitted uppercase
letters. I could have also admitted non-ascii letters.
Results:
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
The full code is mainly the same.
1 # Perl weekly challenge 185
2 # Task 2: Mask Code
3 #
4 # See https://wlmb.github.io/2022/10/03/PWC185/#task-2-mask-code
5 use v5.36;
6 for(@ARGV){
7 my $n=0;
8 say "$_ -> ", join "", map {$n<4 && ($n+=s/[A-Za-z0-9]/x/); $_} split ""
9 }
Example:
./ch-2.pl ab-cde-123 123.abc.420 3abc-0010.xy 1234567.a a-1234-bc a.b.c.d.e.f
Results:
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