SPVM 0.9663 is released

dev.to #perl

Published by Yuki Kimoto -- Perl Club on Tuesday 29 November 2022 00:06

SPVM 0.9663 is released.

New Features and Enhancement

Changes

0.9663 2022-11-29
  [Changes]
    * Add the following file to the MANIFEST.SKIP that is generated by the spvmdist command.

      ^cpanm$
    * The version of the module file that is generated by the spvmdist command is not outputted
      when the --only-lib-files option is specified.
  [New Features]
    * Added the follwoing opitonal arguments to the push method in the StringBuffer class.

      [Before]
      method push : void ($string : string);

      [After]
      method push : void ($string : string, $offset = 0 : int, $length = -1 : int);

      And added the some exceptions. See the doc.

        Adds a C<$string> from the C<$offset> to the position proceeded by the C<$length> after the end of the string in the string buffer.

        Exceptions:

        The C<$string> must be defined.

        The C<$offset> must be greater than or equal to 0.

        The C<$offset> + C<$length> must be less than or equal to the length of the C<$string>.
    * Added the follwoing method to the Hash class.
      method clone : Hash ();
      method to_array : object[] ($sort = 0 : int);
      method delete_or_default_byte : int ($key : string, $default : int);
      method delete_or_default_short : int ($key : string, $default : int);
      method delete_or_default_int : int ($key : string, $default : int);
      method delete_or_default_long : long ($key : string, $default : long);
      method delete_or_default_float : float ($key : string, $default : float);
      method delete_or_default_double : double ($key : string, $default : double);
      method delete_or_default_string : string ($key : string, $default : string);
      method delete_or_default : object ($key : string, $default : object);


    * Added the Cloneable interface to tha Hash class.

  [Imcompatible New Features]
    * The octal escape character \000 and \o{} is added.
      \000 got to be interpreted \o{00} instead of "\0" . "00"
    * The \0 becomes the feature of the octal escape character.
  [Internal Non-Affecting Changes]
    * Fixed the bug that MyTest::compile_ok and MyTest::compile_not_ok can't create the multi-level directory.
  [Compilation And Runtime Error Message Improvement]
    * Notation of class names, method names, field names, and class variable names in compilation and runtime error messages has been unified.
      The \"%s\" class.
      The \"%s\" method.
      The \"%s\" instance method.
      The \"%s\" class method.
      The \"%s\" field.
      The \"%s\" class variable.
  [Exception Error Message Improvement]
    * The notation of the arguments in the exception messages is unified.
      The $foo
  [Bug Fix]
    * Fixed the bug that the interface of the parent class is not recognized.
    * Fiexd the bug that The checking of the required method doesn't see the super class
      https://github.com/yuki-kimoto/SPVM/issues/246
    * Fixed the bug that when searching field doesn't found in the super class, eternal loop occur.
      https://github.com/yuki-kimoto/SPVM/issues/249
    * The bug that original exception is overwriten by destructor exception
      https://github.com/yuki-kimoto/SPVM/issues/253
    * Fixed the bug that Windows I/O binary mode in spvmcc command.
  [Incompatible Bug Fix]
    * Fixed the bug that Format->sprintf "%p" output differs Linux and Windows.  "0x" is added to the output on Windows.
  [New Features]
    * The method can have the more optional arguments than the arguments of the interface method.
    * Added the following methods to the Fn class.

      static method sizeof_native_int : int ();
      static method sizeof_native_pointer : int ();
      static method init_string : void ($string : mutable string, $ascii_code = 0 : int, $offset = 0 : int, $length = -1 : int);

  [Imcompatible Changes]
    * The field in the "foo" class with the same name as the "MyClass\" field in the parent class cannot be defined.
  [Exception Message Improvement]
    Improve the following message.
    [Before]
      (An exception thrown in the DESTROY method is converted to a warning)%s\n
    [After]
      [The following exception is coverted to a warning because it is thrown in the DESTROY method]\n%s\n

#592 - Perl Blogging?

Perl Weekly

Published on Monday 28 November 2022 10:00

Hi there,

We all know not many people blog about Perl anymore. Are we doing anything to get it back on track? Well, unfortunately again, nothing is happening on that front either.

But, hey, there is still hope and handful of Perl fans doing their best. One of them is our chief editor, Gabor Szabo. He has been running Perl Maven for years now and many of us benefitted from his work. He recently started blogging on Dev.To. I request all the Perl fans to follow him and like blog post. I didn't have the account there before so I decided to create personal account. Although I no longer blog at all but this is going to change soon. Earlier I used to blog on blogs.perl.org but then I moved to The Weekly Challenge recently.

Talking about blogging, how can I miss one name, Flavio Poletti? He has been blogging daily for years now. Feel free to check out his work here. Kudos to him for his effort.

I would like to mention another name, Olaf Alders, for his hard work in reviving the good old friend, Perl Advent Calendar. Julien has been helping him in the project too. I remember there was a call for papers by him. If you have time and something to share about your favourite CPAN module then please do contribute. I have booked one slot for myself for this year Advent Calendar. Hopefully, I will submit my article on time.

Last but not the least, I would like to thank all the members of Team PWC for creating friendly and positive vibes for years now. As of today, they have published 3000+ blog posts sharing creative ideas and solutions. If you are interested then please do checkout blog posts.

Enjoy the rest of the newsletter.

Perl Weekly #592 - Perl Blogging?

dev.to #perl

Published by Gabor Szabo on Monday 28 November 2022 06:57

Originally published at Perl Weekly 592

Hi there,

We all know not many people blog about Perl anymore. Are we doing anything to get it back on track? Well, unfortunately again, nothing is happening on that front either.

But, hey, there is still hope and handful of Perl fans doing their best. One of them is our chief editor, Gabor Szabo. He has been running Perl Maven for years now and many of us benefitted from his work. He recently started blogging on Dev.To. I request all the Perl fans to follow him and like blog post. I didn't have the account there before so I decided to create personal account. Although I no longer blog at all but this is going to change soon. Earlier I used to blog on blogs.perl.org but then I moved to The Weekly Challenge recently.

Talking about blogging, how can I miss one name, Flavio Poletti? He has been blogging daily for years now. Feel free to check out his work here. Kudos to him for his effort.

I would like to mention another name, Olaf Alders, for his hard work in reviving the good old friend, Perl Advent Calendar. Julien has been helping him in the project too. I remember there was a call for papers by him. If you have time and something to share about your favourite CPAN module then please do contribute. I have booked one slot for myself for this year Advent Calendar. Hopefully, I will submit my article on time.

Last but not the least, I would like to thank all the members of Team PWC for creating friendly and positive vibes for years now. As of today, they have published 3000+ blog posts sharing creative ideas and solutions. If you are interested then please do checkout blog posts.

Enjoy the rest of the newsletter.

--
Your editor: Mohammad S. Anwar.

Announcements

This Week in PSC (088)

Brief update about the Perl Steering Council latest meetup.

Sponsors

Personalized investment with Torto AI

Any investment in the stock market is partially based on objective data (e.g. P/E ratio) and partially on the subjective world-view of the investor (expected changes in inflation, politics, weather etc.) torto.ai works on providing you a platform where you can easily combine these aspects and find the investment that most suitable for your expectation.

Articles

Two-factor authentication (2FA) in Perl with TOTP algorithm (Microsoft or Google Authenticator or others)

Get the insights of 2FA and how Perl can help you deal with it.

Speaking of certificates and Root CAs...

Preparing for Advent of Code 2022

Samir sharing his plan for this year Advent of Code.

Mojolicious cheatsheet

For Mojolicious fan, please checkout this cheatsheet.

Kephra: Select All

If you are following post about Kephra then this is for you to explore further.

Web

Feature Switch Best Practices

Curtis is back, well organised blog post. Highly Recommended.

Git worktree

Nice little introduction to git worktree. Highly recommended if you are git fan.

An objective criteria for deprecating community platforms

Take a look at the history of community platforms. Interesting ...

Advent of Code 2022 is coming

Never played with Advent of Code. If time permits, I will give it a go. Thanks for sharing.

CPAN

Playing with MQTT

Do you know MQTT? I didn't. Thanks for sharing the knowledge.

The Weekly Challenge

The Weekly Challenge by Mohammad Anwar will help you step out of your comfort-zone. You can even win prize money of $50 Amazon voucher by participating in the weekly challenge. We pick one winner at the end of the month from among all of the contributors during the month. The monthly prize is kindly sponsored by Peter Sergeant of PerlCareers.

The Weekly Challenge - 193

Welcome to a new week with a couple of fun tasks: "Binary String" and "Odd String". If you are new to the weekly challenge, why not join us and have fun every week? For more information, please read the FAQ.

RECAP - The Weekly Challenge - 192

Enjoy a quick recap of last week's contributions by Team PWC dealing with the "Binary Flip" and "Equal Distribution" tasks in Perl and Raku. You will find plenty of solutions to keep you busy.

Flipping to Redistribute

Playing with raw bits makes it fun. Keep it up great work.

Flipped Equilibrium

Cool discussion of the task and solutions in Perl, Raku and Haskell. Worth checking it out. Thanks for sharing.

Frosting a cake without flipping the spatula

Plenty of different approaches discussed from the performance point of view. Great work, keep it up.

Liberté, Égalité, Fraternité

Colin's style of task analysis opens up new angle to it. Highly recommended.

PWC192 - Binary Flip

Bitwise operation in full play in Perl and Raku. Nice work.

PWC192 - Equal Distribution

Task analysis made it so simple to follow. Implementation in Perl and Raku is also fun to watch.

The Weekly Challenge 192

Loved the different ways to deal with bits. Enough to keep you busy. Highly Recommended.

The Counter to Equilibrium

Pure mathematical solution, very nice attempt. Thanks for sharing.

Perl Weekly Challenge 192: Binary Flip and Equal Distribution

Laurent's ability to make difficult task easy is worth watching. Keep it up great work.

distribute and flip

Special one-liner in Raku is not to be nissed. Well done. Thanks for sharing.

Perl Weekly Challenge 192

This week task fits in one-liner as far as Perl is concerned. Great work.

Flipping easy and distributing fairly

Pure discussion of task, just like story telling. You really don't want to skip it.

Equal Flips For All

Javascript bit operation in play this week. Great work, keep it up.

Weekly Challenge 192

As always, we got Perl and Python together playing with bits. Well done.

PWC 192

Loved the discussion of "Equal Distribution" task. Enjoy behind the scene story.

Rakudo

2022.47 Migratory

Weekly collections

NICEPERL's lists

Great CPAN modules released last week;
MetaCPAN weekly report;
StackOverflow Perl report.

The corner of Gabor

A couple of entries sneaked in by Gabor.

Read dates from Excel file using Perl

Videos about Docker

The latest Perl-related posts on DEV

Which articles did you like?

Perl Jobs by Perl Careers

Modern Perl and positive team vibes. UK Remote Perl role

If you’re a Modern Perl developer in the UK with Go-lang experience (or at least a strong desire to learn) and you’re searching for a team of dynamos, we’ve found the perfect place for you. This award-winning company may be newer, but the combined experience of their people is impressive. No doubt this is one of the many reasons their AI recruitment marketing business has taken off!

Bold, beautiful, and… brainy? Senior Perl roles in Malaysia, Dubai and Malta

Our client provides online trading services and with offices in Dubai, Malta, and Malaysia, they’ve got the global reach that may provide the challenge you’re looking for. For the right person, they’ve got a work-sponsored visa and relocation package — if you’ve got the expertise and an adventurous spirit, they’ve got the will and means to get you where you need to be.

C, C++, and Perl Software Engineers, Let’s Keep the Internet Safe. UK Remote Perl Role.

A leading digital safeguarding solutions provider is looking for a software engineer experienced in C, C++, or Perl. You’ll have strong Linux knowledge and a methodical approach to problem solving that you use to investigate, replicate, and address customer issues. Your keen understanding of firewalls, proxies, Iptables, Squid, VPNs/IPSec and HTTP(S) will be key to your success at this company.

Perl to Node Cross-training? Yes Please! UK Remote Perl Role

The client is interested in anyone with experience building web apps in Perl, using one of the major Perl frameworks. If you’re a crack-hand with Catalyst, a Mojolicious master, or a distinguished Dancer, they want you. You’ll be deploying apps your work to AWS, so experience would be handy, and the company’s big on testing, so they’d like you to know your way around Test::More.

Perl Developer and Business Owner? Remote Perl role in UK & EU

Our clients run a job search engine that has grown from two friends with an idea to a site that receives more than 10 million visits per month. They're looking for a Perl pro with at least three years of experience with high-volume and high-traffic apps and sites, a solid understanding of Object-Oriented Perl (perks if that knowledge includes Moose), SQL/MySQL and DBIx::Class.

You joined the Perl Weekly to get weekly e-mails about the Perl programming language and related topics.

