# Perl Weekly Challenge 273.

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

# Task 1: Percentage of Character

You are given a string, \$str and a character \$char.

Write a script to return the percentage, nearest whole,
of given character in the given string.

Example 1
Input: \$str = "perl", \$char = "e"
Output: 25
Example 2
Input: \$str = "java", \$char = "a"
Output: 50
Example 3
Input: \$str = "python", \$char = "m"
Output: 0
Example 4
Input: \$str = "ada", \$char = "a"
Output: 67
Example 5
Input: \$str = "ballerina", \$char = "l"
Output: 22
Example 6
Input: \$str = "analitik", \$char = "k"
Output: 13

The problem seems straightforward. I can split the string, choose the characters that match count them, calculate the percentage and round it. The code can be compacted using the tr operator, which counts matches. As it doesn’t interpolate, it must be evaled. The results fit a oneliner:

Example 1:

perl -E '
(\$w,\$c)=@ARGV; \$l=length \$w; say "str=\$w, char=\$c -> ", int(.5+100*(eval"\\$w=~tr/\$c//")/\$l);
' perl e

Results:

str=perl, char=e -> 25

Example 2:

perl -E '
(\$w,\$c)=@ARGV; \$l=length \$w; say "str=\$w, char=\$c -> ", int(.5+100*(eval"\\$w=~tr/\$c//")/\$l);
' java a

Results:

str=java, char=a -> 50

Example 3:

perl -E '
(\$w,\$c)=@ARGV; \$l=length \$w; say "str=\$w, char=\$c -> ", int(.5+100*(eval"\\$w=~tr/\$c//")/\$l);
' python a

Results:

str=python, char=a -> 0

Example 4:

perl -E '
(\$w,\$c)=@ARGV; \$l=length \$w; say "str=\$w, char=\$c -> ", int(.5+100*(eval"\\$w=~tr/\$c//")/\$l);

Results:

Example 5:

perl -E '
(\$w,\$c)=@ARGV; \$l=length \$w; say "str=\$w, char=\$c -> ", int(.5+100*(eval"\\$w=~tr/\$c//")/\$l);
' ballerina l

Results:

str=ballerina, char=l -> 22

Example 6:

perl -E '
(\$w,\$c)=@ARGV; \$l=length \$w; say "str=\$w, char=\$c -> ", int(.5+100*(eval"\\$w=~tr/\$c//")/\$l);
' analitik k

Results:

str=analitik, char=k -> 13

Notice that the nearest integer to 12.5 is ambiguous, as it is equidistant from 12 and 13. The code above rounds up in this case.

For the full code, I simply split the string, grep the matches and count them, to avoid evali-ing the tr operator. I convert to lowercase to disregard case.

1  # Perl weekly challenge 273
2  # Task 1:  Percentage of Character
3  #
5  use v5.36;
6  use experimental "for_list";
7  die <<~"FIN" unless @ARGV && @ARGV%2==0;
8      Usage: \$0 S1 C1 S2 W2...
9      to find the percentage of character Ci in string Si.
10      FIN
11  for my (\$str, \$chr)(@ARGV){
12      my \$length=length \$str;
13      my \$matches=0+grep{ lc(\$_) eq lc(\$chr)} split "", \$str;
14      my \$percentage = int(.5+100*\$matches/\$length);
15      say "str=\$str, chr=\$chr -> \$percentage";
16  }

Example:

./ch-1.pl perl e java a python a ada a ballerina l analitik k

Results:

str=perl, chr=e -> 25
str=java, chr=a -> 50
str=python, chr=a -> 0
str=ballerina, chr=l -> 22
str=analitik, chr=k -> 13

# Task 2: B After A

You are given a string, \$str.

Write a script to return true if there is at least one b,
and no a appears after the first b.

Example 1
Input: \$str = "aabb"
Output: true
Example 2
Input: \$str = "abab"
Output: false
Example 3
Input: \$str = "aaa"
Output: false
Example 4
Input: \$str = "bbb"
Output: true

“A b, first followed by no a” can be captured by a simple regular expression, yielding a half liner.

Examples:

perl -E 'for(@ARGV){say "\$_ -> ", /^[^b]*b[^a]*\$/i?"true":"false"}' aabb abab aaa bbb

Results:

aabb -> true
abab -> false
aaa -> false
bbb -> true

The full code is similar:

1  # Perl weekly challenge 273
2  # Task 2:  B After A
3  #
5  use v5.36;
6  die <<~"FIN" unless @ARGV;
7      Usage: \$0 S1 S2...
8      to test the strings S1 S2... for B after A
9      FIN
10  for(@ARGV){
11      say "\$_ -> ", /^[^b]*b[^a]*\$/i?"true":"false"
12  }

Example:

./ch-2.pl aabb abab aaa bbb

Results:

aabb -> true
abab -> false
aaa -> false
bbb -> true

/;

Written on June 10, 2024