Perl Weekly Challenge 282.
My solutions (task 1 and task 2 ) to the The Weekly Challenge - 282.
Task 1: Good Integer
Submitted by: Mohammad Sajid Anwar
You are given a positive integer, $int, having 3 or more digits.
Write a script to return the Good Integer in the given integer or -1 if none found.
A good integer is exactly three consecutive matching digits.
Example 1
Input: $int = 12344456
Output: "444"
Example 2
Input: $int = 1233334
Output: -1
Example 3
Input: $int = 10020003
Output: "000"
I can capture with a regular expression a single character, then two
copies of the same character and finally then an arbitrary number of
repetitions of the same character. If the last group is empty, I have
found a good integer. If not, I can substitute the whole expression
and the preceding substring by
an empty string and start again, until there are no more groups of
three consecutive characters, in which case the answer is -1. I use
two loops, one for the input and one for the match attempts. I use the
LABEL.... next LABEL
construction to gracefully jump out of the
inner loop. The code fits a oneliner
Examples:
perl -E '
A:for(@ARGV){my $x=$_;while(s/.*?((.)\2\2(\2*))//){say("$x -> $1"), next A if $3 eq ""} say "$x -> -1"}
' 12344456 1233334 10020003
Results:
12344456 -> 444
1233334 -> -1
10020003 -> 000
The full code is similar:
1 # Perl weekly challenge 282
2 # Task 1: Good Integer
3 #
4 # See https://wlmb.github.io/2024/08/11/PWC282/#task-1-good-integer
5 use v5.36;
6 die <<~"FIN" unless @ARGV;
7 Usage: $0 N1 N2...
8 to find good integers within the numbers N1 N2...
9 FIN
10 ARG: for(@ARGV){
11 my $arg=$_;
12 warn "Expected only digits: $_" unless /^\d+$/;
13 while(s/.*?((.)\2\2(\2*))//){
14 say("$arg -> $1"), next ARG if $3 eq "";
15 }
16 say "$arg -> -1"
17 }
Examples:
./ch-1.pl 12344456 1233334 10020003
Results:
12344456 -> 444
1233334 -> -1
10020003 -> 000
Task 2: Changing Keys
Submitted by: Mohammad Sajid Anwar
You are given an alphabetic string, $str, as typed by user.
Write a script to find the number of times user had to change the key to type the
given string. Changing key is defined as using a key different from the last used
key. The shift and caps lock keys won’t be counted.
Example 1
Input: $str = 'pPeERrLl'
Ouput: 3
p -> P : 0 key change
P -> e : 1 key change
e -> E : 0 key change
E -> R : 1 key change
R -> r : 0 key change
r -> L : 1 key change
L -> l : 0 key change
Example 2
Input: $str = 'rRr'
Ouput: 0
Example 3
Input: $str = 'GoO'
Ouput: 1
I can convert the string to lowercase and interpret same key as same character. I can remove repeated characters using regular expressions and then count how many distinct characters remain and subtract 1 to get the number of changes, one between each pair of consecutive characters. The result fits a half-liner.
Examples:
perl -E '
for(@ARGV){$x=$_; $_=lc; s/(.)\1+/$1/g; say "$x -> ", length($_)-1}
' pPeERrLl rRr GoO
Results:
pPeERrLl -> 3
rRr -> 0
GoO -> 1
The full code is similar.
1 # Perl weekly challenge 282
2 # Task 2: Changing Keys
3 #
4 # See https://wlmb.github.io/2024/08/11/PWC282/#task-2-changing-keys
5 use v5.36;
6 die <<~"FIN" unless @ARGV;
7 Usage: $0 S1 S2...
8 to count how many key changes are required for each character in strings S1 S2...
9 FIN
10 for(@ARGV){
11 warn("Expected alphabetical string: $_"), next unless /^[a-zA-Z]+$/;
12 my $arg=$_;
13 $_=lc;
14 s/(.)\1+/$1/g;
15 say "$arg -> ", length($_)-1
16 }
Example:
./ch-2.pl pPeERrLl rRr GoO
Results:
pPeERrLl -> 3
rRr -> 0
GoO -> 1
/;