Robbie Hatley's Solutions To The Weekly Challenge #280
For those not familiar with "The Weekly Challenge", it is a weekly programming puzzle with two parts, cycling every Sunday. You can find it here:
The Weekly Challenge for the week of 2024-07-28 through 2024-08-03 is #280. Its tasks are as follows:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Task 280-1: Twice Appearance Submitted by: Mohammad Sajid Anwar Given a string containing lowercase English letters only, write a script to print the first letter to appear a second time. [Note, Robbie Hatley, 2024-07-29: The original version said "first letter that appears twice", but the examples contradict that, so I edited it to read "a second time" instead of "twice", in order to jibe with the examples. For example, in "acbddbca" the first letter to appear twice is "a", but the first letter to appear a second time is "d". The difference is that "twice" is not positional, but "second time" IS positional left-to-right (because that's the direction English is read in).] Example 1: Input: "acbddbca" Output: "d" (not a, because d "appears a second time" before a). Example 2: Input: "abccd" Output: "c" (c is only letter to appear a second time) Example 3: Input: "abcdabbb" Output: "a" (not b, because a "appears a second time" before b).
To solve this problem, I'll make a hash of letter abundances. The first letter to reach an abundance greater than 1 will be returned, else the Unicode replacement character if no letter appears a second time.
use v5.38; use utf8; sub second ($x) { my %hash; my $char; for my $idx (0..length($x)-1) { $char = substr($x,$idx,1); ++$hash{$char}; if (2 == $hash{$char}){ return $char; } } return "\x{FFFD}"; }
Robbie Hatley's Perl Solution to The Weekly Challenge 280-1
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Task 280-2: Count Asterisks Submitted by: Mohammad Sajid Anwar Given a string where every two consecutive vertical bars are grouped into a pair, write a script to return the number of asterisks, *, excluding any within each pair of vertical bars. [Note, Robbie Hatley, 2024-07-29: The original said "between each pair", but the examples make it clear that the intended meaning is the opposite, "within each pair". ("Between" would mean "NOT within any pair; outside of all pairs".)] Example 1: Input: "p|*e*rl|w**e|*ekly|" Ouput: 2 (Pair 1 contains "*e*rl" and Pair 2 contains "*ekly", so those are excluded, leaving "pw**e", which contains 2 asterisks.) Example 2: Input: $str = "perl" Ouput: 0 (There are no asterisks at all, so the count is zero.) Example 3: Input: $str = "th|ewe|e**|k|l***ych|alleng|e" Ouput: 5 (Pair 1 contains "ewe", Pair 2 contains "k", and Pair 3 contains "allenge", so those are excluded, leaving "the**l***yche", which contains 5 asterisks.
To solve this problem, I'll use a finite state machine with 2 states: "count on" and "count off", denoted by setting variable $state to 1 for on or 0 for off. $state starts in state "on" at the left end of the string, then as we move right, $state is toggled each time we reach a "|" character. Count asterisks, starting from zerio, only while $count is "on"; the final count is our answer.
use v5.38; use utf8; sub count ($x) { my $state = 1; my $count = 0; my $char = "\x{FFFD}"; for my $idx (0..length($x)-1) { $char = substr($x, $idx, 1); if ('|' eq $char) { $state = !$state; } elsif ('*' eq $char && $state) { ++$count; } else { ; # Do nothing. } } return $count; }
Robbie Hatley's Perl Solution to The Weekly Challenge 280-2
That's it for challenge 280; see you on challenge 281!
Comments
Post a Comment