I've been doing the Perl Weekly Challenges. This one dealt with months and word-wrapping.

The first one was to find months with 5 weekends, specified as 5 sequences of Friday, Saturday and Sunday all falling in the same month. (Actually the specification didn't say "sequences", it just said "5 Friday, 5 Saturday and 5 Sunday"; if you're allowed to start with Saturday and Sunday, and end with a Friday, that'll end up being rather more months.)

This is susceptible to a significant optimisation: it can only happen in a 31-day month, and only if the first day of that month is a Friday. And it will happen in every such month.

use Time::Local; use POSIX qw(strftime); foreach my $y (1900..2019) {

Pick just the 31-day months.

foreach my $m (1,3,5,7,8,10,12) {

I don't actually care about the unixtime, so I'll throw it away. But the output of gmtime (localtime's neglected sibling) is what I need later for strftime.

my @d=gmtime(timegm(0,0,0,1,$m-1,$y));

If the first day of the month is a Friday… (with the looser specification, Friday, Saturday or Sunday, so 5, 6 and 0):

if ($d[6]==5) { print strftime('%B %Y',@d),"

"; } } }

The other one is a paragraph wrapper. Obviously we already have Text::Wrap in CPAN, and indeed Text::LineFold.

use Getopt::Std; my %o=(w => 72); getopts('w:',\%o); my $s=$o{w}; my @w; while (<>) { chomp;

I've extended the specification a bit. If we get a blank line, count that as end of paragraph, and dump any remaining words before it.

if ($_ eq '') { if (@w) { print join(' ',@w),"

"; @w=(); $s=$o{w}; } print "

";

Otherwise, it's the standard greedy algorithm: if the word will fit, fit it, otherwise dump the line buffer and start a new one.

} else { foreach my $w (split ' ',$_) { my $lw=length($w); if ($lw+1 > $s) { print join(' ',@w),"

"; @w=($w); $s=$o{w}-$lw; } else { push @w,$w; $s-=($lw+1); } } } }

If there's something left at the end, dump that too.

if (@w) { print join(' ',@w),"

"; }

In production I'd use a function for the buffer dump, because otherwise I'd have three separate places to change the code when I needed to modify it.

I also wrote my first Perl6 programs, to do the same tasks, with much help from the Perl 5 to 6 in a nutshell guide to get me through the various syntax changes. The first challenge becomes simpler, because there's a built-in Date type, though it's not immediately obvious how to access strftime natively (do I really need to pull in DateTime::Format?) so the output is numeric for now:

for 1990..2019 -> $y { for 1,3,5,7,8,10,12 -> $m { if Date.new($y,$m,1).day-of-week == 5 { say "$m $y"; } } }

The second looks very similar to the way it was before, basically just with syntax changes, though command-line options are also in external modules and I'm trying to keep this basic.