THE WEEKLY CHALLENGE - 237
https://theweeklychallenge.org/blog/perl-weekly-challenge-237/
Table of Contents
Task 1 - Seize the day
Today, we'll be tackling an interesting problem: given a year, a month, a weekday of the month, and a day of the week, we want to find out the exact date that corresponds to these details. Specifically, the task is to determine the day of the month for the Nth occurrence of a specific weekday in a specific month and year.
The Problem Statement
The problem is simple yet intriguing. Given a year, month, weekday of the month (1st, 2nd, 3rd, etc.), and a day of the week (1 for Monday, 2 for Tuesday, ..., 7 for Sunday), the task is to find the exact day of the month that corresponds to these parameters.
For example, if the year is 2024, the month is April, the weekday of the month is 3rd, and the day of the week is Tuesday (2), the corresponding date is the 16th of April 2024.
Algorithmic Approach
- Step 1: Calculate the day of the week for the first day of the given month and year.
- Step 2: Determine the difference in days between this day of the week and the desired day of the week.
- Step 3: Use this difference to find the date of the first occurrence of the desired day of the week in the given month.
- Step 4: Add
(N - 1) * 7
days to this date to find the Nth occurrence. - Step 5: If the resulting date still falls within the same month, then it's a valid date; otherwise, return 0.
Perl Solution
In Perl, we use the Time::Local
module to calculate the day of the week for the first day of the given month and year.
Here is a snippet of the Perl code:
# Calculate the timestamp for the first day of the month
my $first_day = timelocal(0, 0, 0, 1, $month - 1, $year);
# Calculate the day of the week for the first day of the month
my $first_day_of_week = (localtime($first_day))[6];
# Calculate the difference in days to reach the desired day of the week
my $days_diff = ($day_of_week - $first_day_of_week) % 7;
# Calculate the timestamp for the nth occurrence
my $nth_occurrence = $first_occurrence + (($weekday_of_month - 1) * 7 * 86400);
Raku Solution
In Raku, the Date
class provides an easy way to work with dates. We can create a Date
object for the first day of the given month and year and use its .day-of-week
method to get the day of the week.
Here's a snippet of the Raku code:
# Calculate the day of the week for the first day of the month
my $first-day-of-week = Date.new($year, $month, 1).day-of-week;
# Calculate the difference in days to reach the desired day of the week
my $days-diff = ($day-of-week - $first-day-of-week) % 7;
# Calculate the nth occurrence
my $nth-occurrence = 1 + $days-diff + ($weekday-of-month - 1) * 7;
Python Solution
In Python, we can use the datetime
module to achieve the same. Here's a snippet:
from datetime import datetime, timedelta
# Calculate the day of the week for the first day of the month
first_day_of_week = datetime(year, month, 1).weekday()
# Calculate the difference in days to reach the desired day of the week
days_diff = (day_of_week - first_day_of_week - 1) % 7
# Calculate the nth occurrence
nth_occurrence = 1 + days_diff + (weekday_of_month - 1) * 7
Conclusion
By understanding how to manipulate dates and times in different programming languages, we can solve a variety of real-world problems. This problem is just one example, but the techniques used can be applied in many other situations.
Task 2 - Maximise Greatness
Problem Statement
Given an array of integers, the task is to permute the array in such a way that we get the maximum possible "greatness" score. The greatness score is calculated as follows: For each index ( i ) in the array, if ( array[i] < perm[i] ), we increment the greatness score by 1.
For example, given the array ([1, 3, 5, 2, 1, 3, 1]), one possible permutation with maximum greatness is ([2, 5, 1, 3, 3, 1, 1]), yielding a greatness score of 4.
Algorithm
The algorithm is quite simple:
- Sort the array in ascending order.
- Iterate through the original array and for each element:
- Find the smallest element in the sorted array that is greater than the current element.
- Remove that element from the sorted array.
- Increment the greatness counter.
Perl Solution
In Perl, we use the splice
function to remove an element from the sorted array.
sub maximise_greatness {
my @nums = @_;
my @sorted_nums = sort { $a <=> $b } @nums;
my $greatness = 0;
for my $num (@nums) {
for my $i (0..$#sorted_nums) {
if ($sorted_nums[$i] > $num) {
$greatness++;
splice(@sorted_nums, $i, 1);
last;
}
}
}
return $greatness;
}
Python Solution
In Python, we use the remove
method to remove an element from the sorted array.
def maximise_greatness(nums):
sorted_nums = sorted(nums)
greatness = 0
for num in nums:
for i in range(len(sorted_nums)):
if sorted_nums[i] > num:
greatness += 1
sorted_nums.pop(i)
break
return greatness
Raku Solution
In Raku, we use the splice
method to remove an element from the sorted array.
sub maximise-greatness(@nums) {
my @sorted-nums = @nums.sort({ $^a <=> $^b });
my $greatness = 0;
for @nums -> $num {
for 0..^@sorted-nums.elems -> $i {
if @sorted-nums[$i] > $num {
$greatness++;
@sorted-nums.splice($i, 1);
last;
}
}
}
return $greatness;
}
Conclusion
The problem of maximizing greatness in an array can be efficiently solved in Perl, Python, and Raku with slight variations in syntax but keeping the core algorithm the same. All three languages offer efficient ways to manipulate arrays, making it easy to implement the solution.