Want to see more? See the archives of all the issues.

Not yet subscribed to the newsletter? Join us free of charge!

(C) Copyright Gabor Szabo
The articles are copyright the respective authors.

TWC 192: Frosting a cake without flipping the spatula

blogs.perl.org

Published by Bruce Gray on Monday 28 November 2022 00:29

In which we refine and refactor past the point of recognition:

(  [\+] ( @a X- target )  )».abs.sum

In Raku, Perl, and Rust.

(Still editing)

TWC Task #1 - Binary Flip

Task and Observations

Given a positive Int, flip all the bits.

Some possible approaches:

  1. Binary XOR
  2. Change to bitstring, tr///, change to int.
  3. Change to bitstring, split to list of chars, map with translation table, join, change to int.
  4. Loop while non-zero, examining bottom bit, setting flipped bit in result, bit-shift input and result.

Thoughts:

  • Approach #1 requires calculating what number would be all binary 1's with the same count of binary digits as the input, but is very efficient.
  • Approach #2 is slower but the code is clearer.
  • Approach #3 I would not choose over #2 in any language that has tr///.
  • Approach #4 is fine, but uses explicit loops that I find less clear and less elegant than the others. Might be fastest, though; I have not checked.

Perl

Approach #2:

use v5.36;
sub task1 ($n) {
    return oct '0b' . sprintf('%b', $n) =~ tr/01/10/r;
}

In recent Perl, the tr/// translation accepts the /r modifier, to return a modified copy instead of modifying the original.

Poorly-named oct() does not just translate octal; it looks for other prefixes like 0b or 0x and translates them from binary or hex to decimal.

Raku

Approaches #1 and #2:

# Faster, by about 10x
sub all_ones (UInt $n --> UInt) { ( 1 +< ($n.log2.floor + 1) ) - 1 }
sub fast1    (UInt $n --> UInt) { $n +^ all_ones($n) }

# Clearer:
sub task1    (UInt $n --> UInt) {
    return $n.base(2)
             .trans( <0 1> => <1 0> )
             .parse-base(2);
}

The full file has a bonus test that task1() and fast1() match output over the first 16_384 integers.

Rust

fn flip_bits(n: u32) -> u32 {
    let all_ones = (n + 1).next_power_of_two() - 1;

    return n ^ all_ones;
}

The full file has a bonus test that the first 64 integers match a pattern of jumping-then-falling values.


TWC Task #2 - Equal Distribution

Task

Given a list of non-negative integers, how many moves of surfit-->deficit, one at time until all are equal? Return -1 if equality is not achievable.

Observations

  • If @list.sum is not evenly divisible by @list.elems, no algorithm will succeed, we can return -1 via early exit.

Progressive analysis:

A:  6  3  3  3  3  0  3  3  3  3  0  1  3  3  3  6  5
B:  3  0  0  0  0 -3  0  0  0  0 -3 -2  0  0  0  3  2 @a X- $target
C:  3  3  3  3  3  0  0  0  0  0 -3 -5 -5 -5 -5 -2  0 [\+]
D:  3  3  3  3  3  0  0  0  0  0  3  5  5  5  5  2  0 abs
E:  3  6  9 12 15 15 15 15 15 15 18 23 28 33 38 40 40 [\+] to view

A: The initial array.

  • Clearly, the target level is 3.
    The excess 3 in that first 6 needs to fill in the first zero, 5 cells away, so that will cost 3*5=15 moves.
    The excess 3 in the last 6 moves 5 cells left into the last zero; 3*5=15 moves.
    The excess 2 in the last 5 moves 5 cells left into the one; 2*5=10 moves, so 40 moves total.

  • Cells already holding the target were "neutral" to our calculation. This suggests we should try "redefining the baseline" by removing the target from every cell, making the cells that already held the target become zero, and those with excess change to hold only the excess amount. That means that cells with less than the target will become negative. Would that break our model?

  • We moved some to the right, and some to the left, which feels like frosting a sheet cake, and would require forward and backward passes (loops over the array).
    But, as we learned with electricity, the flow of electrons, and the backwards "flow" of "holes" where each electron has left, are identical in everything but direction (+1/-1 "sign", in our case).

B: Removed 3 from every cell.

  • Raku: @a X- $target
  • Perl: map { $_ - $target } @a

C: Running total of B.

  • Notice all the zeros in the middle of C; they are not just copied down from B, the zeros are showing

, unless we weirdly allowed "negative frosting"

Raku

First attempt, as I explored the problem:

my $target = @a.sum div +@a;
# Ack! when a low value is in the middle, pull from which side?
# Sweep like icing a cake, either back-and-forth, or circularly via modulo.
# make test cases of 1 2 4 8 and 8 4 2 1
# No, cannot modulo, because task disallows.
my @forward  = @a.keys         .rotor(2 => -1);
my @backward = @a.keys.reverse .rotor(2 => -1);
my $count = 0;
my $i = 0;
until @a.all == $target {
    say "\nstart:", @a;
    for @forward -> ( \i, \j ) {
        if @a[i] > ( @a[j] & $target ) {
            @a[i]--;
            @a[j]++;
            $count++;
        }
    }
    say "FWD  :", @a;
    for @backward -> ( \i, \j ) {
        if @a[i] > ( @a[j] & $target ) {
            @a[i]--;
            @a[j]++;
            $count++;
        }
    }
    say "BACK :", @a;
}

Intermediate:

for @a.rotor( 2 => -1 ) {
 my $diff = .[0] - $target;
 .[0]   -= $diff;
 .[1]   += $diff;
 $count += $diff.abs;
}

die @a.raku unless @a.all == $target;

Final:

sub task2 ( @a --> Int ) {
    return -1 if @a.sum !%% +@a;

    my $target = @a.sum div @a.elems;

    my ($count, $mound) = 0, 0;
    for @a -> $a {
        $mound += $a - $target;
        $count += $mound.abs;
    }

    die "Cannot happen: $mound" unless $mound == 0;

    return $count;
}

How does that work?

The $mound is the excess (or deficit) value being pushed from the prior element onto the current element of the array.

Perl

use v5.36;
use List::Util qw<sum0 reductions>;
sub functional ( @a ) {
    my $s = sum0 @a;

    return -1 if $s % @a;
    my $target = $s / @a;

    return sum0 map         { abs $_ }
                reductions  { $a + $b }
                map         { $_ - $target }
                @a;
}
sub task2 ( @a ) {
    return -1 if sum0(@a) % scalar(@a);
    my $target = sum0(@a) / scalar(@a);

    my ($count, $mound) = 0, 0;
    for my $n (@a) {
        $mound += $n - $target;
        $count += abs $mound;
    }

    die "Cannot happen: $mound" unless $mound == 0;

    return $count;
}

A few tricks used here:

  • List::Util::reductions() is the Perl equivalent to Raku's .produce() or "triangular" reduce meta-op.

  • Both task2() and its functional() twin are tested by each test case.


Rust

fn task2 ( a : Vec<i32> ) -> i32 {
    let sum : i32 = a.iter().sum();
    let len : i32 = a.len() as i32;

    if sum % len != 0 {
        return -1;
    }

    let target = sum / len;

    // Raku code: (  [\+] ( @a X- target )  )».abs.sum
    return a.iter()
            .scan(0, |state, &x| { *state += x - target;
                                   Some(*state)          })
            .map(|x| { x.abs() })
            .sum();
}

While this code is generally concise, Rust's scan() feel clumsy to me.
I am not it's only critic.

Flipping to Redistribute

RabbitFarm Perl

Published on Sunday 27 November 2022 19:04

The examples used here are from the weekly challenge problem statement and demonstrate the working solution.

Part 1

You are given a positive integer, $n. Write a script to find the binary flip.

Solution


use v5.36;
sub int2bits{
    my($n) = @_;
    my @bits;
    while($n){
        my $b = $n & 1;
        unshift @bits, $b;
        $n = $n >> 1;
    }
    return @bits
}

sub binary_flip{
    my($n) = @_;
    my @bits = int2bits($n);
    @bits = map {$_^ 1} @bits;
    return oct(q/0b/ . join(q//, @bits));
}

MAIN:{
    say binary_flip(5);
    say binary_flip(4);
    say binary_flip(6);
}

Sample Run


$ perl perl/ch-1.pl
2
3
1

Notes

There was once a time when I was positively terrified of bitwise operations. Anything at that level seemed a bit like magic. Especially spooky were the bitwise algorithms detailed in Hacker's Delight! Anyway, has time has gone on I am a bit more confortable with these sorts of things. Especially when, like this problem, the issues are fairly straightforward.

The code here does the following:

  • converts a given integer into an array of bits via int2bits()

  • flips the bits using an xor operation (the map in binary_flip())

  • converts the array of flipped bits to the decimal equivalent via oct() which, despite the name, handles any decimal, binary, octal, and hex strings as input.

Part 2

You are given a list of integers greater than or equal to zero, @list. Write a script to distribute the number so that each members are same. If you succeed then print the total moves otherwise print -1.

Solution


use v5.36;
use POSIX;

sub equal_distribution{
    my(@integers) = @_;
    my $moves;
    my $average = unpack("%32I*", pack("I*",  @integers)) / @integers; 
    return -1 unless floor($average) ==  ceil($average);
    {
        map{
            my $i = $_;
            if($integers[$i] > $average && $integers[$i] > $integers[$i+1]){$integers[$i]--; $integers[$i+1]++; $moves++}
            if($integers[$i] < $average && $integers[$i] < $integers[$i+1]){$integers[$i]++; $integers[$i+1]--; $moves++}
        } 0 .. @integers - 2;
        redo unless 0 == grep {$average != $_} @integers;
    }
    return $moves;
}

MAIN:{
    say equal_distribution(1, 0, 5);
    say equal_distribution(0, 2, 0);
    say equal_distribution(0, 3, 0);
}

Sample Run


$ perl perl/ch-2.pl
4
-1
2

Notes

The rules that must be followed are:

1) You can only move a value of '1' per move

2) You are only allowed to move a value of '1' to a direct neighbor/adjacent cell.

First we compute the average of the numbers in the list. Provided that the average is a non-decimal (confirmed by comparing floor to ceil) we know we can compute the necessary "distribution".

The re-distribution itself is handled just by following the rules and continuously looping until all values in the list are the same.

References

oct

Challenge 192

RECAP - The Weekly Challenge - 192

The Weekly Challenge

Published on Monday 28 November 2022 00:00

TABLE OF CONTENTS 01. HEADLINES 02. STAR CONTRIBUTORS 03. CONTRIBUTION STATS 04. GUESTS 05. LANGUAGES 06. CENTURION CLUB 07. DAMIAN CONWAY’s CORNER 08. ANDREW SHITOV’s CORNER 09. PERL SOLUTIONS 10. RAKU SOLUTIONS 11. PERL & RAKU SOLUTIONS HEADLINES Thank you Team PWC for your continuous support and encouragement. STAR CONTRIBUTORS Following members shared solutions to both tasks in Perl and Raku as well as blogged about it.

The Weekly Challenge - 193

The Weekly Challenge

Published on Monday 28 November 2022 00:00

TABLE OF CONTENTS 01. HEADLINES 02. SPONSOR 03. RECAP 04. PERL REVIEW 05. RAKU REVIEW 06. CHART 07. NEW MEMBERS 08. GUESTS 09. TASK #1: Binary String 10. TASK #2: Odd String HEADLINES Welcome to the Week #193 of The Weekly Challenge. Life is always full of ups & downs. As the year ending, I look back and noticed I missed so many things. I wanted to do so much but couldn’t get anywhere near.

The Weekly Challenge - Guest Contributions

The Weekly Challenge

Published on Monday 28 November 2022 00:00

As you know, The Weekly Challenge, primarily focus on Perl and Raku. During the Week #018, we received solutions to The Weekly Challenge - 018 by Orestis Zekai in Python. It was pleasant surprise to receive solutions in something other than Perl and Raku. Ever since regular team members also started contributing in other languages like Ada, APL, Awk, BASIC, Bash, Bc, Befunge-93, Bourne Shell, BQN, Brainfuck, C3, C, CESIL, Chef, COBOL, Coconut, C Shell, C++, Clojure, Crystal, D, Dart, Dc, Elixir, Elm, Emacs Lisp, Erlang, Excel VBA, Fennel, Fish, Forth, Fortran, Gembase, GNAT, Go, Haskell, Haxe, HTML, Idris, IO, J, Janet, Java, JavaScript, Julia, Kotlin, Lisp, Logo, Lua, M4, Maxima, Miranda, Modula 3, MMIX, Mumps, Myrddin, Nelua, Nim, Nix, Node.

TWC 189: Saving your Degree by Great Character!

blogs.perl.org

Published by Bruce Gray on Sunday 27 November 2022 19:28

In which we achieve Single Pass and Single Expression, respectively.

Next door to the Haunted Mansion.

