Time to see what is in the boxes
Weekly Challenge 312 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: Minimum Time Task 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 pointer one character clockwise or anti-clockwise. The pointer initially points at a. Write a script to return minimum time it takes to print the given string. My solution I might need to explain to the younger readers what a type writer is. I think the last time I saw one was in the early nineties, while I was at high school. For this I create a variable called seconds which starts with the length of the string. This is the number of seconds it takes to type each character. I then create a list (array in Perl) of the position on the dial of each letter (a is 0, z is 25) in the positions value. I prepend 0 to the list to represent that we start with the letter a. Finally I have an iterator that goes from 1 to the length of positions. For each iteration, I calculate the absolute difference between the letter at this position and the letter at the previous position. If this difference is greater than 13, it is quicker to go in the other direction, so take the difference from 26. I add this value to the seconds variable. def minimum_time(s: str) -> int: if not re.search('^[a-z]+$', s): raise ValueError('Invalid input') seconds = len(s) positions = [string.ascii_lowercase.index(c) for c in s] positions.insert(0, 0) for i in range(1, len(positions)): diff = abs(positions[i-1] - positions[i]) if diff > 13: diff = 26 - diff seconds += diff return seconds The Perl solution follows the same principles but does things slightly different. sub main ($str) { if ( $str !~ /^[a-z]+$/ ) { die "Invalid input\n"; } my $seconds = length($str); my @positions = map { ord($_) - ord('a') } split //, $str; unshift( @positions, 0 ); foreach my $i ( 1 .. $#positions ) { my $diff = abs( $positions[ $i - 1 ] - $positions[$i] ); if ( $diff > 13 ) { $diff = 26 - $diff; } $seconds += $diff; } say $seconds; } Examples $ ./ch-1.py abc 5 $ ./ch-1.py bza 7 $ ./ch-1.py zjpc 34 Task 2: Balls and Boxes Task 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. My solution I'm totally stumped about the reference to $n in the task. It doesn't seem to be used elsewhere in the task or the examples. I have chosen to ignore it. The first thing I so is ensure the string matches the regular expression ^(?:[RGB][0-9])+$. This means it is one more occurrences of the letter R, G, B followed by a single digit. def ball_and_boxes(s: str) -> int: if not re.search('^(?:[RGB][0-9])+$', s): raise ValueError('Invalid input') I have a variable boxes to represent what color the balls are in each box. The boxes value is a dict (hash in Perl) with the key the box number and the values a set (hash in Perl) of the color of the balls in that box. I then iterate over each letter number pair with the variables color and box. Each iteration will put the color of the ball in the appropriate box. boxes = {} for color, box in re.findall('([RGB])([0-9])', s): if box not in boxes: boxes[box] = set() boxes[box].add(color) Finally I return the number of boxes that have three balls in it. As we use a set for the boxes value, it isn't possible to put three balls of the same color to trigger the success. This is shown in the last example below. return sum(1 for b in boxes.values() if len(b) == 3) Examples $ ./ch-2.py G0B1R2R0B0 1 $ ./ch-2.py G1R3R6B3G6B1B6R1G3 3 $ ./ch-2.py B3B2G1B3 0 $ ./ch-2.py B3G3B3 0

Weekly Challenge 312
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.
Task 1: Minimum Time
Task
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 pointer one character clockwise or anti-clockwise.
The pointer initially points at a
.
Write a script to return minimum time it takes to print the given string.
My solution
I might need to explain to the younger readers what a type writer is. I think the last time I saw one was in the early nineties, while I was at high school.
For this I create a variable called seconds
which starts with the length of the string. This is the number of seconds it takes to type each character.
I then create a list (array in Perl) of the position on the dial of each letter (a
is 0, z
is 25) in the positions
value. I prepend 0
to the list to represent that we start with the letter a
.
Finally I have an iterator that goes from 1 to the length of positions
. For each iteration, I calculate the absolute difference between the letter at this position and the letter at the previous position. If this difference is greater than 13, it is quicker to go in the other direction, so take the difference from 26. I add this value to the seconds
variable.
def minimum_time(s: str) -> int:
if not re.search('^[a-z]+$', s):
raise ValueError('Invalid input')
seconds = len(s)
positions = [string.ascii_lowercase.index(c) for c in s]
positions.insert(0, 0)
for i in range(1, len(positions)):
diff = abs(positions[i-1] - positions[i])
if diff > 13:
diff = 26 - diff
seconds += diff
return seconds
The Perl solution follows the same principles but does things slightly different.
sub main ($str) {
if ( $str !~ /^[a-z]+$/ ) {
die "Invalid input\n";
}
my $seconds = length($str);
my @positions = map { ord($_) - ord('a') } split //, $str;
unshift( @positions, 0 );
foreach my $i ( 1 .. $#positions ) {
my $diff = abs( $positions[ $i - 1 ] - $positions[$i] );
if ( $diff > 13 ) {
$diff = 26 - $diff;
}
$seconds += $diff;
}
say $seconds;
}
Examples
$ ./ch-1.py abc
5
$ ./ch-1.py bza
7
$ ./ch-1.py zjpc
34
Task 2: Balls and Boxes
Task
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.
My solution
I'm totally stumped about the reference to $n
in the task. It doesn't seem to be used elsewhere in the task or the examples. I have chosen to ignore it.
The first thing I so is ensure the string matches the regular expression ^(?:[RGB][0-9])+$
. This means it is one more occurrences of the letter R
, G
, B
followed by a single digit.
def ball_and_boxes(s: str) -> int:
if not re.search('^(?:[RGB][0-9])+$', s):
raise ValueError('Invalid input')
I have a variable boxes
to represent what color the balls are in each box. The boxes
value is a dict (hash in Perl) with the key the box number and the values a set (hash in Perl) of the color of the balls in that box.
I then iterate over each letter number pair with the variables color
and box
. Each iteration will put the color of the ball in the appropriate box.
boxes = {}
for color, box in re.findall('([RGB])([0-9])', s):
if box not in boxes:
boxes[box] = set()
boxes[box].add(color)
Finally I return the number of boxes that have three balls in it. As we use a set for the boxes
value, it isn't possible to put three balls of the same color to trigger the success. This is shown in the last example below.
return sum(1 for b in boxes.values() if len(b) == 3)
Examples
$ ./ch-2.py G0B1R2R0B0
1
$ ./ch-2.py G1R3R6B3G6B1B6R1G3
3
$ ./ch-2.py B3B2G1B3
0
$ ./ch-2.py B3G3B3
0