Perl Weekly Challenge 215.

My solutions (task 1 and task 2 ) to the The Weekly Challenge - 215.

Task 1: Odd one Out

Submitted by: Mohammad S Anwar
You are given a list of words (alphabetic characters only) of same size.

Write a script to remove all words not sorted alphabetically and print the
number of words in the list that are not alphabetically sorted.


Example 1
Input: @words = ('abc', 'xyz', 'tsu')
Output: 1

The words 'abc' and 'xyz' are sorted and can't be removed.
The word 'tsu' is not sorted and hence can be removed.
Example 2
Input: @words = ('rat', 'cab', 'dad')
Output: 3

None of the words in the given list are sorted.
Therefore all three needs to be removed.
Example 3
Input: @words = ('x', 'y', 'z')
Output: 0

I can solve this task by splitting each word into letters, sorting them, joining them back and comparing them to the original word. I can grep those that change and count them. This yields a small oneliner:

perl -E 'say "@ARGV -> ", 0+grep {(join "", sort {$a cmp $b} split "") ne $_} @ARGV' abc xyz tsu
perl -E 'say "@ARGV -> ", 0+grep {(join "", sort {$a cmp $b} split "") ne $_} @ARGV' rat cab dad
perl -E 'say "@ARGV -> ", 0+grep {(join "", sort {$a cmp $b} split "") ne $_} @ARGV' x y z

Results:

abc xyz tsu -> 1
rat cab dad -> 3
x y z -> 0

The full code is essentially identical:

 1  # Perl weekly challenge 215
 2  # Task 1:  Odd one Out
 3  #
 4  # See https://wlmb.github.io/2023/05/01/PWC215/#task-1-odd-one-out
 5  use v5.36;
 6  die <<~"FIN" unless @ARGV;
 7      Usage: $0 W1 [W2...]
 8      to count words whose letters are not sorted
 9      FIN
10  say "@ARGV -> ", 0+grep {(join "", sort {$a cmp $b} split "") ne $_} @ARGV;

Example:

./ch-1.pl abc xyz tsu
./ch-1.pl rat cab dad
./ch-1.pl x y z

Results:

abc xyz tsu -> 1
rat cab dad -> 3
x y z -> 0

Task 2: Number Placement

Submitted by: Mohammad S Anwar
You are given a list of numbers having just 0 and 1. You are also given
placement count (>=1).

Write a script to find out if it is possible to replace 0 with 1 in the
given list. The only condition is that you can only replace when there is
no 1 on either side. Print 1 if it is possible otherwise 0.

Example 1:
Input: @numbers = (1,0,0,0,1), $count = 1
Output: 1

You are asked to replace only one 0 as given count is 1.
We can easily replace middle 0 in the list i.e. (1,0,1,0,1).
Example 2:
Input: @numbers = (1,0,0,0,1), $count = 2
Output: 0

You are asked to replace two 0's as given count is 2.
It is impossible to replace two 0's.
Example 3:
Input: @numbers = (1,0,0,0,0,0,0,0,1), $count = 3
Output: 1

I guess that being the first number means there is no 1 to the left, and being the last means there is no 1 to the right, so 0,0,0 may become 1,0,1. To solve the challenge I assume the input is a string. I can use Perl’s substitute to add a 0 to the right and left and count how many groups of three consecutive zeroes there are, i.e., how many 000’s may be replaced, one at a time, from left to right, by ‘010’. This fits a oneliner.

Example 1:

perl -E '
($n, $x)=@ARGV; for($x){s/^/0/; s/$/0/; ++$c while s/000/010/; say "@ARGV->",$c>=$n?1:0}' 1 10001

Results:

1 10001->1

Example 2:

perl -E '
($n, $x)=@ARGV; for($x){s/^/0/; s/$/0/; ++$c while s/000/010/; say "@ARGV->",$c>=$n?1:0}' 2 10001

Results:

2 10001->0

Example 3:

perl -E '
($n, $x)=@ARGV; for($x){s/^/0/; s/$/0/; ++$c while s/000/010/; say "@ARGV->",$c>=$n?1:0}' 3 100000001

Results:

3 100000001->1

The full code adds a few checks.

 1  # Perl weekly challenge 215
 2  # Task 2:  Number Placement
 3  #
 4  # See https://wlmb.github.io/2023/05/01/PWC215/#task-2-number-placement
 5  use v5.36;
 6  die <<~"FIN" unless @ARGV==2;
 7      Usage: $0 N S
 8      to find if I can replace N 1's in the string S consisting of 0's and 1's
 9      Only 0's that don't have a 1 to their left nor right may be replaced.
10      FIN
11  my $count=shift;
12  my $copy=my $orig=shift;
13  for($copy){ # localize
14      die "Only 0's and 1's allowed. Invalid input: $_" unless /^[01]*$/;
15      s/^/0/; # add leading and trailing 0's
16      s/$/0/;
17      my $replacements=0;
18      $replacements++ while s/000/010/; # count replacements
19      say "Count: $count, string: $orig -> ", $replacements>=$count? 1:0;
20  }

Examples:

./ch-2.pl 1 10001
./ch-2.pl 2 10001
./ch-2.pl 3 100000001

Results:

Count: 1, string: 10001 -> 1
Count: 2, string: 10001 -> 0
Count: 3, string: 100000001 -> 1

/;

Written on May 1, 2023