Task 1: Minimum Time
You are given a typewriter with lowercase english letters a to z arranged in a circle.
Typing a character takes 1 sec. You can move the pointer one character clockwise or anti-clockwise.
The pointer initially points at a.
Write a script to return the minimum time it takes to print the given string.
Example 1
Input: $str = "abc"
Output: 5
The pointer is at 'a' initially.
1 sec - type the letter 'a'
1 sec - move pointer clockwise to 'b'
1 sec - type the letter 'b'
1 sec - move pointer clockwise to 'c'
1 sec - type the letter 'c'
Example 2
Input: $str = "bza"
Output: 7
The pointer is at 'a' initially.
1 sec - move pointer clockwise to 'b'
1 sec - type the letter 'b'
1 sec - move pointer anti-clockwise to 'a'
1 sec - move pointer anti-clockwise to 'z'
1 sec - type the letter 'z'
1 sec - move pointer clockwise to 'a'
1 sec - type the letter 'a'
Example 3
Input: $str = "zjpc"
Output: 34
Logic
To find the minimum time to type the string on a circular typewriter:
- Start at position 0 (letter 'a').
- For each character, calculate the clockwise and anti-clockwise distances from the current position.
- Take the minimum of the two distances (since the letters are arranged in a circle, going the other way around might be shorter).
- Add the move time plus 1 second for typing the character.
- Update the current position and continue to the next character.
The key insight is that on a circle of 26 letters, the distance between two positions is min(|a-b|, 26 - |a-b|).
Perl Solution
ch-1.pl
#!/usr/bin/env perl
use v5.38;
use warnings;
use feature 'signatures';
no warnings 'experimental::signatures';
## no critic (Subroutines::ProhibitSubroutinePrototypes)
use Type::Params qw(compile);
use Types::Standard qw(Str);
sub _pos ($ch) { return ord($ch) - ord('a') }
sub minimum_time ($str) {
($str) = compile(Str)->($str);
my $time = 0;
my $pos = 0; # 'a'
for my $ch ( split //, $str ) {
my $target = _pos($ch);
my $diff = abs( $target - $pos );
my $move = $diff < ( 26 - $diff ) ? $diff : ( 26 - $diff );
$time += $move + 1; # move + type
$pos = $target;
}
return $time;
}
Python Solution
ch-1.py
#!/usr/bin/env python3
"""Minimum Time - Perl Weekly Challenge 312 task 1."""
from __future__ import annotations
from collections.abc import Sequence
import sys
import unittest
def minimum_time(text: str) -> int:
"""
Return minimum time to type text on a circular typewriter (a-z).
Start at 'a'. Each move step costs 1 second; typing each character costs 1 second.
"""
pos = 0
total = 0
for ch in text:
target = ord(ch) - ord("a")
diff = abs(target - pos)
total += min(diff, 26 - diff) + 1
pos = target
return total
class MinimumTimeExamples(unittest.TestCase):
"""Example-based tests from the specification."""
def test_example_1(self) -> None:
self.assertEqual(minimum_time("abc"), 5)
def test_example_2(self) -> None:
self.assertEqual(minimum_time("bza"), 7)
def test_example_3(self) -> None:
self.assertEqual(minimum_time("zjpc"), 34)
Task 2: Balls and Boxes
There are n balls of mixed colors: red, blue or green. They are all distributed in 10 boxes labelled 0-9.
You are given a string describing the location of balls.
Write a script to find the number of boxes containing all three colors. Return 0 if none found.
Example 1
Input: $str = "G0B1R2R0B0"
Output: 1
The given string describes there are 5 balls as below:
Box 0: Green(G0), Red(R0), Blue(B0) => 3 balls
Box 1: Blue(B1) => 1 ball
Box 2: Red(R2) => 1 ball
Example 2
Input: $str = "G1R3R6B3G6B1B6R1G3"
Output: 3
The given string describes there are 9 balls as below:
Box 1: Red(R1), Blue(B1), Green(G1) => 3 balls
Box 3: Red(R3), Blue(B3), Green(G3) => 3 balls
Box 6: Red(R6), Blue(B6), Green(G6) => 3 balls
Example 3
Input: $str = "B3B2G1B3"
Output: 0
Box 1: Green(G1) => 1 ball
Box 2: Blue(B2) => 1 ball
Box 3: Blue(B3) => 2 balls
Logic
To find the number of boxes containing all three colors:
- Parse the input string as pairs of (color, box_digit).
- For each pair, add the color to the corresponding box's set of colors.
- After processing all pairs, count how many boxes have all three colors (R, G, B) in their set.
- Return the count (0 if none).
The input string has even length, with each pair consisting of a color letter (R/G/B) followed by a box digit (0-9).
Perl Solution
ch-2.pl
#!/usr/bin/env perl
use v5.38;
use warnings;
use feature 'signatures';
no warnings 'experimental::signatures';
## no critic (Subroutines::ProhibitSubroutinePrototypes)
use Type::Params qw(compile);
use Types::Standard qw(Str);
sub balls_and_boxes ($str) {
($str) = compile(Str)->($str);
die 'Expected an even-length string of (Color,Box) pairs' if length($str) % 2 != 0;
my @boxes;
for my $i ( 0 .. 9 ) {
$boxes[$i] = {};
}
my @chars = split //, $str;
for ( my $i = 0; $i < @chars; $i += 2 ) {
my $color = $chars[$i];
my $box = $chars[ $i + 1 ];
die 'Invalid color' if $color !~ /\A[RGB]\z/;
die 'Invalid box' if $box !~ /\A[0-9]\z/;
$boxes[$box]{$color} = 1;
}
my $count = 0;
for my $box ( 0 .. 9 ) {
++$count if $boxes[$box]{R} && $boxes[$box]{G} && $boxes[$box]{B};
}
return $count;
}
Python Solution
ch-2.py
#!/usr/bin/env python3
"""Balls and Boxes - Perl Weekly Challenge 312 task 2."""
from __future__ import annotations
from collections.abc import Sequence
import sys
import unittest
def balls_and_boxes(text: str) -> int:
"""Return number of boxes containing all three colors (R/G/B)."""
if len(text) % 2 != 0:
raise ValueError("Expected an even-length string of (Color,Box) pairs")
boxes: list[set[str]] = [set() for _ in range(10)]
for idx in range(0, len(text), 2):
color = text[idx]
box = text[idx + 1]
if color not in {"R", "G", "B"}:
raise ValueError("Invalid color")
if box not in "0123456789":
raise ValueError("Invalid box")
boxes[int(box)].add(color)
return sum(1 for colors in boxes if {"R", "G", "B"}.issubset(colors))
class BallsAndBoxesExamples(unittest.TestCase):
"""Example-based tests from the specification."""
def test_example_1(self) -> None:
self.assertEqual(balls_and_boxes("G0B1R2R0B0"), 1)
def test_example_2(self) -> None:
self.assertEqual(balls_and_boxes("G1R3R6B3G6B1B6R1G3"), 3)
def test_example_3(self) -> None:
self.assertEqual(balls_and_boxes("B3B2G1B3"), 0)