Perl Weekly Challenge 181.
My solutions (task 1 and task 2 ) to the The Weekly Challenge - 181.
Task 1: Sentence Order
Submitted by: Mohammad S Anwar
You are given a paragraph.
Write a script to order each sentence alphanumerically and
print the whole paragraph.
Example
Input:
All he could think about was how it would all end. There was
still a bit of uncertainty in the equation, but the basics
were there for anyone to see. No matter how much he tried to
see the positive, it wasn't anywhere to be seen. The end was
coming and it wasn't going to be pretty.
Ouput:
about All all could end he how it think was would. a anyone
basics bit but equation, for in of see still the the There
there to uncertainty was were. anywhere be he how it matter
much No positive, see seen the to to tried wasn't. and be
coming end going it pretty The to was wasn't.
To solve the problem I read the whole file, separate into sentences by splitting on ‘.’, split on space, order alphanumerically and join, sticking in the end-of-sentence ‘.’. This fits comfortably into a oneliner.
perl -n -000 -E '
chomp; say ((join " ", sort {fc $a cmp fc $b} split " ").". ") for split /\./; say "";
' <<EOF |fmt
All he could think about was how it would all end. There was
still a bit of uncertainty in the equation, but the basics
were there for anyone to see. No matter how much he tried to
see the positive, it wasn't anywhere to be seen. The end was
coming and it wasn't going to be pretty.
It all started with the computer. Had he known what was to
follow, he would have never logged on that day. But the truth
was there was no way to know what was about to happen. So Dave
pressed the start button, the computer booted up, the screen
came alive, and everything Dave knew to be true no longer was.
EOF
(2nd paragraph taken from here).
I used the -000 flag to split the input into paragraphs, so
that I can arrange longer texts, and -n
to implicitly loop over them. Each paragraph is split into sentences,
reordered normalizing with the fc
function before comparing strings, so
that ‘Z’ doesn’t come before ‘a’.
The results are:
about All all could end he how it think was would. a anyone basics bit
but equation, for in of see still the the There there to uncertainty
was were. anywhere be he how it matter much No positive, see seen the
to to tried wasn't. and be coming end going it pretty The to was wasn't.
all computer It started the with. day follow, Had have he he known
logged never on that to was what would. about But happen know no the
there to to truth was was was way what. alive, and be booted button,
came computer Dave Dave everything knew longer no pressed screen So
start the the the to true up, was.
The full code is
1 # Perl weekly challenge 181
2 # Task 1: Sentence order
3 #
4 # See https://wlmb.github.io/2022/09/05/PWC181/#task-1-sentence-order
5 use v5.36;
6 use Text::Wrap qw(wrap $columns $break);
7 $columns=62; $break=qr/\s/;
8 local $/ = ""; # paragraph mode
9 while(<>){ # for each paragraph
10 chomp; # remove trailing newlines
11 my @output;
12 foreach(split /\./){ # For each sentence. Assume ends in "."
13 my @words = split " "; # Separate into words. Assume a space even after punctuation.
14 my @sorted_words = sort {fc $a cmp fc $b} @words;
15 push @output, join(" ", @sorted_words) . ". "; # join words and add ending "."
16 }
17 say wrap('', '', (join " ", @output), "\n");
18 }
Example:
./ch-1.pl <<EOF
All he could think about was how it would all end. There was
still a bit of uncertainty in the equation, but the basics
were there for anyone to see. No matter how much he tried to
see the positive, it wasn't anywhere to be seen. The end was
coming and it wasn't going to be pretty.
It all started with the computer. Had he known what was to
follow, he would have never logged on that day. But the truth
was there was no way to know what was about to happen. So Dave
pressed the start button, the computer booted up, the screen
came alive, and everything Dave knew to be true no longer was.
EOF
Results:
about All all could end he how it think was would. a anyone
basics bit but equation, for in of see still the the There
there to uncertainty was were. anywhere be he how it matter
much No positive, see seen the to to tried wasn't. and be
coming end going it pretty The to was wasn't.
all computer It started the with. day follow, Had have he he
known logged never on that to was what would. about But
happen know no the there to to truth was was was way what.
alive, and be booted button, came computer Dave Dave
everything knew longer no pressed screen So start the the the
to true up, was.
Task 2: Hot Day
Submitted by: Mohammad S Anwar
You are given file with daily temperature record in random
order.
Write a script to find out days hotter than previous day.
Example
Input File: (temperature.txt)
2022-08-01, 20
2022-08-09, 10
2022-08-03, 19
2022-08-06, 24
2022-08-05, 22
2022-08-10, 28
2022-08-07, 20
2022-08-04, 18
2022-08-08, 21
2022-08-02, 25
Output:
2022-08-02
2022-08-05
2022-08-06
2022-08-08
2022-08-10
I can read the input into a hash, sort the keys and then compare temperatures. Assuming there are no holes in the table the problem may be solved with a 3-liner.
perl -MList::MoreUtils=pairwise -n -E '
BEGIN{sub dc($p, $q){@p=split "-",$p; @q=split "-",$q;@c=pairwise {$a<=>$b} @p,@q;
for(0..2){return $c[$_] if $c[$_]} 0}} chomp; ($d,$t)=split ", "; $t{$d}=$t;
END {@d=sort {dc($a, $b)} keys %t; for(1..@d-1){say $d[$_] if $t{$d[$_]}>$t{$d[$_-1]}}}
' <<EOF
2022-08-01, 20
2022-08-09, 10
2022-08-03, 19
2022-08-06, 24
2022-08-05, 22
2022-08-10, 28
2022-08-07, 20
2022-08-04, 18
2022-08-08, 21
2022-08-02, 25
EOF
Results:
2022-08-02
2022-08-05
2022-08-06
2022-08-08
2022-08-10
I test it with dates that cross month and year boundaries
perl -MList::MoreUtils=pairwise -n -E '
BEGIN{sub dc($p, $q){@p=split "-",$p; @q=split "-",$q;@c=pairwise {$a<=>$b} @p,@q;
for(0..2){return $c[$_] if $c[$_]} 0}} chomp; ($d,$t)=split ", "; $t{$d}=$t;
END {@d=sort {dc($a, $b)} keys %t; for(1..@d-1){say $d[$_] if $t{$d[$_]}>$t{$d[$_-1]}}}
' <<EOF
2022-12-31, 20
2023-01-08, 10
2023-01-02, 19
2023-01-05, 24
2023-01-04, 22
2023-01-09, 28
2023-01-06, 20
2023-01-03, 18
2023-01-07, 21
2023-01-01, 25
EOF
Results:
2023-01-01
2023-01-04
2023-01-05
2023-01-07
2023-01-09
For the full code I use the DateTime
and Date::Parse
modules to compare dates and add some checks for invalid and
missing dates.
1 # Perl weekly challenge 181
2 # Task 2: Hot day
3 #
4 # See https://wlmb.github.io/2022/09/05/PWC181/#task-2-hot-day
5 use v5.36;
6 use List::MoreUtils qw(pairwise);
7 use Date::Parse;
8 use DateTime;
9
10 my %temps;
11 while(<>){ # Input data from standard input in format YYYY-MM-DD, Temp
12 chomp;
13 my ($date, $temp)=split ", ";
14 $temps{$date}=$temp;
15 }
16 my %datetimes;
17 for(keys %temps){ # check valid dates
18 die "Wrong date $_" unless defined (my $time=str2time($_));
19 $datetimes{$_}=DateTime->from_epoch($time); # Build DateTime object
20 }
21 my @sorted=sort {DateTime->compare($datetimes{$a}, $datetimes{$b})} keys %temps;
22 for(1..@sorted-1){
23 die "Dates not consecutive"
24 unless $datetimes{$sorted[$_]}->delta_days($datetimes{$sorted[$_-1]})->days==1;
25 say $sorted[$_] if $temps{$sorted[$_]}>$temps{$sorted[$_-1]}
26 }
27
28
29
Example:
./ch-2.pl <<EOF
2022-08-01, 20
2022-08-09, 10
2022-08-03, 19
2022-08-06, 24
2022-08-05, 22
2022-08-10, 28
2022-08-07, 20
2022-08-04, 18
2022-08-08, 21
2022-08-02, 25
EOF
Results:
2022-08-02
2022-08-05
2022-08-06
2022-08-08
2022-08-10