DEV Community

Simon Green
Simon Green

Posted on

The Weekly Challenge: Alike Time

Weekly Challenge 348

Each week Mohammad S. Anwar sends out The Weekly Challenge, a chance for all of us to come up with solutions to two weekly tasks. My solutions are written in Python first, and then converted to Perl. It's a great way for us all to practice some coding.

Challenge, My solutions

Task 1: String Alike

Tasks

You are given a string of even length.

Write a script to find if the given string split into two halves of equal lengths and they both have same number of vowels.

My solution

The main logic for this challenge is a function called count_vowels. The takes a string and returns the number of vowels. The Python code for this function is

def count_vowels(s: str) -> int:
    vowels = 'aeiouAEIOU'
    return sum(1 for char in s if char in vowels)
Enter fullscreen mode Exit fullscreen mode

Not to be outdone, it's a single line in Perl.

sub count_vowels ($s) {
    return $s =~ tr/aeiouAEIOU/aeiouAEIOU/;
}
Enter fullscreen mode Exit fullscreen mode

With that out of the way, the main function

  1. Throws an error if there there there is not an even number of characters in the input_string.
  2. Return False if there is are no vowels in the input_string.
  3. Set the variables first_half and second_half.
  4. Compare the number of vowels in each half.
  5. Return True if the two string have the same number of vowels, else False.
def string_alike(input_string: str) -> bool:
    if len(input_string) % 2 == 1:
        raise ValueError("Input string must have an even length.")

    if count_vowels(input_string) == 0:
        return False

    first_half = input_string[:len(input_string)//2]
    second_half = input_string[len(input_string)//2:]
    return count_vowels(first_half) == count_vowels(second_half)
Enter fullscreen mode Exit fullscreen mode

The Perl solution follows the same logic.

sub string_alike ($input_string) {
    die "Input string must have an even length."
      if length($input_string) % 2 == 1;

    if ( count_vowels($input_string) == 0 ) {
        say "False";
        return;
    }

    my $mid         = length($input_string) / 2;
    my $first_half  = substr( $input_string, 0, $mid );
    my $second_half = substr( $input_string, $mid );
    say count_vowels($first_half) == count_vowels($second_half)
      ? "True"
      : "False";
}
Enter fullscreen mode Exit fullscreen mode

Examples

$ ./ch-1.py textbook
False

$ ./ch-1.py book
True

$ ./ch-1.py AbCdEfGh
True

$ ./ch-1.py rhythmmyth
False

$ ./ch-1.py UmpireeAudio
False
Enter fullscreen mode Exit fullscreen mode

Task 2: Covert Time

Task

You are given two strings, $source and $target, containing time in 24-hour time form.

Write a script to convert the source into target by performing one of the following operations:

  1. Add 1 minute
  2. Add 5 minutes
  3. Add 15 minutes
  4. Add 60 minutes

Find the total operations needed to get to the target.

My solution

For this task I have created a function called time_to_minutes that takes the time in HH:MM format, and returns the minutes since midnight. It also checks that the time is in a valid format, and the hours (0-23) and minutes (0-59) minutes are in range.

def time_to_minute(s: str) -> int:
    if not re.match(r'^\d{1,2}:\d{2}$', s):
        raise ValueError("Invalid time format, should be HH:MM")

    hour, minute = map(int, s.split(':'))

    if hour < 0 or hour > 23 or minute < 0 or minute > 59:
        raise ValueError("Invalid time format")

    return hour * 60 + minute
Enter fullscreen mode Exit fullscreen mode

In the main function, I set a variable duration that is the minutes difference between the source and target. If this value is negative, the time crosses midnight, so I add 1440 (60 × 24) minutes to compute the correct duration.

def convert_time(source: str, target: str) -> int:
    duration = time_to_minute(target) - time_to_minute(source)
    if duration < 0:
        duration += 24 * 60
Enter fullscreen mode Exit fullscreen mode

I set the moves list (array in Perl) to the possible moves, with the largest first. For each move, I make as many moves as possible, adding the number of moves to the count variable, and reducing duration to what remains.

    moves = [60, 15, 5, 1]
    count = 0

    for move in moves:
        count += duration // move

        duration %= move

    return count
Enter fullscreen mode Exit fullscreen mode

The Perl solution follows the same logic.

Examples

$ ./ch-2.py 02:30 02:45
1

$ ./ch-2.py 11:55 12:15
2

$ ./ch-2.py 09:00 13:00
4

$ ./ch-2.py 23:45 00:30
3

$ ./ch-2.py 14:20 15:25
2
Enter fullscreen mode Exit fullscreen mode

Top comments (0)