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
Written on October 3, 2022