Advent Calendar - December 5, 2024

Thursday, Dec 5, 2024| Tags: Perl, Raku

Advent Calendar 2024

|   Day 4   |   Day 5   |   Day 6   |


The gift is presented by Laurent Rosenfeld. Today he is talking about his solution to The Weekly Challenge - 255. This is re-produced for Advent Calendar 2024 from the original post 1. and post 2.



Task 1: Odd Character



You are given two strings, $s and $t.
The string $t is generated using the shuffled characters of the string $s with an additional character.

Write a script to find the additional character in the string $t.

Odd Character in Raku



This task is really simple in Raku: we simply convert each input string into a Bag of its letters, and then use the (-) infix set difference operator to find the extra item in $t. So we end up with a short one-line subroutine.


sub odd-char ($s, $t) {
    return ~ ($t.comb.Bag (-) $s.comb.Bag);
}

for <Perl Preel>, <Weekly Weeakly>, <Box Boxy> -> @test {
    printf "%-8s %-8s => ", @test;
    say odd-char @test[0], @test[1];
}

This program displays the following output:


$ raku ./odd-characters.raku
Perl     Preel    => e
Weekly   Weeakly  => a
Box      Boxy     => y

Odd Character in Perl



The solution is slightly more complicated in Perl, because Perl doesn’t have Bags and set difference operators. We can easily replace bags with hashes (with values being the frequency of each letter). Then we have to find the extra hash item in %t.


use strict; use warnings; use feature 'say';

sub odd_char {
    my (%s, %t);
    %s = map { $_ => ++$s{$_} } split //, $_[0];
    %t = map { $_ => ++$t{$_} } split //, $_[1];
    my @result = grep { (not defined $s{$_})
        or $t{$_} - $s{$_} > 0 } keys %t;
}

for my $test ([<Perl Preel>], [<Weekly Weeakly>], [<Box Boxy>]) {
    printf "%-8s %-8s => ", @$test;
    say odd_char $test->[0], $test->[1];
}

This program displays the following output:


$ perl  ./odd-characters.pl
Perl     Preel    => e
Weekly   Weeakly  => a
Box      Boxy     => y

Task 2: Most Frequent Word



You are given a paragraph $p and a banned word $w.

Write a script to return the most frequent word that is not banned.

Most Frequent Word in Raku



We first use the tr/// in-place transliteration operator to remove punctuation characters from the input paragraph, which makes it possible to use the words to split the paragraph into words. We then use grep to remove the banned word from the word list and convert the resulting list into a Bag, histo (for histogram). Finally, we return the item from the bag having the highest frequency.


sub most-frequent-word ($para is copy, $banned) {
    $para ~~ tr/,.:;?!//;
    my $histo = $para.words.grep({$_ ne $banned}).Bag;
    return $histo.keys.max({$histo{$_}});
}

my $t = "Joe hit a ball, the hit ball flew far after it was hit.";
printf "%-30s... => ", substr $t, 0, 28;
say most-frequent-word $t, "hit";

$t = "Perl and Raku belong to the same family. Perl is the most popular language in the weekly challenge.";
printf "%-30s... => ", substr $t, 0, 28;
say most-frequent-word $t, "the";

This program displays the following output:


$ raku ./most-frequent-word.raku
Joe hit a ball, the hit ball  ... => ball
Perl and Raku belong to the   ... => Perl

Most Frequent Word in Perl



This is a port to Perl of the Raku program above, using a hash instead of a Bag and the split function instead of words.


use strict;
use warnings;
use feature 'say';

sub most_frequent_word {
    my ($para, $banned) = @_;
    $para =~ tr/,.:;?!//;
    my %histo;
    %histo = map { $_ => ++$histo{$_} }
        grep {$_ ne $banned} split /\W/, $para;
    return (sort { $histo{$b} <=> $histo{$a} } keys %histo )[0];
}

my $t = "Joe hit a ball, the hit ball flew far after it was hit.";
printf "%-30s... => ", substr $t, 0, 28;
say most_frequent_word $t, "hit";

$t = "Perl and Raku belong to the same family. Perl is the most popular language in the weekly challenge.";
printf "%-30s... => ", substr $t, 0, 28;
say most_frequent_word $t, "the";

This program displays the following output:


$ perl ./most-frequent-word.pl
Joe hit a ball, the hit ball  ... => ball
Perl and Raku belong to the   ... => Perl


If you have any suggestion then please do share with us perlweeklychallenge@yahoo.com.

|   Advent Calendar 2024   |

SO WHAT DO YOU THINK ?

If you have any suggestions or ideas then please do share with us.

Contact with me