Note: Both of my Perl solutions use v5.36, because it auto-enables strict, warnings, and signatures.

The Raku solutions are registered as mind-altering substances.

Produced in a facility that may have contained peanuts, tree nuts, or Halloween.


TWC Task #1 - Greater Character

Fixing the Task

This task has a mis-match between the description and the examples. "...smallest character in the given array lexicographically greater than the target character" implies an undefined answer if nothing in the array is gt the target. However, the 5th example expects the target to be returned in that null case. I chose to code to match the examples, because it was a more interesting problem.

Perl

Final answer:

use v5.36;
use List::Util qw<minstr>;

sub task1 ( $aref, $target ) {
    my @gt = grep { $_ gt $target } @{$aref};

    return @gt ? minstr(@gt) : $target;
}

List::Util::minstr has the useful property of returning undef from an empty list, which allows this shorter version that I had wanted in Raku:

    return minstr( grep { $_ gt $target } @{$aref} )
            // $target;

I decided against that single-statement version, because:
1. it requires knowledge that minstr returns undef when given an empty list, and
2. compared to the two-statement form, // deemphasizes the ill-defined part of the task.

I also considered increasing the emphasis by splitting the solution into two subs along the fault-line of the contention:

sub smallest_gt_target ($a, $t) { minstr grep { $_ gt $t } @{$a} }
sub task1              ($a, $t) { smallest_gt_target($a, $t) // $t }

What do you think, would that increase in emphasis be worth the loss in D.R.Y.ness?

Raku

Final answer:

sub task1 ( @a, Str $target --> Str ) {

    return .elems ?? .min !! $target given @a.grep( * gt $target );

I could have used .so instead of .elems, but weighed .so as less well-known.

Similar:

return $_ eq 'Inf' ?? $target !! $_ given @a.grep(* gt $target).min;

I rejected it because:

  • You must know that .min returns Inf when called on an empty list.
  • I have to use the literal $_ two times, instead of zero times (.elems, .min) in the final answer.
  • Converting a potential Inf to string in order to compare with 'Inf' via eq felt icky for a Numeric.
  • (Related) I mis-remembered that Inf does not == itself; I was confusing its behavior with NaN, which indeed does not equal itself.

Single-pass too-clever alternative:

sub task1 ( @a, Str $target --> Str ) {

    return @a.min({ $_ !gt $target, $_ }) max $target;

BWAHAHAHAHA!

How does that work?

  • The methods .min, .max, .minmax, and .sort all default to using cmp as the comparator.
  • When comparing two Lists, cmp is run on the first element (.[0]) of each List, and if they are Order::Same, proceeds to cmp the second elements, and so on until the tie is broken or the lists are exhausted.
  • False is "less" than True; (True,False).sort would return (Bool::False, Bool::True).
  • The !gt operator is the same as le, but used in its negative form here to keep the "greater than" from the original wording and make the "greater than target" values "sort" (really the more efficient min) to the top, so we can only get a minimum value le target if no value is gt target.
  • If @a contained anything gt target, .min returns it, and it always wins in the fight against max $target, so the result is the intended value.
  • If @a contained nothing gt target, .min returns the lowest value in the whole array, and it must always lose in the fight against max $target, so the result is the specified target.

Even though I am writing Raku documentation compare&contrast sort versus min/max/minmax, and I wrote this code myself, I find this code hard to grok after being away for 5 minutes. It is particularly egregious "clever code", because it swallows the original problem requirements into its cleverness. You can't read that (uncommented) code and infer the spec. So, we don't really do such things in real life. Really!


TWC Task #2 - Array Degree

Fixing the examples

This task will involve keeping track of element counts and slice lengths and start indexes and end indexes; all of these are non-negative integers that the developer will be scrutinizing and staring at, past the midnight hour. And yet, even though the problem is exactly the same with arrays filled with any-old-thing, the task specifies non-negative integers for the array contents, and indeed, every example contains nothing but non-negative integers. Non-negative integers everywhere! It is enough to make a person... non-positive.

So, while I have kept the original examples intact, I commented them out during development. Just below them, you will see exact equivalent letter transpositions:
1 => A, 2 => B, etc. Thus, I kept my sanity. (But seem to have increased my verbosity?)

Key insight:

The positions of the element(s) contributing to the degree are all that matter.

If @a is 1000 elements, each a single capital letter, and the array's Degree is 99 (due to having 99 B, 99 F, 99 Y, and the other letters 98-or-less each), then our final slice of @a must include all the B's or all the F's or all the Y's. Otherwise, we have reduced the degree. Also, whichever of (B|F|Y) we choose, the slice must start and end with that letter. Otherwise, the slice is not as small as it could be.

Raku has the Bag type, which can concisely give us the array Degree with @a.Bag.values.max, but it will turn out that knowledge of the array Degree will not be useful enough to be worth calculating early!

For each element that exists in the array, we only need to know:

  • Count of occurrences
  • First position seen
  • Last position seen
  • Span (last_position - first_position + 1)

Once we have that information, of all the elements with maximum count (Degree), find which has the minimum span, and maybe use first position as a tie-breaker. For that element, make a Range of the first and last positions, and return a slice of @a[ $first .. $last ].

Raku (built-in) and Perl (module) have concise methods to "group" the array indexes by the elements found there. You will see code that does, and does not use them.

Perl

Raku's min/max do take &by parameters, but do not return a list when there are ties.

Raku's minpairs/maxpairs do return a list when there are ties, but do not take &by parameters.

The Perl module List::UtilsBy does both, and is a great fit for this problem.

Final answer:

#!/usr/bin/env perl
use v5.36;
use experimental     qw<for_list builtin>;
use builtin          qw<indexed>;
use List::UtilsBy    qw<max_by min_by>;

sub task2 ( @a ) {
    my %h;
    for my ($k, $v) (indexed @a) {
        my $href = ( $h{$v} //= {} );

        $href->{KEY  }   = $v;
        $href->{COUNT}  +=  1;
        $href->{FIRST} //= $k;
        $href->{LAST }   = $k;
    }
    $_->{SPAN} = $_->{LAST} - $_->{FIRST} + 1 for values %h;

    my $best = min_by { $_->{FIRST} }
               min_by { $_->{SPAN } }
               max_by { $_->{COUNT} }
               values %h;

   return [ @a[ $best->{FIRST} .. $best->{LAST} ] ];
}

A few tricks used here:

  • Perl v5.36's for_list and indexed are combined to have the same effect as Raku's for @a.kv -> $k,$v {...}.
  • my $href = ( $h{$v} //= {} ); just grabs a reference when the sub-hash already exists in %h. Otherwise it creates the sub-hash in %h just before taking the reference. This is a well-known idiom here, but I should have split it into two lines for expository code.
  • The sub-hashes are each a Record, achieved in Perl by only using a fixed set of keys. (Perl's hashes serve the purpose of other languages' Dictionaries,Sets,Bags,Mixes,Records just by how we use them. Perl's arrays similarly act as Stacks or Queues by only coding push&pop or push&shift.)
  • COUNT is auto-vivified and interpreted as zero for +=, so adding 1 gives us a running total of the times the element has been seen.
  • FIRST will only be undef the first time each element is seen, so //= only populates it once.
  • LAST is simply assigned to, so it keeps getting over-written; when we exit the loop, it will hold the last index where that element was seen.
  • SPAN would be awkward to calculate (and have to be recalculated on each loop), so a postfix for can populate it concisely and efficiently with the size of the slice reaching from first index where the element was seen to the last such index.
  • The array element is kept in the KEY slot, just to help with debugging. It gets overwritten on each loop, but always with the same value, so no problem. Now that I write that, I see that it could also use //= for efficiency.
  • max_by and min_by receive lists, and are called in list context until the last min_by, so ties are passed through. The last one cannot be a tie, because only one element could have any particular FIRST.
  • The chain of max_by and min_by act as tie-breakers; if only one element makes up the array's Degree, then it will be the only hashref emitted by max_by, and the two min_by will just pass it through without needing to do other work. If more than one element create the same maximum Degree, then the lowest SPAN is found, and so on.

I also wrote a version that collapsed (most of) the building of %h into a single line using List::Categorize:

use List::Categorize qw<categorize>;
sub task2 ( @a ) {
    my %h = categorize { $a[$_] } keys @a;

    my $best = min_by { $_->[0]                } # First
               min_by { $_->[-1] - $_->[0] + 1 } # Span
               max_by { 0+@{$_}                } # Count
               values %h;

    my ($head, $tail) = @{$best}[0,-1];
    return [ @a[ $head .. $tail ] ];
}

This may be less efficient than the earlier version; categorize (like .classify later in the Raku code) will keep all of the locations where each element is found, which is much more info than we strictly need. More important to me is that hand-rolling %h allows me to NAME the slots in each href. The %h that categorize populates requires comments to clarify the min_by and max_by code blocks.

Raku

Final answer:

sub task2 ( @a ) {
    my $best =
        @a.pairs
        .classify( {.value}, :as{.key} )
        .map({ .value })
        .max({ .elems, -(.tail - .head + 1), -.head });

    return @a[ $best.head .. $best.tail ];
}

How does that work? Well, let's look at almost the same code, with intermediate variables for each line, like the Raku REPL could demonstrate:

my @a = <A B C B D A B D A>;
       # 0 1 2 3 4 5 6 7 8 are the indexes.


my @b = @a.pairs;
    [0 => A  1 => B  2 => C  3 => B
     4 => D  5 => A  6 => B  7 => D  8 => A]


my @c = @b.classify( {.value}, :as{.key} );
    [A => [0 5 8] D => [4 7] C => [2] B => [1 3 6]]


my @d = @c.map({ .value });
    [[0 5 8] [4 7] [2] [1 3 6]]

(Without the map of .value, we would have to precede many methods with .value in the lines below. Surprisingly, we do not need the .key at all any more!)

Here we will diverge from the actual code, so you can see the values that .max will operate on in the real code.

my @e = @d.map: {
    my $r = .head .. .tail;
    (.elems, -$r.elems, -.head, $r);
};


say @e.sort.reverse; # For illustration only; we will really
                     # use `max` instead of `sort.reverse`.
                     # Note that Span and First will be negated.

   Count = Number of times it occured
   |
   |  Span = size of the range from first to last occurance
   |  |
   |  |  First position found
   |  |  |
   |  |  |  Range of first..last positions found
   |  |  |  |
   v  v  v  v
( (3 -6 -1 1..6)   # 'B' 3 times, span=6, first in pos 1, over 1..6
  (3 -9  0 0..8)   # 'A' 3 times, span=9, first in pos 0, over 0..8
  (2 -4 -4 4..7)   # 'D' twice, is less than the degree of A or B
  (1 -1 -2 2..2) ) # 'C' once , is less than the degree of A or B


my $best = @e.max;
    (3 -6 -1 1..6)


return @a[ $best[3].list ]; # Expand the Range 1..6
                            # to allow the slicing.

We are relying on the max/min/cmp action on List that we used in Task#1.

The black-cat-level sneakiness here is that we can get the min of numbers by scanning for the max of their negated values.

So, we don't really need that big .map to build the List of sorting fields; we can specify them inline as the &by argument to .max:

.max({ .elems, -(.tail - .head + 1), -.head });

Now $best is the full list of indexes of the winning element, and we need the full range from the first place that element was found, to the last, even including other intervening elements (or it wouldn't be a "slice").

return @a[ $best.head .. $best.tail ];

By the way, these three produce the same result Pairs. Which do you like better?

@a.keys  .classify( { @a[$_] }              )
@a.pairs .classify( { .value }, :as{ .key } )
@a       .classify( { $_     }, :as{ $++  } )

I'm fixing a hole where the rain gets in
And stops my mind from wandering
Where it will go
(La la la la la)
-- Fixing a Hole, by The Beatles
(as covered by George Burns, after being re-arranged by the Bee Gees. BWAHAHAHAHAHA!)

Why do you prefer using a scripting language?

dev.to #perl

Published by Mike Nakis on Sunday 27 November 2022 10:46

Scripting languages have seen tremendous growth in recent years. CodingNomads ran some stats on job postings on Linkedin (see cover image) and found that from the top-10 programming languages in highest demand in 2022, six of them are scripting languages.

Why do you choose to program in a scripting language rather than in a real programming language?

Please tell us your reasons.

To help you get started, here are some ready-made options:

  • It is easier to learn.
  • It is easier to be productive.
  • It gives fewer errors.
  • I do not want to have to wait for it to compile.
  • It does not require an IDE, I can just use a text editor.
  • I do not need type safety, because I do testing.
  • There exist lots of libraries for it.
  • I can modify my program as it is running.
  • It is the only option on the browser.
  • It is easy to find a job doing it.
  • I have not learned any real programming language.

Weekly Challenge 192

dev.to #perl

Published by Simon Green on Sunday 27 November 2022 09:30

Challenge, My solutions

Task 1: Binary Flip

Task

You are given a positive integer, $n.

Write a script to find the binary flip.

My solution

So there are at least two ways you could take this task. The obvious option is to convert $n to a binary, use string.translate (or tr in Perl) to flip the bits, and convert this back to an integer number. And given that this is a one off with a very small number, that's a perfectly acceptable solution.

The solution I chose was to find the next power of 2 higher than $n, and then subtract one less than that from the original number.

As an example, the next power of 2 for the number 5 is 8 = 2³. One less than that is 7 (binary 111). Since we know that in subtraction that effectively will flip all the bits, we will have the correct solution.

Examples

$ ./ch-1.py 5
2

$ ./ch-1.py 4
3

$ ./ch-1.py 6
1

Task 2: Equal Distribution

Task

You are given a list of integers greater than or equal to zero, @list.

Write a script to distribute the number so that each members are same. If you succeed then print the total moves otherwise print -1.

Please follow the rules:

  1. You can only move a value of '1' per move
  2. You are only allowed to move a value of '1' to a direct neighbor/adjacent cell

My solution

Like most weeks, I wrote the code for this task on Monday evening (morning UK time). It was pretty straight forward (a couple of lines). Also like most weeks, I tend to write my blog on a Sunday evening. So I went to write this blog post and the rules have changed :)

Which I don't really mind as the new rules makes the task more challenging. The original solution was just a simple calculation (the sum of all numbers greater than the average). I'm sure some cleverer Team PWC members were able to do the same with the new challenge, but in the end I took the approach of actually moving the numbers.

We know that a solution is only possible if the sum of all numbers is even divisible by the number of numbers. If this isn't the case, I print -1 and exit. If it is I store this as the target value.

I then work through the list from left to right. If the number is less than the target, we know we need to take value away from a different number. This is the needed value. I then have an inner loop that also works from left to right to decide where to take the value from. The logic behind this is taking values from the leftmost item in the excess of the target will result in less moves.

The value we can take is the minimum of needed or the excess value from the target, which I have called take. We take the value from one and give to another. The needed value is reduced, and we add the take value by the number of positions to the moves count. If the needed value is still not zero we continue this inner loop moving to the next leftmost number greater than the target.

Examples

$ ./ch-2.py 1 0 5
4

$ ./ch-2.py 0 2 0
-1

$ ./ch-2.py 0 3 0
2

(cdxx) 11 great CPAN modules released last week

Niceperl

Published by Unknown on Sunday 27 November 2022 08:58

Updates for great CPAN modules released last week. A module is considered great if its favorites count is greater or equal than 12.

  1. Alien::Build - Build external dependencies for use in CPAN
    • Version: 2.73 on 2022-11-20
    • Votes: 22
    • Previous version: 2.72 was 25 days before
  2. App::Netdisco - An open source web-based network management tool.
    • Version: 2.059001 on 2022-11-26
    • Votes: 14
    • Previous version: 2.058003 was 22 days before
  3. DBIx::Class::Schema::Loader - Create a DBIx::Class::Schema based on a database
    • Version: 0.07051 on 2022-11-23
    • Votes: 45
    • Previous version: 0.07049 was 4 years, 8 months, 2 days before
  4. Dist::Zilla - distribution builder; installer not included!
    • Version: 6.029 on 2022-11-25
    • Votes: 178
    • Previous version: 6.028 was 16 days before
  5. Exporter::Tiny - an exporter with the features of Sub::Exporter but only core dependencies
    • Version: 1.006000 on 2022-11-21
    • Votes: 21
    • Previous version: 1.004004 was 1 month, 6 days before
  6. Future::AsyncAwait - deferred subroutine syntax for futures
    • Version: 0.61 on 2022-11-21
    • Votes: 44
    • Previous version: 0.59 was 1 month, 28 days before
  7. IO::Socket::SSL - Nearly transparent SSL encapsulation for IO::Socket::INET.
    • Version: 2.077 on 2022-11-21
    • Votes: 44
    • Previous version: 2.076 was 7 days before
  8. Log::Any - Bringing loggers and listeners together
    • Version: 1.711 on 2022-11-22
    • Votes: 60
    • Previous version: 1.710 was 1 year, 3 months, 20 days before
  9. Module::CoreList - what modules shipped with versions of perl
    • Version: 5.20221120 on 2022-11-20
    • Votes: 40
    • Previous version: 5.20221020 was 1 month before
  10. Mojolicious - Real-time web framework
    • Version: 9.30 on 2022-11-23
    • Votes: 475
    • Previous version: 9.29 was 12 days before
  11. Pod::Man - Convert POD data to various other formats
    • Version: 5.00 on 2022-11-25
    • Votes: 12
    • Previous version: 4.14 was 2 years, 10 months, 21 days before

(dxxxiii) metacpan weekly report - Perl::Critic

Niceperl

Published by Unknown on Sunday 27 November 2022 08:56

This is the weekly favourites list of CPAN distributions. Votes count: 42

Week's winner: Perl::Critic (+2)

Build date: 2022/11/27 07:55:57 GMT


Clicked for first time:


Increasing its reputation:

(dlxi) stackoverflow perl report

Niceperl

Published by Unknown on Sunday 27 November 2022 08:55

These are the five most rated questions at Stack Overflow last week.
Between brackets: [question score / answers count]
Build date: 2022-11-27 07:54:48 GMT


  1. perldoc does not display text between section - [2/2]
  2. How to access multiple option values from hash specification - [2/1]
  3. Perl :: Can You Have a Lists of Objects Within a Hash? - [2/1]
  4. How to Bless Objects in a List Passed to a Subroutine? - [2/1]
  5. Restore pack value from hex string - [2/1]

An objective criteria for deprecating community platforms

blogs.perl.org

Published by Dean on Saturday 26 November 2022 08:01

Perl has been around for a couple of years longer than Python and Linux. Perl 5 was released in 1993, the same year as FreeBSD and NetBSD.

In the 90's for Open Source projects the "community platforms" where Usenet newsgroups and mailing lists run on Listserv or Majordomo (Mailman didn't show up until 1999). IRC was used for text based chat but without SSL!. CVS was the open source version control system of choice or you might have been unlucky enough to use Visual Source Safe at work, whilst Subversion wouldn't show up until 2000.

But the 90's are more than 20 years in the past and IPv6 is actually seeing meaningful adoption now. Many of the above technologies are as completely foreign to people with 10+ years of industry experience as Compact Cassettes, VHS, LaserDisc and maybe CDs or even DVDs.

As people have embraced Git and even now IPv6 - we too can and must embrace newer platforms that offer a better experience for us humans as we work together on Perl related projects.

This will mean making some difficult and dispassionate decisions to deprecate long cherished platforms, as we embrace contemporary alternatives.

I think a reasonable decision criteria would be:

1. Will a newcomer have a satisfactory experience?
Which includes more than:

1a. How discoverable is it?
1b. How high/low is the barrier of entry?
1c. How familiar is the interface to newcomers?
1d. How intuitive and effective is the user interface?
1e. Will questions be taken seriously and answered in a timely manner?
1f. Is the platform providing reasonable privacy and moderation controls?

2. How much time will admins spend maintaining the platform compared to maintaining the community on the platform?

3. Would it be set up now if it didn't already exist?

Mailing lists are a good example which we can compare to my criteria.

If you can find the right list, you subscribe and send your question. Your email address is blasted out to all subscribers which aren't visible to you, whilst your inbox is already being filled with all discussion on the list even if you're not interested- assuming there is any discussion.

Good luck finding old questions or discussions to contribute or update on.

Once something is sent it can never be edited or removed from recipients. Users have each others email addresses so can contact each other without moderation. You can set up filters in your email if you care to, but this is an inconsistent user interface that is user dependent and you're still having to maintain the folder's unread messages. Emails themselves become dominated by reply text, making reviewing threads high effort and low signal compared to interfaces like reddit or even a classic but inferior webforum layout.

If I started a new community I wouldn't create an email list.

Run IRC through the above criteria and its even worse! To have a good experience users need to connect continuously or set up something that does. Then try to sift through the stream of content to find some signal. If there's any significant activity, questions and comments will get lost in the stream or conflated with other discussion.

So let's not, metaphorically speaking, hand new Perl programmers an audio cassette saying "this really is the best way to listen to music" and then expect them to take Perl seriously or to conclude that it is anything other than a dead language.

Kephra: Select All

blogs.perl.org

Published by lichtkind on Saturday 26 November 2022 00:43

To continue my previous post about Kephra, please let me ramble about just one seemingly little feature. It is interesting in its own right - but also an example for the design principles I employ:

1. max productivity

2. max consistency (less to memorize)

3. breaking habits and customs only when 1 and 2 demand it.

As soon graphics plays a greater role I will add max beauty as new 2.

The feature is called incremental selection and there are a few fancy editors who implement it. It is an extension on an idea already present in nearly all editors; when you click on text : the first left click moves the cursor to this position. The second on same position selects the word and third the whole line. That I meant by "an expanding selection" and I find it crazy that even that functionality is not available from keyboard. I'm a strong believer in the UI principle that every function should be available from every input method (unless very good reasons).

Atom has a rich Selection menu. But this is only an excellent and fast documentation - not something fur intuitively and fast usage. And since there are more things you want to select than key combinations you want to learn - why not put them all on one. Repeating the same key stroke doesn't cost much finger movement and expanding selection is kinda the same thing over and over.

The only key combo which is already universally used to select something is <Ctrl>+<A> and we all know how seldom its actually used. Even select one word/variable/command is more often needed So lets put that on <Ctrl>+<A>. And (long live Huffman - Coding) if you press it four times you still end up selecting the document (after selected line and block).

But we can go even crazier since there is really not much difference to press it four or 6 times right. Since were programmer - we often want to get a quoted string without much cursor navigation - or a complete loop with head and body. This would also avoid the hassle of finding free key bindings for syntax scheme dependent commands. Why not blend their functionality into the existing commands? And the good thing (since <Ctrl>+<Shift>+<A> is also still free) we could use that key combo to revert the expansion in case you pressed it one time to many.

This Week in PSC (088)

blogs.perl.org

Published by Perl Steering Council on Friday 25 November 2022 21:58

A smaller-than-usual meeting because of the US Holiday; only Paul and Philippe today.

  • We remembered we still need to write the announcement for deprecating smartmatch
  • We need to resync with Neil about how "SSL in Core" investigations are going
  • Reviewed RFCs and found a shortlist of "soon to expire" ones. A nudge email will be sent to the RFC sponsors.

Perl Dancer #3 - Hello World

dev.to #perl

Published by Gabor Szabo on Friday 25 November 2022 05:25

In this video first we check what happened to the installation and then if it was successful then we are going to write our first Dancer-based web application.

Then I can go to the Command Prompt or the Power Shell if I was on Windows, or if I was on Linux or Mac I'd go to the terminal and type in the following:

perl -MDancer2 -e1

This will run perl. *-MDancer2 will make it try to load the Dancer2 module into memory and -e1 just tells perl to execute the program
consisting of the number 1 which is a non-operation. It basically tells perl to do nothing.
The goal here is to see if perl can find and load the Dancer2 module.

If there is no output to the screen that means everything is fine. Unlike in the previous case when this command failed.

This, not having any output, means that Dancer2 is installed.

If, however, we try

perl -MDancer3 -e1

We'll get something like:

Can't locate Dancer3.pm in @INC (you may need to install the Dancer3 module) (@INC contains:
/home/gabor/perl5/lib/perl5/5.34.0/x86_64-linux-gnu-thread-multi
/home/gabor/perl5/lib/perl5/5.34.0
/home/gabor/perl5/lib/perl5/x86_64-linux-gnu-thread-multi
/home/gabor/perl5/lib/perl5
/etc/perl
/usr/local/lib/x86_64-linux-gnu/perl/5.34.0
/usr/local/share/perl/5.34.0
/usr/lib/x86_64-linux-gnu/perl5/5.34
/usr/share/perl5
/usr/lib/x86_64-linux-gnu/perl-base
/usr/lib/x86_64-linux-gnu/perl/5.34
/usr/share/perl/5.34
/usr/local/lib/site_perl).
BEGIN failed--compilation aborted.

This failed obviously because Dancer3 is not installed because it does not even exist.

It told me that it can't locate Dancer3 and that I should install it.

Of course perl does not know that my problem here is not the lack of installation, but that I made a mistake (on purpose) in the name of the module.

Course slides

The other thing that we left at the end of the previous video was the unzipping of the course material.
If you switch to the other window - the file explorer - where you started the unzip, you'll see a folder (directory) called slides-main.

Within the slides-main you will find a folder for each training course I have.

The Dancer2 course material is within the perl course and thus in the perl folder.

Within the perl folder you'll find the example files from the slides by following the path that you can see above each example on the slides.
For example here.

Then I switched to the Command Prompt/Terminal and typed in cd (change directory) and then the path where I wanted to switch to.

I can go to the file-explorer, click on the "address bar" and then it will show me the full path to the directory I am viewing.
I can copy that by pressing Ctrl-C then I can paste it to the terminal window my clicking on the right button of the mouse.

hen I can press the Home key to jump to the beginning of the line and type in cd.

cd c:\course\slides-main\perl\examples\dancer\hello_world

By pressing ENTER I'll jump to the selected folder.

If now I type in

dir

I can see the files that are in that directory.

... app.psgi
... test.out
... test.t

Switching to the file-explorer I can see the same.

Among the 3 files in the directory: app.psgi is the file that we'll actually need now. That's where our "application" is.
test.t is the test file that is checking that our code works properly.

Then you'll find all kinds of extra files with .out extension that you won't have in a real application.
I only have them to store the output of various commands so I can include it in the slides.
You don't have to worry about those files.

Hello World

The content of the app.psgi file can be seen here:

package App;
use Dancer2;

get '/' => sub {
    return 'Hello World!';
};

App->to_app;

What you need to do at this point is type in the Command Prompt:

plackup

It will print something like this on the screen:

HTTP::Server::PSGI: Accepting connections at http://0:5000/

This tells us that the server is running and accepting connection on port 5000.

If you are using Windows, you'll probably also see a pop-up of the Windows Defender Firewall saying that it has blocked
some features of this app.

This happens if you have the Windows Firewall on your computer that will limit the access to your computer.

It has two checkboxes, one to enable access on Private networks, the other to enable access on Public networks

For some reason on my computer the Public networks was checked. I prefer to only allow access on Private networks so I checked that box
and unchecked the box of the Public networks.

Then I clicked Allow access. It took a couple of seconds to make the pop-up disappear.
It might have been slow because I was recording the video on a Windows running in a Virtual Box while the video-recording was running.
So my computer was already busy.

Then I can open my browser to the URL that was listed on the terminal window: http://0:5000/. (you should be able to just click on this link)

If that does not work you can also try to type in http://127.0.0.1:5000/ which is going to "localhost" which is your computer.

Finally you can try http://localhost:5000/.

In the video you can see that I tried all of these using the browser that came with Windows (I think it was Edge).

Install Firefox or Chrome

So because I could not convince Edge to work I decided to download Firefox. Which is Open Source so I like it.

While I was waiting for Firefox to be installed I tried Edge again and this time it worked.

Either I did something incorrectly earlier or Edge just got scared when it saw I am downloading Firefox and started to work.

Finally it works!

So we can see in the browser Hello World1. It's not much of a web application, but it works and it is ours!

In the terminal/Command Prompt window you can see the access log. Apparently also the previous attempts showed up even though we did not get a response in the browser.

The code

Let's go over the code now.

package App;

This is just the declaration of the Perl package. The name App isn't really important here. You can put there virtually anything.
As long as at the end of the code you use the same name.

use Dancer2;

This loads the Dancer2 module. (This is what the -MDaner2 did on the command line.)

get '/' => sub {
    return 'Hello World!';
};

This is called a route.

The way Dancer works is that we need to map URL pathes to anonymous functions. (You could also use named functions, but they are usually anonymous.)

The "path" is the part that comes in the URL after the name of web site. So in case of this URL: "https://code-maven.com/slides/dancer/hello-world-with-dancer"
The part "/slides/dancer/hello-world-with-dancer" is the path.

In case of "http://localhost:5000/" the path is just "/" though when I typed it in the browser hid it.

I could also type in some longer path, for example I tried "http://localhost:5000/hello" and I got a Error 404 - Not Found message.
That's because the path /hello has not been defined in this application.

After the get keyword is the path we are mapping.

After the fat-arrow => you can see the anonymous subroutine. Whatever it returns is sent back to the browser.

It can return some HTML to make a nice page, but in our case we only returned the plain text "Hello World!" and the browser displayed it.

The code with the fat-arrow might look a bit strange, especially if you know Perl, but it is basically just a key-value pair
where the path is the key and the anonymous function is the value.

Just don't forget the semi-colon at the end of that block! This is one of the cases when after the closing of curly braces you have to put a semi-colon
because this is a statement and not just a block.

The same as this code written slightly differently might help you understand what's really going on here.

get('/', sub {
    return 'Hello World!';
});

We imported the get function from the Dancer2 module. This function gets two parameters. The first one is the path and the second one is the function to be executed when someone requests that path.

Stop the application

To stop the application you need to switch to the terminal/command prompt again and press Ctrl-C. Windows will ask you for confirmation. Type Y.

Testing

Then remains the question, how do we know that this actually works. Without manually starting the whole thing and then visiting the web site?

This is what we'll see in the next video.

Raku Advent Calendar submission deadline approaching!

Perl Foundation News

Published by Amber Deuel on Thursday 24 November 2022 13:36

The Christmas season is almost here, and that means a fresh batch of Raku Advent Calendar posts. Every year since 2009, the Raku community has hosted an annual Advent event, in the spirit of Perl and other projects, consisting of daily articles starting on the 1st of December and ending on the 25th. The Raku community has had so many great posts and, hopefully, this year will live up to that same high standard.

But, to do that, Raku needs your help: If you'd like to write a post, please sign up on the Raku Advent Calendar GitHub repo. The deadline for post submission is December 1st (next week!). However, if you would like to post but cannot meet that deadline, please sign up anyway and reach out about when you can submit a post – it's likely that we can make the timing work.

Let’s all write some great posts and have a Merry Raku Advent indeed!

Maintaining Perl (Tony Cook) October 2022

Perl Foundation News

Published by alh on Wednesday 23 November 2022 09:01


Tony writes:

``` [Hours] [Activity] 2022/10/01 Saturday  0.12 github notifications  0.22 #20355 comment

 0.13 #20362 ask for more info

 0.47

2022/10/03 Monday  1.05 #20207 LogFile::Read, Nagios::Cmd patches  0.23 #20207 Log::Procmail patch

 0.05 #20346 Text::PerlPP - look at test report and comment

 1.33

2022/10/06 Thursday  0.07 github notifications  0.67 #20355 long comment  1.03 #20362 review new info, research and comment  0.80 #20026 research and comment  0.18 #20356 review and approve  0.30 #20290 review testing (was going to merge, but) comment on test noise  0.23 #20367 review and approve

 0.30 #20309 review and comment

 3.58

2022/10/10 Monday  0.23 #20290 review updates and apply to blead, perldelta  0.23 #20372 testing, comment  0.70 #20370 review and approve  0.17 #20380 review and approve  2.00 #20362 re-work test-dist-modules (based on Bram’s PR)  2.83 #20362 fix, restart, not using system perl, add missing file for threads, threads-shared, debugging, move file data to DATA, testing

 0.05 #20362 fixes and push for more CI

 6.21

2022/10/11 Tuesday  1.72 #20362 clean up commits, add more logging, testing  3.28 #20362 look into failures, fix build issue with threads, threads-shared, fix probing bug on darwin, try fix for emulation not happening (macos system perl doesn’t -

DPERL_DARWIN)

 5.00

2022/10/12 Wednesday  0.75 #20372 research and comment (and some #p5p discussion)  2.98 #20362 look into EU:PXS failure and update EU::CBuilder, commit clean up, polish

 1.78 #20362 more polish, final test, post PR #20385

 5.51

2022/10/13 Thursday  0.08 #20304 review and approve  0.68 github notifications  0.28 #20362 changes to avoid conflict with #20304  0.30 #20388 review, research and comment briefly  0.52 #20390 review and comment  0.30 #20387 review, research and approve

 1.75 #20346 testing, debugging

 3.91

2022/10/17 Monday  0.35 #20362/#20385 follow-up on PR comments  0.13 #20403 review and approve  0.35 #20388 review and comment  0.40 #20402 review and approve  0.50 #20404 review, research and approve  0.33 #20393 review and comment  0.60 #20351 apply to blead, perldelta  1.45 look into blead test failure (Test::More related?), cannot reproduce

 0.35 look over RFC discussions

 4.46

2022/10/18 Tuesday  0.30 github notifications  0.40 #20199 apply to blead, perldelta and open related #20408  0.47 #20397 review and approve  0.38 #20408 comment

 1.97 #19964 re-work, testing

 3.52

2022/10/19 Wednesday  0.92 #19964 fixes, testing, push for CI  0.13 github notifications  0.68 #20409 why hasn’t this been an issue before - testing, only in miniperl, comment  0.20 rfc pr #30 review and comments  0.43 #20399 research  0.43 #19964 look into test failures

 0.95 #20412 review, research and comment

 3.74

2022/10/20 Thursday  1.70 #20411 reproduce, debugging  2.83 #20411 look into why the save stack is getting so large, try some fixes, look into supplied solution, work on

better solution, testing

 4.53

2022/10/24 Monday  0.38 github notifications  0.85 rfc #17 review and comments  0.13 #20417 review and approve  0.65 #20398 review  0.10 #20398 more review and comment  0.08 #20429 review and approve  0.18 #20428 review and comment  0.03 #20424 review and approve with comment  0.67 #20415 review and approve  0.57 #20385 rebase, testing and apply manually to blead  0.42 #20363 recheck, issues with blead, fix B::Op_private

version, investigate other problems

 4.06

2022/10/25 Tuesday  0.33 github notifications  0.22 #20427 review and comment  0.58 look into dist-modules macos failures, make PR 20436  0.35 rfc #17 look at changes  0.57 #20434 review and comment

 0.50 #20435 review and comments

 2.55

2022/10/26 Wednesday  1.37 #20440 review, testing, long comment  0.65 #20427 follow-up, some #p5p discussion  0.03 #20435 briefly comment  0.68 #20365 review  1.03 #20365 try to track down issue, more testing, comments  0.80 #20346 look over still failing modules, retest Mojolicioous::Plugin::RenderCGI and comment  0.33 #20427 discussion, review patch and approve

 0.12 #20440 approve modified PR

 5.01

2022/10/27 Thursday  2.53 #20365 alt branch review, testing, comments at https://github.com/Perl/perl5/commit/d6b8be71272aafbbaa17b b27be4ac484f8726651

 1.43 #20411 try to make patch crash

 3.96

2022/10/28 Friday

 0.85 #20446 review updates, testing, comments

 0.85

2022/10/31 Monday  1.88 #19814 review, performance testing, comment  1.30 #20446 review updates, minor comments  0.58 #20457 review, comments  0.32 #20459 comment  0.37 #20460 review discussion and comment  0.22 #20378 review, research and comment  0.25 #20451 review and comment  0.62 #20411 polish, testing, push for CI

 0.87 security list - research, comment

 6.41

Which I calculate is 65.1 hours.

Approximately 51 tickets were reviewed or worked on, and 4 patches were applied. ```

Read dates from Excel file using Perl

Perl Maven

Published by Gabor Szabo on Wednesday 23 November 2022 05:30

There are several modules on CPAN that help your read an Excel file. In this article we'll look at handling dates that are in Excel files.

#591 - Less than 50% use CI

Perl Weekly

Published on Monday 21 November 2022 10:00

Hi there,

One of the best things about programming is that you can get almost immediate feedback from your work. The compiler tells you immediately if your code has syntax errors. Your tests can tell you within minutes if your code does what you expected on your computer. Your CI system can tell you within another few minutes if your code works on various other environments.

In the Perl community writing test became the norm. You rarely find any Open Source Perl code without tests. People write test even for code that only they use. Even for code they consider 'toys'. Yet with CI we are still far from it. On our stats page you can see that 12% are missing their link to VCS (some of those do have VCS they are just missing the link), but 45-60% (depending on the week) of CPAN releases have no CI configured.

From experience I know that corporations are way behind the curve in terms of test writing. So I can only imagine how few use Continuous Integration. There is a lot of work to be done.

Enjoy your week!

Twice Largest Once Cute

RabbitFarm Perl

Published on Sunday 20 November 2022 21:50

The examples used here are from the weekly challenge problem statement and demonstrate the working solution.

Part 1

You are given list of integers, @list. Write a script to find out whether the largest item in the list is at least twice as large as each of the other items.

Solution


use v5.36;
use strict;
use warnings;

sub twice_largest{
    my(@list_integers) = @_;
    my @sorted_integers = sort {$a <=> $b} @list_integers;
    for my $i (@sorted_integers[0 .. @sorted_integers - 1]){
        unless($sorted_integers[@sorted_integers - 1] == $i){
            return -1 unless $sorted_integers[@sorted_integers - 1] >= 2 * $i; 
        }
    }
    return 1;
}

MAIN:{
    say twice_largest(1, 2, 3, 4);
    say twice_largest(1, 2, 0, 5);
    say twice_largest(2, 6, 3, 1);
    say twice_largest(4, 5, 2, 3);
}

Sample Run


$ perl perl/ch-1.pl
-1
1
1
-1

Notes

For Part 1 I at first couldn't see how to avoid a basic O(n^2) nested for loop. After I took a nap I think the best approach is what I have here:

  1. sort the list O(n log n)

  2. get the max element from the sorted list O(1)

  3. iterate over the sorted list, stop and return false if at any point an element times two is not less then max. return true if all elements (other than $max itself) pass the test. O(n)

So total worst case dominated by the sort O(n log n).

(And the nap was required because I was on an overnight camping trip with my son's Cub Scout pack the previous day and barely slept at all!)

Part 2

You are given an integer, 0 < $n <= 15. Write a script to find the number of orderings of numbers that form a cute list.

Solution


use v5.36;
use strict;
use warnings;

use Hash::MultiKey;

sub cute_list{
    my($n) = @_;
    my %cute;
    tie %cute, "Hash::MultiKey";
    for my $i (1 .. $n){
        $cute{[$i]} = undef;
    }
    my $i = 1;
    {
        $i++;
        my %cute_temp;
        tie %cute_temp, "Hash::MultiKey";
        for my $j (1 .. $n){
            for my $cute (keys %cute){
                if(0 == grep {$j == $_} @{$cute}){
                    if(0 == $j % $i || 0 == $i % $j){
                        $cute_temp{[@{$cute}, $j]} = undef;
                    }    
                }
            }
        }
        %cute = %cute_temp;
        untie %cute_temp;
        redo unless $i == $n;
    }
    return keys %cute;
}

MAIN:{
    say cute_list(2) . q//;
    say cute_list(3) . q//;
    say cute_list(5) . q//;
    say cute_list(10) . q//;
    say cute_list(11) . q//;
    say cute_list(15) . q//;
}

Sample Run


$ perl perl/ch-2.pl
2
3
10
700
750
24679

Notes

This solution with a dynamic programming style approach seems to work pretty well. cute(11) runs in less than a second (perl 5.34.0, M1 Mac Mini 2020) which is pretty good compared to some other reported run times that have been posted to social media this week.

Some may notice that the solution here bears a striking resemblance to the one for TWC 117! The logic there was a bit more complicated, since multiple paths could be chosen. The overall idea is the same though: as we grow the possible lists we are able to branch and create new lists (paths).

References

Challenge 191

RECAP - The Weekly Challenge - 191

The Weekly Challenge

Published on Monday 21 November 2022 00:00

TABLE OF CONTENTS 01. HEADLINES 02. STAR CONTRIBUTORS 03. CONTRIBUTION STATS 04. GUESTS 05. LANGUAGES 06. CENTURION CLUB 07. DAMIAN CONWAY’s CORNER 08. ANDREW SHITOV’s CORNER 09. PERL SOLUTIONS 10. RAKU SOLUTIONS 11. PERL & RAKU SOLUTIONS HEADLINES Thank you Team PWC for your continuous support and encouragement. STAR CONTRIBUTORS Following members shared solutions to both tasks in Perl and Raku as well as blogged about it.

The Weekly Challenge - 192

The Weekly Challenge

Published on Monday 21 November 2022 00:00

TABLE OF CONTENTS 01. HEADLINES 02. SPONSOR 03. RECAP 04. PERL REVIEW 05. RAKU REVIEW 06. CHART 07. NEW MEMBERS 08. GUESTS 09. TASK #1: Binary Flip 10. TASK #2: Equal Distribution HEADLINES Welcome to the Week #192 of The Weekly Challenge. Another busy week with 100+ contributions. This is the record in the history of The Weekly Challenge, we achieved the target for the 8th consecutive weeks. Thank you Team PWC for the support and encouragement.

(cdxix) 10 great CPAN modules released last week

Niceperl

Published by Unknown on Saturday 19 November 2022 23:20

Updates for great CPAN modules released last week. A module is considered great if its favorites count is greater or equal than 12.

  1. Code::TidyAll - Engine for tidyall, your all-in-one code tidier and validator
    • Version: 0.83 on 2022-11-19
    • Votes: 38
    • Previous version: 0.82 was 7 months, 4 days before
  2. Devel::NYTProf - Powerful fast feature-rich Perl source code profiler
    • Version: 6.12 on 2022-11-16
    • Votes: 180
    • Previous version: 6.11 was 1 year, 1 month, 27 days before
  3. FFI::Platypus - Write Perl bindings to non-Perl libraries with FFI. No XS required.
    • Version: 2.05 on 2022-11-16
    • Votes: 58
    • Previous version: 2.04 was 11 days before
  4. Getopt::Long - Module to handle parsing command line options
    • Version: 2.54 on 2022-11-17
    • Votes: 114
    • Previous version: 2.52 was 2 years, 2 months, 30 days before
  5. IO::Socket::SSL - Nearly transparent SSL encapsulation for IO::Socket::INET.
    • Version: 2.076 on 2022-11-14
    • Votes: 44
    • Previous version: 2.075 was 2 months, 12 days before
  6. Minilla - CPAN module authoring tool
    • Version: v3.1.20 on 2022-11-13
    • Votes: 58
    • Previous version: v3.1.19 was 5 months, 10 days before
  7. Mozilla::CA - Mozilla's CA cert bundle in PEM format
    • Version: 20221114 on 2022-11-14
    • Votes: 18
    • Previous version: 20211001 was 1 year, 1 month, 13 days before
  8. PDF::API2 - Create, modify, and examine PDF files
    • Version: 2.044 on 2022-11-16
    • Votes: 27
    • Previous version: 2.043 was 11 months, 8 days before
  9. Perl::LanguageServer - Language Server and Debug Protocol Adapter for Perl
    • Version: v2.4.0 on 2022-11-18
    • Votes: 26
    • Previous version: 2.3.0 was 1 year, 1 month, 22 days before
  10. SPVM - SPVM Language
    • Version: 0.9662 on 2022-11-15
    • Votes: 27
    • Previous version: 0.9659 was 18 days before

(dxxxii) metacpan weekly report - Perl::Dist::APPerl

Niceperl

Published by Unknown on Saturday 19 November 2022 23:18

This is the weekly favourites list of CPAN distributions. Votes count: 39

Week's winner (+3): Perl::Dist::APPerl

Build date: 2022/11/19 22:16:45 GMT


Clicked for first time:


Increasing its reputation:

#590 - Perl & Corinna

Perl Weekly

Published on Monday 14 November 2022 10:00

Hi there,

Congratulation to all England cricket team fans for the T20I world cup trophy. You played like a champion in the final. Although you beat us (India) in the semi final, still I am very happy for you.

Did you hear any update about Corinna recently?

We used to get regular update earlier and I really enjoyed the discussion about the Corinna. Last week Curtis shared a tweet where he mentioned that code example has been added to README.md. I am sure you are going to love it. Thank you Curtis and the entire team of Corinna for all the hard work. We are waiting for it patiently.

There was one more tweet by Curtis that made my day about the proposed feature of Perl v5.38 where you no longer need to end module with true value. In my career of 23 years, I have come across many creative ways to return true values in the module. I welcome this change and thanks the entire team.

I am keeping the editorial short this week as I am running short of time. Enjoy the rest of the newsletter.

Capital Detection Decode

RabbitFarm Perl

Published on Sunday 13 November 2022 21:12

The examples used here are from the weekly challenge problem statement and demonstrate the working solution.

Part 1

You are given a string with alphabetic characters only: A..Z and a..z. Write a script to find out if the usage of Capital is appropriate if it satisfies at least one of the rules.

Solution


use v5.36;
use strict;
use warnings;

use boolean;

sub capital_detection{
    {my($s) = @_; return true if length($s) == $s =~ tr/A-Z//d;}
    {my($s) = @_; return true if length($s) == $s =~ tr/a-z//d;}
    {
        my($s) = @_; 
        $s =~ m/(^.{1})(.*)$/;
        my $first_letter = $1;
        my $rest_letters = $2;
        return true if $first_letter =~ tr/A-Z//d == 1 &&
                       length($rest_letters) == $rest_letters =~ tr/a-z//d;
    }
    return false;
}

MAIN:{
    say capital_detection(q/Perl/);
    say capital_detection(q/TPF/);
    say capital_detection(q/PyThon/);
    say capital_detection(q/raku/);
}

Sample Run


$ perl perl/ch-1.pl
1
1
0
1

Notes

The rules to be satisfied are:

1) Only first letter is capital and all others are small.

2) Every letter is small.

3) Every letter is capital.

I did a bit of experimenting with tr this week. Somewhat relatedly I also reminded myself of scope issues in Perl.

The tr function has a nice feature where it returns the number of characters changed, or as was the case here, deleted. Here we delete all upper or lower case letters and if the number of letters deleted is equal to original length we know that the original contained all upper/lower case letters as required by the rules. One catch is that tr when used this way alters the original string. One way around that would be to use temporary variables. Another option is to contain each of these rules checks in their own block!

Part 2

You are given an encoded string consisting of a sequence $s of numeric characters: 0..9. Write a script to find the all valid different decodings in sorted order.

Solution


use v5.36;
use strict;
use warnings;

use AI::Prolog;
use Hash::MultiKey;

my $prolog_code;
sub init_prolog{
    $prolog_code = do{
        local $/;
        <DATA>;
    };
}

sub decoded_list{
    my($s) = @_;
    my $prolog = $prolog_code;
    my @alphabet = qw/A B C D E F G H I J K L M N O P Q R S T U V W X Y Z/;
    my @encoded;
    my @decoded;
    my $length = length($s);
    $prolog =~ s/_LENGTH_/$length/g;
    $prolog = AI::Prolog->new($prolog); 
    $prolog->query("sum(Digits).");
    my %h;
    tie %h, "Hash::MultiKey";
    while(my $result = $prolog->results){
        $h{$result->[1]} = undef;
    }
    for my $pattern (keys %h){
        my $index = 0;
        my $encoded = [];
        for my $i (@{$pattern}){
            push @{$encoded}, substr($s, $index, $i);
            $index += $i;
        }
        push @encoded, $encoded if 0 == grep { $_ > 26 } @{$encoded};
    }
    @decoded = sort { $a cmp $b } map { join("", map { $alphabet[$_ - 1] } @{$_}) } @encoded;
}

MAIN:{
    init_prolog;
    say join(", ", decoded_list(11));
    say join(", ", decoded_list(1115));
    say join(", ", decoded_list(127));
}

__DATA__
member(X,[X|_]).
member(X,[_|T]) :- member(X,T).

digits([1, 2]).

sum(Digits):-
    sum([], Digits, 0).

sum(Digits, Digits, _LENGTH_). 

sum(Partial, Digits, Sum):-   
    Sum < _LENGTH_, 
    digits(L),
    member(X,L),
    S is Sum + X,
    sum([X | Partial], Digits, S). 

Sample Run


$ perl perl/ch-2.pl
AA, K
AAAE, AAO, AKE, KAE, KO
ABG, LG

Notes

There is an element of this task which reminded me of a much older problem presented back in TWC 075. In brief, the question was how many ways could coins be used in combination to form a target sum. My solution used a mix of Prolog and Perl since Prolog is especially well suited for elegant solutions to these sorts of combinatorial problems.

I recognized that this week we have a similar problem in how we may separate the given encoded string into different possible chunks for decoding. Here we know that no chunk may have value greater than 26 and so we can only choose one or two digits at a time. How many ways we can make these one or two digit chunks is the exact same problem, somewhat in hiding, as in TWC 075!

I re-use almost the exact same Prolog code as used previously. This is used to identify the different combinations of digits for all possible chunks. Once that is done we need only map the chunks to letters and sort.

References

Scoping in Perl

Challenge 190

#589 - GitHub Actions for Perl modules

Perl Weekly

Published on Monday 07 November 2022 10:00

Hi there!

Winter has arrived to us as well. After many months, yesterday was the first day I had to put on long trousers and socks. Tomorrow we might even get some rain. Anyway...

It is still a bit surprising to me that only about 50% of the distributions recently uploaded to CPAN have any CI configured. Look at the stats and look at the detailed report. Clearly we, in the Perl community, have been spoiled by the excellent work of the CPAN Testers and thus people feel less need to enable GitHub Actions. On the other hand by enabling GitHub Actions they could reduce the load from the (very few) CPAN testers. They could get feedback much faster. In some ways they could do even do more diverse testing.

I just saw the Tips for testing Perl modules via GitHub of Felipe Gaspar. There are some excellent suggestions on how to test your module on some special versions of perl and on other platforms such as Cygwin, FreeBSD, OpenBSD. Just to name a few. I'd like to also reiterate my offer. If you'd like to get help adding GitHub Actions to your project, open an issue on your GitHub project and tag me (@szabgab) so I'll be notified. I'll be happy to help and maybe even create a blog post and record a video about your module. I keep a journal of the recent PRs I sent with some comments and links.

The Perl community embraced automated tests. Every Perl module comes with lots of tests. Let's now embrace Continuous Integration that runs on every push and executes these test to get very quick feedback!

Enjoy your week!

To a Greater Degree

RabbitFarm Perl

Published on Sunday 06 November 2022 18:58

The examples used here are from the weekly challenge problem statement and demonstrate the working solution.

Part 1

You are given an array of characters (a..z) and a target character. Write a script to find out the smallest character in the given array lexicographically greater than the target character.

Solution


use v5.36;
use strict;
use warnings;

sub greatest_character{
    my($characters, $target) = @_;
    return [sort {$a cmp $b} grep {$_ gt $target} @{$characters}]->[0] || $target;
}

MAIN:{
    say greatest_character([qw/e m u g/], q/b/);
    say greatest_character([qw/d c e f/], q/a/);
    say greatest_character([qw/j a r/],   q/o/);
    say greatest_character([qw/d c a f/], q/a/);
    say greatest_character([qw/t g a l/], q/v/);
}

Sample Run


$ perl perl/ch-1.pl
e
c
r
c
v

Notes

Practically a one liner! Here we use grep to filter out all the characters greater than the target. The results are then sorted and we return the first one. If all that yields no result, say there are no characters greater than the target, the just return the target.

Part 2

You are given an array of 2 or more non-negative integers. Write a script to find out the smallest slice, i.e. contiguous subarray of the original array, having the degree of the given array.

Solution


use v5.36;
use strict;
use warnings;

sub array_degree{
    my(@integers) = @_;
    my @counts;
    map { $counts[$_]++ } @integers;
    @counts = grep {defined} @counts;
    return [sort {$b <=> $a} @counts]->[0];
}

sub least_slice_degree{
    my(@integers) = @_;
    my @minimum_length_slice;
    my $minimum_length = @integers;
    my $array_degree = array_degree(@integers);
    for my $i (0 .. @integers - 1){
        for my $j ($i + 1 .. @integers - 1){
            if(array_degree(@integers[$i .. $j]) == $array_degree && @integers[$i .. $j] < $minimum_length){
                @minimum_length_slice = @integers[$i .. $j];
                $minimum_length = @minimum_length_slice;
            }
        }
    }
    return @minimum_length_slice;
}

MAIN:{
    say "(" . join(", ", least_slice_degree(1, 3, 3, 2)) . ")";
    say "(" . join(", ", least_slice_degree(1, 2, 1)) . ")";
    say "(" . join(", ", least_slice_degree(1, 3, 2, 1, 2)) . ")";
    say "(" . join(", ", least_slice_degree(1, 1 ,2 ,3, 2)) . ")";
    say "(" . join(", ", least_slice_degree(2, 1, 2, 1, 1)) . ")";
}

Sample Run


$ perl perl/ch-2.pl
(3, 3)
(1, 2, 1)
(2, 1, 2)
(1, 1)
(1, 2, 1, 1)

Notes

I view this problem in two main pieces:

  1. Compute the degree of any given array.

  2. Generate all contiguous slices of the given array and looking for a match on the criteria.

So, with that in mind we perform (1) in sub array_degree and then think of how we might best compute all those contiguous slices. Here we use a nested for loop. Since we also need to check to see if any of the computed slices have an array degree equal to the starting array we just do that inside the nested loop as well. This way we don't need to use any extra storage. Instead we just track the minimum length slice with matching array degree. Once the loops exit we return that minimum length slice.

References

Challenge 189

Separate release branch for App::Puppet::Environment::Updater

Perl Maven

Published by Gabor Szabo on Sunday 06 November 2022 11:30

The CPAN Digger provides a list of recently uploaded Perl modules and indicates, among several other things, if they have some kind of a Continuous Integration configured. That's how I arrived to App::Puppet::Environment::Updater and it took me quite some time till I noticed that it has GitHub Action configured, but not in the default branch.

TPRF to support FOSDEM Participation

Perl Foundation News

Published by Amber Deuel on Friday 04 November 2022 18:59

One of the goals TPRF would like to achieve, now that conferences are becoming increasingly available in person, is to spread awareness of current Perl and Raku projects. In support of this goal, TPRF will be issuing a limited number of mini grants of up to $300 to participants interested in holding Perl/Raku based talks in FOSDEM 2023 dev rooms. To apply for a mini grant please send a completed application to fosdem2023-grants@perlfoundation.org.

Please note that grants will be awarded only to those applicants whose talks are selected for FOSDEM. TPRF has made an intentional decision to not apply for a dev room, but to encourage talks to be given in other, non-language specific dev rooms instead. This will allow Perl and Raku to be shared with new audiences.

Maintaining Perl (Tony Cook) September 2022

Perl Foundation News

Published by alh on Tuesday 01 November 2022 09:08


Tony writes:

``` [Hours] [Activity] 2022/09/01 Thursday 1.60 #20204 write up some tests, start on implementation

2.43 #20204 more work on implementation

4.03

2022/09/05 Monday 0.47 github notifications 0.55 #20143 research, comment 0.55 #17831 follow-up 0.50 #20207 review discussion, comment

1.72 #20204 more work on implementation

3.79

2022/09/06 Tuesday 0.15 review Coverity scan results and ask khw about it 0.40 github notifications 0.60 #20189 write up a patch in branch 20189-setjmp, push for

CI

1.15

2022/09/07 Wednesday 0.17 #20189 look at CI failure, rebase, resubmit 1.62 #20255 review discussion, testing, research, comment 0.20 #20189 review CI results, make into PR 20264 0.83 #20204 work on following the symlink chain 3.10 #20204 testing, debugging, try to handle block devices too and fail, for now... (still need to do better symlink

chain tests)

5.92

2022/09/08 Thursday 0.23 review github notifications 2.03 #20204 review CI results, test/debug/fix mingw failure, time for more tests, debugging, #20130 cleanup 2.82 #20204 debug symlink following, debug strange result from

readlink, lrn2use readlink, fix issues, start full test

5.08

2022/09/12 Monday 1.05 github notifications 1.02 #20204 look into CI failures, try to reproduce locally 2.30 #20204 more try to reproduce, testing with DrMemory, repeated testing, restarting CI job (it mostly fails but occasionally succeeds)

0.65 #20128 review, research and briefly comment

5.02

2022/09/13 Tuesday 0.13 github notifications 0.95 #20204 work on debugging code, can’t get unmodified code to fail in CI 1.73 check if cygwin’s newlocale fix, fixed. Testing and

apparently it did fix, push for CI.

2.81

2022/09/14 Wednesday 0.05 cygwin: open PR 20299 0.67 #20204 try to get it to fail again, local test to check if we can distinguish broken link from a missing file (we can’t in the initial CreateFileA) 0.05 #20288 review and briefly comment

1.38 #20295 review logs and code, research and comment

2.15

2022/09/15 Thursday 1.27 github notifications 1.03 look at moving lexical sub setup to pad setup time - research 0.12 look at moving lexical sub setup to pad setup time - research 1.13 #20204 fix missing SKIP:, modify win32_readlink() a bit,

testing, push

3.55

2022/09/19 Monday 1.10 #20271 review comments, comment 1.20 #20310/#20180 review problem, proposed PR, comments 0.18 #20314 review and approve 0.08 #20315 review and approve 0.35 #20199 fix a minor test issue 0.27 #20199 re-word and expand commit message 0.43 #20316 review and comments 0.23 #20313 review and apply to blead 0.20 #20312 review and apply to blead 0.35 look into new build warnings, make pr 20318 0.25 #20317 review and approve

0.17 #20311 review and comment

4.81

2022/09/20 Tuesday 0.28 #20322 review and comment 0.70 #20311 follow-up 0.73 look at coverity reported defect, work up fix and push for CI

0.07 check CI results and make PR 20323

1.78

2022/09/21 Wednesday 0.63 github notifications 0.52 #20316 research, comment 1.27 #20307 testing, debugging 1.57 #20307 try to work out a test (existing tests don’t deal

with stdin)

3.99

2022/09/22 Thursday 0.50 github notifications 1.28 #20307 re-work a bit, testing 1.57 #20207 debug log4perl problem and make PR

https://github.com/mschilli/log4perl/pull/119

3.35

2022/09/26 Monday 0.17 github notifications 0.40 #20307 rebase, retest and make PR #20351 0.55 #20207 look into File::AptFetch failures 1.58 #20207 work out the problem (error rather than eof unlike the other modules the original patch had an effect on), and supply a patch to the module 0.22 #20350 review, research and comment 1.02 #20344 review, get confused by macros, research, comment 0.33 #19776 review, testing and comment 0.18 #20329 review 2.50 #16856 work through possible const fixes, find a

PL_splitstr bug and make PR #20352

6.95

2022/09/27 Tuesday 0.57 look at coverity reported defect and create PR 20353 0.22 github notifications

0.28 #16856

1.07

2022/09/28 Wednesday 0.25 review mailing list discussion 1.53 #20026 review, testing, comment 3.32 #20291 / #20346 debugging failing modules (mostly BenchmarkAnything::Schema)

1.33 #20291 / #20346 debugging failing modules

6.43

2022/09/29 Thursday 0.37 github notifications 0.13 #20344 review and approve 0.58 read through RFC discussion 0.38 #20355 review discussion and comment 0.77 #20354 debugging

0.60 feature-class - review code, discussions

2.83

2022/09/30 Friday 0.22 comment on “not exists” thread 0.33 look into current build warnings, only one, fix and push for CI 0.40 fix preprocessor conditions for build warnin fix, testing 0.45 #20354 debugging 2.08 #20354 debugging, testing 0.45 #20348 testing and comment

0.22 #20362 review discussion and T::HiRes Makefile.PL, comment

4.15

Which I calculate is 68.86 hours.

Approximately 32 tickets were reviewed or worked on, and 2 patches were applied. ```

Dancer2: Skeleton

Perl Maven

Published by Gabor Szabo on Tuesday 01 November 2022 08:30

Part of the Dancer2 video course.

List of new CPAN distributions – Oct 2022

Perlancar

Published by perlancar on Tuesday 01 November 2022 00:12

dist author first_version latest_version abstract
AI-ParticleSwarmOptimization-MCE STRZELEC 1.000 1.002 Particle Swarm Optimization (object oriented) with support for multi-core processing
AI-ParticleSwarmOptimization-Pmap STRZELEC 1.000 1.005 Particle Swarm Optimization (object oriented) with support for multi-core processing
Acme-CPANModules-WorkingWithCSV PERLANCAR 0.001 0.001 Working with CSV (comma-separated value) data in Perl
Acme-CPANModules-WorkingWithXLS PERLANCAR 0.001 0.001 Working with Excel formats (XLS, XLSX) or other spreadsheet formats like LibreOffice Calc (ODS)
Acme-Color-Rust PLICEASE 0.01 0.04 Color example class using Rust + FFI
Alien-Bazel WBRASWELL 0.01 0.01 Find or build bazel
Alien-CSFML SANKO v0.0.1 v0.0.7 Build and provide access to the official binding of SFML for the C language
Alien-ghostunnel PLICEASE 0.01 0.01 Find or install ghostunnel TLS proxy
App-SeismicUnixGui GLLORE v0.80.0 v0.80.0 A graphical user interface for Seismic Unix
App-UniqUtils PERLANCAR 0.001 0.001 Utilities related to unique lines and/or Unix uniq utility
App-WebSearchUtils PERLANCAR 0.001 0.001 CLI utilites related to searching with search engines
App-Yabsm NHUBBARD 3.11 3.14 a btrfs snapshot and backup management system
App-denomfind TULAMILI 0.250 0.313 下記ã®2個ã®ã‚³ãƒžãƒ³ãƒ‰ã¨ãã®æ©Ÿèƒ½ã‚’æä¾›ã™ã‚‹ã€‚
App-expskip TULAMILI 0.113 0.113 To see a large text file, 1st, 10th, 100th, 1000th .. lines are shown to see fewer lines. Output lines can be specifed by the options.
App-ipchgmon DAVIES 1.0.0 1.0.6 Watches for changes to public facing IP addresses
App-numero2bgc TULAMILI 0.021 0.021 Put colors on the background of each number from input text.
App-remotediff KALDOR 1.10 1.10 remote diff over rsync
ArrayData-Lingua-Word-EN-Medical-Glutanimate PERLANCAR 20220727.0.0 20220727.0.0 Medical word list (English)
Author-Daemon-Site-Ptr-Bond DAEMON 0.001 0.008 turns baubles into trinkets
BmltClient-ApiClient BMLT 0 0 a Moose role for the BMLT
Chemistry-File-OPTIMADE MERKYS 0.10 0.11 OPTIMADE reader
CryptoTron ZTENRETEP 0.01 0.08 Perl extension for blah blah blah
CryptoTron-GetAccountJsonStr ZTENRETEP 0.03 0.05 Perl extension for use with the Tron blockchain
CryptoTron-GetAccount_JsonStr ZTENRETEP 0.01 0.01 Perl extension for use with the Tron blockchain
CryptoTron-JsonHttp ZTENRETEP 0.01 0.02 Perl extension for use of with the Tron blockchain
CryptoTron-JsonRpc ZTENRETEP 0.04 0.10 Perl extension for use with the Tron blockchain
DB-SimpleKV YHPENG 0.01 0.04 Simple k/v interface to text configuration file
DBIx-Class-ResultClass-TrackColumns JJNAPIORK 0.001001 0.001001 Track changed columns original storage value
Dancer2-Plugin-RPC-RESTISH ABELTJE 2.01_02 2.02 Helper Test module that imports useful stuff.
Data-Combination DRCLAW v0.1.0 v0.1.0 Hash and Array element combination generator
Data-Commons-Image SKIM 0.01 0.05 Data object for Wikimedia Commons image.
Data-Image SKIM 0.01 0.02 Data object for image.
Data-Page-Nav LUCAS 0.01 0.02 Module for pages navigation
Data-Validate-OpenAPI MERKYS 0.1.0 0.1.0 Validate and untaint input parameters via OpenAPI schema
Devel-DieHandler-DumpDieArgs PERLANCAR 0.001 0.001 Dump content of die arguments
Device-Serial-SLuRM PEVANS 0.01 0.03 communicate the SLµRM protocol over a serial port
Exception-FFI-ErrorCode PLICEASE 0.01 0.03 Exception class based on integer error codes common in C code
FFI-Platypus-Lang-Zig PLICEASE 0.01 0.01 Documentation and tools for using Platypus with the Zig programming language
Filesys-Notify-Win32-ReadDirectoryChanges CORION 0.01 0.04 read/watch directory changes
Finance-Exchange DERIV 0.01 0.01 represents a financial stock exchange object.
Finance-MIFIR-CONCAT DERIV 0.01 0.01 provides CONCAT code generation out of client data according to MIFIR rules
Finance-YieldCurve DERIV 0.001 0.001 Handles interpolation on yield curves for interest rates and dividends
Format-JSON-Stream SHLOMIF 0.0.1 0.0.1 a stream of JSON data.
Future-Queue PEVANS 0.49 0.49 a FIFO queue of values that uses Futures
GFX-Tools KOBOLDWIZ v0.1.12 v0.1.12 several command line graphics tools
GFX-Tools-Buffer KOBOLDWIZ v0.1.8 v0.1.8 array code
Game-NURBS KOBOLDWIZ v0.1.1 v0.1.13 Perl extension for manipulating NURBS curves
Game-Ninja KOBOLDWIZ v0.1.4 v0.1.6 Perl extension for making ninja games, e.g. beat 'em ups like Double Dragon
Game-SDL KOBOLDWIZ v0.1.1 v0.1.1 Perl extension for making games with SDL(1)
Geo-TCX PATJOL 1.00 1.02 Parse and edit and TCX activity and course files from GPS training devices
Graphics-ColorNames-Pantone LICHTKIND 0.50 0.54 RGB values of Pantone colors
Graphics-Toolkit-Color LICHTKIND 0.99_0 1.02 color palette creation tool
IO-FD DRCLAW v0.1.0 v0.1.2 faster accept, socket, listen, read, write and friends with file descriptors, not handles
LWP-Protocol-clipboard PERLANCAR 0.001 0.001 Get/set clipboard content through LWP
Lilith VVELOX v0.0.1 v0.0.1 Work with Suricata/Sagan EVE logs and PostgreSQL.
Math-Numerical MATHIAS 0.01 0.05 Algorithms for numerical functions (root findings, etc.)
Memcached-RateLimit PLICEASE 0.01 0.06 Sliding window rate limiting with Memcached
Mojo-Log-Role-Format JHTHORSEN 0.01 0.02 Add sprintf logging to Mojo::Log
Mojo-ShareDir JHTHORSEN 0.01 0.01 Shared files and directories as Mojo::File objects
MooX-Tag-TO_HASH DJERIUS 0.01 0.03 Controlled translation of Moo objects into Hashes
MooseX-Types-Parameterized JJNAPIORK 0.09 0.09 Create your own Parameterizable Types for Moose
Net-Gemini JMATES 0.01 0.03 a small gemini client
Org-To-ANSIText PERLANCAR 0.001 0.001 Export Org document to text with ANSI color codes
Parse-H BOGDRO 0.10 0.11 A parser for C header files that calls the given subroutines when a symbol of a specified type is encountered.
Pg-SQL-PrettyPrinter DEPESZ 0.4 0.4 Pretty printer for SQL queries
REFECO-Blockchain-Contract-Solidity-ABI-Encoder REFECO 0.001 0.001 Contract Application Binary Interface argument encoder
RF-Component EWHEELER 1.001 1.001 Compose RF component circuits and calculate values from objects (L, C, ESR, etc).
Sah-Schemas-Data-Sah PERLANCAR 0.001 0.001 Sah schemas related to Data::Sah
Shell-Var-Reader VVELOX v0.0.1 v0.0.1 Runs a sh or bash script and returns the variables that have been set as well as their values.
SpecioX-XS TOBYINK 0.001 0.001 speed boost for Specio using Type::Tiny::XS
TableDataBundle-Business-ID-BPOM PERLANCAR 20221027.0.0 20221027.0.0 Collection of TableData:: modules related to Indonesia's BPOM (Badan Pengawas Obat dan Makanan, or the National Agency or Drug and Food Control)
Tags-HTML-Image-Grid SKIM 0.01 0.01 Tags helper class for image grid.
Test-Spy BRTASTIC 0.001 0.003 build mocked interfaces and examine call data easily
Test2-Tools-Rustfmt PLICEASE 0.01 0.03 Test that bundled Rust code is formatted according to Rust style guidelines
WebFetch-RSS IKLUFT 0.3.0 0.3.0 compatibility mode to access WebFetch::RSS under its previous name
WebService-MyJSONs POLETTIX 0.001 0.001 Perl SDK to consume the MyJSONs web service
Wikibase-API SKIM 0.01 0.02 Wikibase API class.
Wikibase-Datatype-Print SKIM 0.01 0.01 Wikibase data types print.
WordList-EN-Medical-Glutanimate PERLANCAR 20220727.0.0 20220727.0.0 Medical word list (English)
YAML-yq-Helper VVELOX 0.01 v0.1.0 Wrapper for yq for various common tasks so YAML files can be manipulated in a manner to preserve comments and version header.
pEFL PERLMAX 0.7 0.7 Perl bindings for the Enlightenment Foundation Libraries
sms-send-in-nicsms INDRADG 1.00 1.00 Regional context SMS::Send driver to send messages via NIC's SMS Gateway ( https://smsgw.sms.gov.in )

Stats

Number of new CPAN distributions this period: 82

Number of authors releasing new CPAN distributions this period: 42

Authors by number of new CPAN distributions this period:

No Author Distributions
1 PERLANCAR 11
2 PLICEASE 6
3 SKIM 5
4 KOBOLDWIZ 5
5 ZTENRETEP 5
6 DERIV 3
7 TULAMILI 3
8 VVELOX 3
9 PEVANS 2
10 JJNAPIORK 2
11 DRCLAW 2
12 LICHTKIND 2
13 MERKYS 2
14 JHTHORSEN 2
15 STRZELEC 2
16 DAVIES 1
17 MATHIAS 1
18 TOBYINK 1
19 SHLOMIF 1
20 SANKO 1
21 BMLT 1
22 DJERIUS 1
23 YHPENG 1
24 NHUBBARD 1
25 GLLORE 1
26 CORION 1
27 LUCAS 1
28 KALDOR 1
29 WBRASWELL 1
30 DEPESZ 1
31 ABELTJE 1
32 DAEMON 1
33 INDRADG 1
34 BOGDRO 1
35 POLETTIX 1
36 BRTASTIC 1
37 PATJOL 1
38 REFECO 1
39 EWHEELER 1
40 PERLMAX 1
41 IKLUFT 1
42 JMATES 1

#588 - TRPF, what’s in a name?

Perl Weekly

Published on Monday 31 October 2022 10:00

Hi there,

Few days ago, I came across the official announcement with regard to the name change. I saw mixed reaction on Facebook groups for Perl fans.

So what is my (personal) view on the topic?

I understand name change is not an easy decision, it must have been going on for days if not months. My view is to keep Perl and Raku separate. Having said, I like the name change at least it is better than what it was before. Since we are talking about name change, my suggestion is why not change it back to "Yet Another Society (YAS)" as it was before if I am not mistaken. Then have two separate board under its wings i.e. "The Perl Foundation (TPF)" and "The Raku Foundation (TRF)". Also allow the individual board to decide the path they want to follow. This way we don't cross each others path and stay friendly. It sounds simple, isn't it? Not sure if it is easy to implement.

This name change brought back memories when I decided to change the name Perl Weekly Challenge. As you all know, right from day one, we decided to have both Perl and Raku as the main contributing languages. A few months later after the launch, I found the name not reflecting what actual happens on the ground. But I already had the domain perlweeklychallenge.org registered and all the actions were happening under the same domain. After discussing with some of my close friends, I decided to change it to a new domain, theweeklychallenge.org. To me, it makes more sense as we gradually opened up to many more languages, 92 to be precise as of today. It wasn't an easy decision for me to change the name and move everything to new domain. Gabor Szabo helped me with the domain switch and patch the old domain to divert trafic to the new domain. Everthing seems to be stable now but I still refer the team as Team PWC as it is very close to my heart.

How was your experience with Hacktoberfest 2022?

My contributions this time didn't meet the minimum requirement of the event. Although I submitted 4 Pull Requests and all of them were accepted and merged by the author but only 2 PR were counted as the other two PR were part of non-participating repositories. Having said, I am happy many of the Team PWC members got more than 4 Pull Requests this time. Congratulations Team PWC.

If you want to have fun and share your knowledge every week with others then please do join us here on The Weekly Challenge. Also please don't forget to checkout the experience of our champions.

Enjoy rest of the newsletter.

Pairs Divided by Zero

RabbitFarm Perl

Published on Sunday 30 October 2022 19:24

The examples used here are from the weekly challenge problem statement and demonstrate the working solution.

Part 1

You are given list of integers @list of size $n and divisor $k. Write a script to find out count of pairs in the given list that satisfies a set of rules.

Solution


use v5.36;
use strict;
use warnings;

sub divisible_pairs{
    my($numbers, $k) = @_;
    my @pairs;
    for my $i (0 .. @{$numbers} - 1){
        for my $j ($i + 1 .. @{$numbers} - 1){
            push @pairs, [$i, $j] if(($numbers->[$i] + $numbers->[$j]) % $k == 0);
        }
    }
    return @pairs;
}

MAIN:{
    my @pairs;
    @pairs = divisible_pairs([4, 5, 1, 6], 2);
    print @pairs . "\n";
    @pairs = divisible_pairs([1, 2, 3, 4], 2);
    print @pairs . "\n";
    @pairs = divisible_pairs([1, 3, 4, 5], 3);
    print @pairs . "\n";
    @pairs = divisible_pairs([5, 1, 2, 3], 4);
    print @pairs . "\n";
    @pairs = divisible_pairs([7, 2, 4, 5], 4);
    print @pairs . "\n";
}

Sample Run


$ perl perl/ch-1.pl
2
2
2
2
1

Notes

The rules, if not clear from the above code are : the pair (i, j) is eligible if and only if

  • 0 <= i < j < len(list)

  • list[i] + list[j] is divisible by k

While certainly possible to develop a more complicated looking solution using map and grep I found myself going with nested for loops. The construction of the loop indices takes care of the first condition and the second is straightforward.

Part 2

You are given two positive integers $x and $y. Write a script to find out the number of operations needed to make both ZERO.

Solution


use v5.36;
use strict;
use warnings;

sub count_zero{
    my($x, $y) = @_;
    my $count = 0;
    {
        my $x_original = $x;
        $x = $x - $y if $x >= $y;
        $y = $y - $x_original if $y >= $x_original;
        $count++;
        redo unless $x == 0 && $y == 0;
    }
    return $count;
}

MAIN:{
    say count_zero(5, 4);
    say count_zero(4, 6);
    say count_zero(2, 5);
    say count_zero(3, 1);
    say count_zero(7, 4);
}

Sample Run


$ perl perl/ch-2.pl
5
3
4
3
5

Notes

The operations are dictated by these rules:

  • $x = $x - $y if $x >= $y

or

  • $y = $y - $x if $y >= $x (using the original value of $x)

This problem seemed somewhat confusingly stated at first. I had to work through the first given example by hand to make sure I really understood what was going on.

After a little analysis I realized this is not as confusing as I first thought. The main problem I ran into was not properly accounting for the changed value of $x using a temporary variable $x_original. If you see my Prolog Solutions for this problem you can see how Prolog's immutable variables obviate this issue!

References

Challenge 188