THE WEEKLY CHALLENGE - 241
https://theweeklychallenge.org/blog/perl-weekly-challenge-241/
Table of Contents
Task 1 - Arithmetic Triplets
Problem Statement
You are given an array of integers sorted in ascending order and a positive integer called diff
. Your task is to find the number of unique arithmetic triplets in the array that satisfy the following conditions:
- ( i < j < k )
- nums[j] - nums[i] = diff
- nums[k] - nums[j] = diff
Algorithm
To solve this problem efficiently, we can use a Set data structure to store all the numbers in the array. Then, we can iterate through the array and check whether each number ( x ) forms an arithmetic triplet ( (x - diff, x, x + diff) ) using the Set.
The algorithm can be broken down into the following steps:
- Create an empty Set and populate it with all numbers in the array.
- Initialize a counter variable to 0.
- Loop through the array:
- For each number ( x ), check if ( (x - diff) ) and ( (x + diff) ) exist in the Set.
- If they do, increment the counter by 1.
Complexity Analysis
The algorithm has a time complexity of ( O(n) ), where ( n ) is the size of the array. This is because we only loop through the array once, and all Set operations take ( O(1) ) time.
Python Implementation
def count_arithmetic_triplets(nums, diff):
count = 0
nums_set = set(nums)
for num in nums:
if (num + diff) in nums_set and (num - diff) in nums_set:
count += 1
return count
# Test Cases
print(count_arithmetic_triplets([0, 1, 4, 6, 7, 10], 3)) # Output: 2
print(count_arithmetic_triplets([4, 5, 6, 7, 8, 9], 2)) # Output: 2
Perl Implementation
sub count_arithmetic_triplets {
my ($nums, $diff) = @_;
my $count = 0;
my %nums_set = map { $_ => 1 } @$nums;
for my $num (@$nums) {
if (exists $nums_set{$num + $diff} && exists $nums_set{$num - $diff}) {
$count++;
}
}
return $count;
}
# Test Cases
print count_arithmetic_triplets([0, 1, 4, 6, 7, 10], 3); # Output: 2
print count_arithmetic_triplets([4, 5, 6, 7, 8, 9], 2); # Output: 2
Raku Implementation
sub count-arithmetic-triplets(@nums, $diff) {
my $count = 0;
my %nums-set = @nums.Set;
for @nums -> $num {
if %nums-set{$num + $diff}:exists {
if %nums-set{$num - $diff}:exists {
$count++;
}
}
}
return $count;
}
# Test Cases
say count-arithmetic-triplets([0, 1, 4, 6, 7, 10], 3); # Should print 2
say count-arithmetic-triplets([4, 5, 6, 7, 8, 9], 2); # Should print 2
That's it! This is how we can efficiently find the number of unique arithmetic triplets in an array.
Task 2 - Prime Order
The Problem
You are given an array of unique positive integers greater than 2. Write a script to sort them in ascending order of the count of their prime factors, tie-breaking by ascending value.
Example:
Input: [11, 8, 27, 4]
Output: [11, 4, 8, 27]
Analysis
The problem can be divided into two main steps:
- Finding the prime factors for each number in the array
- Sorting the array based on the count of the prime factors and the value itself
Algorithm
- Create a function to find the prime factors of a given number.
- Sort the array of numbers, using the count of prime factors as the primary key and the number itself as the secondary key.
Python Implementation
Python allows us to use the sorted
function with a custom key. We'll use this to sort the array according to our needs.
from math import isqrt
def prime_factors(n):
factors = []
while n % 2 == 0:
factors.append(2)
n //= 2
for i in range(3, isqrt(n) + 1, 2):
while n % i == 0:
factors.append(i)
n //= i
if n > 2:
factors.append(n)
return factors
def sort_by_prime_factors(nums):
return sorted(nums, key=lambda x: (len(prime_factors(x)), x))
# Test case
print(sort_by_prime_factors([11, 8, 27, 4]))
Perl Implementation
In Perl, the sort
function can be customized by defining a custom comparison subroutine. Here's how:
use strict;
use warnings;
sub prime_factors {
my $n = shift;
my @factors;
while ($n % 2 == 0) {
push @factors, 2;
$n /= 2;
}
for my $i (3 .. sqrt($n)) {
while ($n % $i == 0) {
push @factors, $i;
$n /= $i;
}
}
push @factors, $n if $n > 2;
return @factors;
}
sub sort_by_prime_factors {
my @nums = @_;
return sort { scalar(prime_factors($a)) <=> scalar(prime_factors($b)) || $a <=> $b } @nums;
}
# Test case
print join(", ", sort_by_prime_factors(11, 8, 27, 4));
Raku Implementation
Raku provides a .sort
method that can accept a block of code to determine the sorting key. This makes it very convenient to implement our custom sorting logic.
sub prime-factors(Int $n is copy) {
my @factors;
while $n %% 2 {
@factors.push: 2;
$n div= 2;
}
for 3, 5 ... * -> $i {
last if $i > sqrt($n);
while $n %% $i {
@factors.push: $i;
$n div= $i;
}
}
@factors.push: $n if $n > 2;
return @factors;
}
sub sort-by-prime-factors(@nums) {
my @sorted-nums = @nums.sort: { prime-factors($_).elems, $_ };
return @sorted-nums;
}
# Test Cases
say sort-by-prime-factors([11, 8, 27, 4]);