Round Here: Weekly Challenge #273
Welcome to Weekly Challenge #273! I would dive into what kind of number 273 is, but I just don’t have it in me right now.
Task 1: Percentage of Character
Submitted by: Mohammad Sajid Anwar
You are given a string,$strand a character$char.Write a script to return the percentage, nearest whole, of given character in the given string.
Let’s Talk About It
This moves toward a question I hadn’t thought to engage before, which goes to rounding. I hadn’t ever even thought to round before. Cut off at so many significant digits, sure, or cast as int, but not rounded to nearest whole number.
Because I always found it to be a useful tool, I went with sprintf, specifically with zero significant digits, or sprintf '%.0f', $number, and I found unexpected behavior.
for my $f (map { $_ + 0.5 } 0 ..5 ) {
my $w = sprintf '%.0f', $f;
my $o = $w < $f ? 'down' : 'up';
say qq{ $f round $o to $w };
}
0.5 round down to 0
1.5 round up to 2
2.5 round down to 2
3.5 round up to 4
4.5 round down to 4
5.5 round up to 6
The defined, IEEE-approved behavior, is to round to the nearest even number at 0.5, and the example problem that hits this point rounds the wrong way.
Back in elementary school, the rounding rule was 2.5 rounds to 3, not 2. I wrote a round function that behaves as I had learned it. I know that Math::Round exists, but I decided against it.
Show Me The Code!
#!/usr/bin/env perl
use strict;
use warnings;
use experimental qw{ bitwise fc postderef say signatures state };
use List::Util qw{max};
my @examples = (
{ str => "perl", char => "e" },
{ str => "java", char => "a" },
{ str => "python", char => "m" },
{ str => "ada", char => "a" },
{ str => "ballerina", char => "l" },
{ str => "analitik", char => "k" },
);
for my $example (@examples) {
my $char = $example->{char};
my $str = $example->{str};
my @str = split //, $str;
my $count = scalar grep { $_ eq $char } @str;
my $total = scalar @str;
my $output = round( 100 * $count / $total );
say <<"END";
Input: \$str = "$str", \$char = "$char"
Output: "$output"
END
}
sub round ($number) {
my $int = int $number;
return $number if $number == $int;
my $r = $number - $int;
return $r < 0.5 ? $int : $int + 1;
}
$ ./ch-1.pl
^[[AInput: $str = "perl", $char = "e"
Output: "25"
Input: $str = "java", $char = "a"
Output: "50"
Input: $str = "python", $char = "m"
Output: "0"
Input: $str = "ada", $char = "a"
Output: "67"
Input: $str = "ballerina", $char = "l"
Output: "22"
Input: $str = "analitik", $char = "k"
Output: "13"
Task 2: B After A
Submitted by: Mohammad Sajid Anwar
You are given a string,$str.Write a script to return
trueif there is at least oneb, and noaappears after the firstb.
Let’s Talk About It
I think this is all fairly clear pattern matching and substr.
Show Me The Code!
#!/usr/bin/env perl
use strict;
use warnings;
use experimental qw{ fc say postderef signatures state };
use List::Util qw{ sum0 };
my @examples = (
"aabb",
"abab",
"aaa",
"bbb",
);
for my $example (@examples) {
my $output = baftera($example);
say <<"END";
Input: \$str = "$example"
Output: $output
END
}
sub baftera ($str) {
return 'false' unless $str =~ /b/mix;
my $has_b = 0;
for my $i ( 0 .. length $str ) {
my $char = substr $str, $i, 1;
$has_b = 1 if $char eq 'b';
return 'false' if $has_b && $char eq 'a';
}
return 'true';
}
$ ./ch-2.pl
Input: $str = "aabb"
Output: true
Input: $str = "abab"
Output: false
Input: $str = "aaa"
Output: false
Input: $str = "bbb"
Output: true