Perl Weekly Challenge 235.
My solutions (task 1 and task 2 ) to the The Weekly Challenge - 235.
Task 1: Remove One
Submitted by: Mohammad S Anwar
You are given an array of integers.
Write a script to find out if removing ONLY one integer makes it strictly
increasing order.
Example 1
Input: @ints = (0, 2, 9, 4, 6)
Output: true
Removing ONLY 9 in the given array makes it strictly increasing order.
Example 2
Input: @ints = (5, 1, 3, 2)
Output: false
Example 3
Input: @ints = (2, 2, 3)
Output: true
To solve the problem I move the numbers from an input array to an output sorted array counting the number of required deletions. If I delete more than one element, the result is false. The code fits a three-liner which is better explained in the full code below.
Example 1:
perl -E '
sub t {return 1 if @i<=2;push @o, shift @i;while(@i){if($i[0]>$o[-1]){
push @o, shift @i;}else{$o[-1]=shift(@i);++$c;return 0 if $c>=2 || (@o>=2
&& $o[-2]>= $o[-1]);}}return 1;}@i=@ARGV;say "@ARGV -> ", t?"True":"False";
' 0 2 9 4 6
Results:
0 2 9 4 6 -> True
Example 2:
perl -E '
sub t {return 1 if @i<=2;push @o, shift @i;while(@i){if($i[0]>$o[-1]){
push @o, shift @i;}else{$o[-1]=shift(@i);++$c;return 0 if $c>=2 || (@o>=2
&& $o[-2]>= $o[-1]);}}return 1;}@i=@ARGV;say "@ARGV -> ", t?"True":"False";
' 5 1 3 2
Results:
5 1 3 2 -> False
Example 3:
perl -E '
sub t {return 1 if @i<=2;push @o, shift @i;while(@i){if($i[0]>$o[-1]){
push @o, shift @i;}else{$o[-1]=shift(@i);++$c;return 0 if $c>=2 || (@o>=2
&& $o[-2]>= $o[-1]);}}return 1;}@i=@ARGV;say "@ARGV -> ", t?"True":"False";
' 2 2 3
Results:
2 2 3 -> True
The full code follows.
1 # Perl weekly challenge 235
2 # Task 1: Remove One
3 #
4 # See https://wlmb.github.io/2023/09/18/PWC235/#task-1-remove-one
5 use v5.36;
6
7 sub test(@in) {
8 # Removing one element from a one or two element array yields an
9 # empty or a one element trivially sorted array
10 return 1 if @in<=2;
11 my $count=0;
12 my @sorted;
13 push @sorted, shift @in; # initialize
14 while(@in){
15 if($in[0]>$sorted[-1]){ # can move from @in to @sorted
16 # without disordering it?
17 push @sorted, shift @in;
18 }else{ # if not
19 $sorted[-1]=shift(@in); # replace last element of @sorted
20 ++$count;
21
22 return 0
23 if $count>=2 # fail if too many replacements or
24 # if @sorted is not actually ordered
25 || (@sorted>=2 && $sorted[-2] >= $sorted[-1]);
26 }
27 }return 1; # success
28 }
29 die <<~"FIN" unless @ARGV;
30 Usage: $0 N1 {N2...]
31 to find if the array N1, N2... becomes sorted by removing
32 only one element.
33 FIN
34 my @in=@ARGV;
35 my $out=test(@in)?"True":"False";
36 say "@ARGV -> $out";
Examples:
./ch-1.pl 0 2 9 4 6
./ch-1.pl 5 1 3 2
./ch-1.pl 2 2 3
Results:
0 2 9 4 6 -> True
5 1 3 2 -> False
2 2 3 -> True
Task 2: Duplicate Zeros
Submitted by: Mohammad S Anwar
You are given an array of integers.
Write a script to duplicate each occurrence of ZERO in the given array
and shift the remaining to the right but make sure the size of array remain the same.
Example 1
Input: @ints = (1, 0, 2, 3, 0, 4, 5, 0)
Ouput: (1, 0, 0, 2, 3, 0, 0, 4)
Example 2
Input: @ints = (1, 2, 3)
Ouput: (1, 2, 3)
Example 3
Input: @ints = (0, 3, 0, 4, 5)
Ouput: (0, 0, 3, 0, 0)
To solve this challenge I moved numbers from an input array to
an output array. Whenever I see a zero, I push an
additional zero and pop
the last element of the input array, as it
wouldn’t fit in the fixed size output. Care should be taken as the
second zero may not fit into the output. The result fits a oneliner.
Example 1:
perl -E '
@i=@ARGV; while(@i){push @o, shift @i; pop @i, push @o,0 if @i && $o[-1]==0;} say "@ARGV -> @o";
' 1 0 2 3 0 4 5 0
Results:
1 0 2 3 0 4 5 0 -> 1 0 0 2 3 0 0 4
Example 2:
perl -E '
@i=@ARGV; while(@i){push @o, shift @i; pop @i, push @o,0 if @i && $o[-1]==0;} say "@ARGV -> @o";
' 1 2 3
Results:
1 2 3 -> 1 2 3
Example 3:
perl -E '
@i=@ARGV; while(@i){push @o, shift @i; pop @i, push @o,0 if @i && $o[-1]==0;} say "@ARGV -> @o";
' 0 3 0 4 5
Results:
0 3 0 4 5 -> 0 0 3 0 0
The full code is almost identical:
1 # Perl weekly challenge 235
2 # Task 2: Duplicate Zeros
3 #
4 # See https://wlmb.github.io/2023/09/18/PWC235/#task-2-duplicate-zeros
5 use v5.36;
6 die <<~"FIN" unless @ARGV;
7 Usage: $0 N1 [N2...]
8 to duplicate the zeroes in the array N1, N2...
9 without changing the size of the array
10 FIN
11 my @in=@ARGV;
12 my @out;
13 while(@in){
14 push @out, shift @in; # move from @in to @out
15 pop @in, # remove last element
16 push @out, 0 # and duplicate zero
17 if @in # if there is enough space
18 && $out[-1]==0; # and the last element was a 0
19 }
20 say "@ARGV -> @out";
Examples:
./ch-2.pl 1 0 2 3 0 4 5 0
./ch-2.pl 1 2 3
./ch-2.pl 0 3 0 4 5
./ch-2.pl 3 0
./ch-2.pl 0 3 0 4
Results:
1 0 2 3 0 4 5 0 -> 1 0 0 2 3 0 0 4
1 2 3 -> 1 2 3
0 3 0 4 5 -> 0 0 3 0 0
3 0 -> 3 0
0 3 0 4 -> 0 0 3 0
The last two examples show that trailing zeroes are not duplicated.