Advent Calendar 2024
| Day 9 | Day 10 | Day 11 |
The gift is presented by Robbie Hatley
. Today he is talking about his solution to The Weekly Challenge - 260. This is re-produced for Advent Calendar 2024
from the original post.
The Weekly Challenge 260
Task #1: Unique Occurrences
You are given an array of integers, @ints.
Write a script to return 1 if the number of occurrences of each value in the given array is unique or 0 otherwise.
There are probably other ways to solve this (TIMTOWTDI
), but the method I stumbled on was to first create a sub called "occurrences"
which returns a list of the occurrences of the various kinds of elements in the input array, then I apply "occurrences" twice
, basically "occurrences of occurrences"
. If the result is a list of 1s
, then the occurrences of element kinds are unique, otherwise they aren’t. Instead of checking every element of "occurrences of occurrences"
individually, I just look at their product; if it’s 1
, the occurrences are unique, otherwise they aren’t:
use v5.38;
use utf8;
use List::Util 'product';
# What are the occurrences of the elements of an array?
sub occurrences(@array) {
my %a;
for my $item (@array) {++$a{$item};}
return values %a;
}
# Are the occurrences of the elements of an array unique?
sub occurrences_are_unique(@array) {
return 1 == product occurrences occurrences @array;
}
my @arrays = @ARGV ? eval($ARGV[0]) :
(
[1,2,2,1,1,3],
[1,2,3],
[-2,0,1,-2,1,1,0,1,-2,9],
);
for my $aref (@arrays) {
say '';
say '@ints = (', join(', ', @$aref), ')';
occurrences_are_unique @$aref
and say 1, ' (occurrences are unique)'
or say 0, ' (occurrences are not unique)';
}
Task #2: Dictionary Rank
You are given a word, $word.
Write a script to compute the dictionary rank of the given word.
Example 1 says "combinations"
, but the context makes it clear that the author actually meant "permutations"
. With that in mind, I use the "permute"
function from CPAN
module "Math::Combinatorics"
to get a list of all letter orders, then sort, then use the "uniq"
function from CPAN
module "List::Util"
to get rid of duplicates, then use the "firstidx"
function from CPAN
module "List::MoreUtils"
to find the index of the first element which is equal to the original word, then add 1
for 1-indexing
:
use v5.38;
use utf8;
use Math::Combinatorics 'permute';
use List::Util 'uniq';
use List::MoreUtils 'firstidx';
# What is the "dictionary order" (as defined in the problem
# description) of a word?
sub dictionary_order ($word) {
my @dic = uniq sort map {join '', @$_} permute split //, $word;
return 1 + firstidx {$_ eq $word} @dic;
}
my @words = @ARGV ? @ARGV : qw( CAT GOOGLE SECRET );
for my $word (@words) {
say '';
say "word = $word";
say 'dictionary order = ', dictionary_order($word);
}
If you have any suggestion then please do share with us perlweeklychallenge@yahoo.com.