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

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

Popular posts from this blog

Robbie Hatley's Solutions To The Weekly Challenge #262

Robbie Hatley's Solutions To The Weekly Challenge #239

Robbie Hatley's Solutions To The Weekly Challenge #266