Perl Weekly Challenge 305.
My solutions (task 1 and task 2 ) to the The Weekly Challenge - 305.
Task 1: Binary Prefix
Submitted by: Mohammad Sajid Anwar
You are given a binary array.
Write a script to return an array of booleans where the partial binary number
up to that point is prime.
Example 1
Input: @binary = (1, 0, 1)
Output: (false, true, true)
Sub-arrays (base-10):
(1): 1 - not prime
(1, 0): 2 - prime
(1, 0, 1): 5 - prime
Example 2
Input: @binary = (1, 1, 0)
Output: (false, true, false)
Sub-arrays (base-10):
(1): 1 - not prime
(1, 1): 3 - prime
(1, 1, 0): 6 - not prime
Example 3
Input: @binary = (1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1)
Output: (false, true, true, false, false, true, false, false, false, false,
false, false, false, false, false, false, false, false, false, true)
I can build the candidate primes one bit at a time by duplicating the
ongoing candidate and adding the current digit. I use the is_prime
test from Math::Prime::Util
for fast checking of primality (or
probable primality if the number is very large). This yields a one liner:
Example 1:
perl -MMath::Prime::Util=is_prime -E '
push @r,is_prime($x=2*$x+$_)?"t":"f" for (@ARGV) ; say "@ARGV -> @r";
' 1 0 1
Results:
1 0 1 -> f t t
Example 2:
perl -MMath::Prime::Util=is_prime -E '
push @r,is_prime($x=2*$x+$_)?"t":"f" for (@ARGV) ; say "@ARGV -> @r";
' 1 1 0
Results:
1 1 0 -> f t f
Example 3:
perl -MMath::Prime::Util=is_prime -E '
push @r,is_prime($x=2*$x+$_)?"t":"f" for (@ARGV) ; say "@ARGV -> @r";
' 1 1 1 1 0 1 0 0 0 0 1 0 1 0 0 1 0 0 0 1
Results:
1 1 1 1 0 1 0 0 0 0 1 0 1 0 0 1 0 0 0 1 -> f t t f f t f f f f f f f f f f f f f t
I chose t
and f
rather than true
and false
for brevity.
The full code is similar, but I encode the binary digits in a single string, so I can test several strings in the same run:
1 # Perl weekly challenge 305
2 # Task 1: Binary Prefix
3 #
4 # See https://wlmb.github.io/2025/01/20/PWC305/#task-1-binary-prefix
5 use v5.36;
6 use Math::Prime::Util qw(is_prime);
7 die <<~"FIN" unless @ARGV;
8 Usage: $0 B0 B1 B2...
9 to test whether the binary substrings of the binary strings B0 B1...
10 represet a prime number.
11 FIN
12 for(@ARGV){
13 warn("Expected a bunary string"), next unless /^[01]*$/;
14 my @digits=split "";
15 my @result;
16 my $x=0;
17 push @result, is_prime($x=2*$x+$_)?"t":"f" for (@digits);
18 say "@digits -> @result";
19 }
Examples:
./ch-1.pl 101 110 11110100001010010001
Results:
1 0 1 -> f t t
1 1 0 -> f t f
1 1 1 1 0 1 0 0 0 0 1 0 1 0 0 1 0 0 0 1 -> f t t f f t f f f f f f f f f f f f f t
Task 2: Alien Dictionary
Submitted by: Mohammad Sajid Anwar
You are given a list of words and alien dictionary character order.
Write a script to sort lexicographically the given list of words based
on the alien dictionary characters.
Example 1
Input: @words = ("perl", "python", "raku")
@alien = qw/h l a b y d e f g i r k m n o p q j s t u v w x c z/
Output: ("raku", "python", "perl")
Example 2
Input: @words = ("the", "weekly", "challenge")
@alien = qw/c o r l d a b t e f g h i j k m n p q s w u v x y z/
Output: ("challenge", "the", "weekly")
I can read the dictionary, make a hash with integer values for each letter and use those values to sort the input. I use a Schwartz transform to split the strings into their letters and a recursive sort function. The solution fits a 3-liner.
Example 1:
perl -E '
$v{$_}=$i++for split"",$d=shift;@s=map{$_->[0]}sort{g($a->[1],$b->[1])}map{[$_,[split
"",$_]]}@ARGV;say"$d; @ARGV -> @s";sub g($x,$y){@x=@$x;@y=@$y;return 0unless@x||@y;
return -1unless@y;return 1unless@x;$c=$v{shift@x}<=>$v{shift@y};return$c||g(\@x,\@y)}
' hlabydefgirkmnopqjstuvwxcz perl python raku
Results:
hlabydefgirkmnopqjstuvwxcz; perl python raku -> raku python perl
Example 2:
perl -E '
$v{$_}=$i++for split"",$d=shift;@s=map{$_->[0]}sort{g($a->[1],$b->[1])}map{[$_,[split
"",$_]]}@ARGV;say"$d; @ARGV -> @s";sub g($x,$y){@x=@$x;@y=@$y;return 0unless@x||@y;
return -1unless@y;return 1unless@x;$c=$v{shift@x}<=>$v{shift@y};return$c||g(\@x,\@y)}
' corldabtefghijkmnpqswuvxyz the weekly challenge
Results:
corldabtefghijkmnpqswuvxyz; the weekly challenge -> challenge the weekly
The full code adds a few tests:
1 # Perl weekly challenge 305
2 # Task 2: Alien Dictionary
3 #
4 # See https://wlmb.github.io/2025/01/20/PWC305/#task-2-alien-dictionary
5 use v5.36;
6 die <<~"FIN" unless @ARGV;
7 Usage: $0 D W1 W2...
8 to sort the words Wi according the the order of
9 letters in the dictionary D. The dictionary is
10 a string with all letters.
11 FIN
12 my %values;
13 my $i=0;
14 $values{lc $_}=$i++ for split "", my $dictionary=shift;
15 die "Non-ascii letters: $dictionary" unless $dictionary =~ /^[a-z]*$/i;
16 my @letters=("A".."Z");
17 die "Missing letters: $dictionary" unless keys %values==@letters;
18 die "Repeated letters: $dictionary" unless length $dictionary == @letters;
19
20 my @sorted= map {$_->[0]}
21 sort {compare($a->[1], $b->[1])}
22 map {[$_, [split "", $_]]} @ARGV;
23 say "$dictionary; @ARGV -> @sorted";
24
25 sub compare($x, $y){
26 my @x=@$x;
27 my @y=@$y;
28 return 0 unless @x||@y; #
29 return -1 unless @y;
30 return 1 unless @x;
31 my $cmp = $values{shift @x}<=>$values{shift @y};
32 return $cmp || compare(\@x,\@y);
33 }
34
Example:
./ch-2.pl hlabydefgirkmnopqjstuvwxcz perl python raku
./ch-2.pl corldabtefghijkmnpqswuvxyz the weekly challenge
Results:
hlabydefgirkmnopqjstuvwxcz; perl python raku -> raku python perl
corldabtefghijkmnpqswuvxyz; the weekly challenge -> challenge the weekly