THE WEEKLY CHALLENGE - 236
https://theweeklychallenge.org/blog/perl-weekly-challenge-236/
Table of Contents
Task 1 - Exact Change
Introduction
In this blog post, we will explore solutions to two interesting coding problems: "Exact Change" and "Unequal Triplets". We'll break down the problems, discuss algorithms, and present solutions in Perl, Python, and Raku.
Problem 1: Exact Change
Problem Statement
You are selling juice for $5 and have an array of bills from customers. You can only give change in $5, $10, and $20 notes, and you don't have any change initially. Determine if you can give exact change to every customer.
Algorithm
- Initialize counters for $5 and $10 bills as 0.
- Loop through the array of customer bills.
- If the bill is $5, increase the $5 counter.
- If the bill is $10, check if you have a $5 bill for change. If yes, reduce the $5 counter and increase the $10 counter.
- If the bill is $20, check for change options: either one $10 and one $5, or three $5s.
Perl Code Snippet
for my $bill (@bills) {
if ($bill == 5) {
$five++;
} elsif ($bill == 10) {
return 0 if $five == 0;
$five--;
} else {
# Handle $20 bill
}
}
Raku Code Snippet
for @bills -> $bill {
if $bill == 5 {
$five++;
} elsif $bill == 10 {
return False if $five == 0;
$five--;
} else {
# Handle $20 bill
}
}
Python Code Snippet
def can_sell_with_exact_change(bills: list) -> bool:
five, ten = 0, 0
for bill in bills:
if bill == 5:
five += 1
elif bill == 10:
if five == 0:
return False
five -= 1
ten += 1
else: # bill is 20
if ten > 0 and five > 0:
ten -= 1
five -= 1
elif five >= 3:
five -= 3
else:
return False
return True
Task 2 - Array Loops
Introduction
The "Array Loops" problem, submitted by Mark Anderson for the Perl Weekly Challenge, is an interesting one that tests our understanding of arrays and loops. The problem asks us to determine the number of loops that exist within a given array of unique integers. This may sound straightforward, but it involves a good deal of logic and algorithmic thinking.
Problem Statement
Given an array of unique integers, write a script to determine how many loops exist within the array. A loop starts at any index and follows the chain of integers until it returns back to the starting index.
For example, consider the array ([4, 6, 3, 8, 15, 0, 13, 18, 7, 16, 14, 19, 17, 5, 11, 1, 12, 2, 9, 10]). The loops in this array are:
- (4 -> 15-> 1 -> 6 -> 13 -> 5 -> 0 -> 4)
- (3 -> 8 -> 7 -> 18 -> 9 -> 16 -> 12 -> 17 -> 2 -> 3)
- (14 -> 11 -> 19 -> 10 -> 14)
The output for this array should be (3).
Algorithm Explanation
To solve this problem, we can use the following algorithm:
- Initialize a set or hash to keep track of visited indices.
- Initialize a counter to keep track of the number of loops.
- For each unvisited index in the array:
- Mark the index as visited.
- Follow the chain of integers, marking each subsequent index as visited, until you reach an index that has already been visited.
- Increment the loop counter.
- Return the loop counter.
Let's implement this algorithm in Perl, Python, and Raku.
Perl Solution
Here's how we could implement the algorithm in Perl:
use strict;
use warnings;
sub find_loops {
my @arr = @_;
my %visited;
my $loops = 0;
for my $i (0..$#arr) {
next if $visited{$i};
my $j = $i;
while (!exists $visited{$j}) {
$visited{$j} = 1;
$j = $arr[$j];
}
$loops++;
}
return $loops;
}
print find_loops(4,6,3,8,15,0,13,18,7,16,14,19,17,5,11,1,12,2,9,10); # Output: 3
Python Solution
The Python solution uses a set data structure to keep track of visited indices:
def find_loops(arr: list) -> int:
visited = set()
loops = 0
for i in range(len(arr)):
if i in visited:
continue
j = i
while j not in visited:
visited.add(j)
j = arr[j]
loops += 1
return loops
print(find_loops([4,6,3,8,15,0,13,18,7,16,14,19,17,5,11,1,12,2,9,10])) # Output: 3
Raku Solution
In Raku, the algorithm stays largely the same:
sub find-loops(@arr) {
my %visited;
my $loops = 0;
for 0..^@arr.elems -> $i {
next if %visited{$i}:exists;
my $j = $i;
while !%visited{$j}:exists {
%visited{$j} = 1;
$j = @arr[$j];
}
$loops++;
}
return $loops;
}
say find-loops(4,6,3,8,15,0,13,18,7,16,14,19,17,5,11,1,12,2,9,10); # Output: 3
Conclusion
The "Array Loops" problem is a good exercise in understanding how to traverse arrays while keeping track of visited elements. The algorithm is straightforward but requires careful implementation to ensure that all loops are counted correctly. With solutions available in Perl, Python, and Raku, we can appreciate the nuances of each language while solving the same algorithmic challenge.