Perl Weekly Challenge 181: Sentence Order and Hot day
These are some answers to the Week 181 of the Perl Weekly Challenge organized by Mohammad S. Anwar.
Spoiler Alert: This weekly challenge deadline is due in a few of days from now (on Sept. 11, 2022 at 23:59). This blog post offers some solutions to this challenge, please don’t read on if you intend to complete the challenge on your own.
Task 1: Sentence Order
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.
Splitting the paragraph into sentences and then splitting the sentences into words and reordering them in alphabetic order is order is the easiest part, outputting the result in lines with approximately equal lengths is slightly more difficult.
Sentence Order in Raku
We split the input into sentences, and then split each sentence into words, reorder the words into the alphabetic order of their lower-case equivalent, and store each word in the @words
array. Once this is completed, we put each word in turn into a string ($line
). Once the string reaches a predefined length, we print out the string and continue with a new empty string.
constant $MAX = 55;
my $paragraph = q:to/END/;
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.
END
my @words;
for $paragraph.split(/'.'/) -> $sentence {
next if $sentence ~~ /^\s*$/; # remove any empty line
@words.append(sort { $_.lc }, $sentence.split(/\s/));
@words[*-1] ~= ".";
}
my $line = "";
for @words -> $w {
$line ~= "$w ";
if $line.chars > $MAX {
say $line;
$line = "";
}
}
say $line;
This program displays the following output:
$ raku ./sentence-order.raku
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.
Sentence Order in Perl
We do essentially the same as in Raku: we split the input paragraph into sentences, and then split each sentence into words, reorder the words into the alphabetic order of their lower-case equivalent, and store each word in the @words
array. Once this is completed, we put each word and a space in turn into a string ($line
). Once the string reaches a predefined length, we print out the string and continue with a new empty string.
use strict;
use warnings;
use feature qw/say/;
use constant MAX => 55;
my $paragraph = <<'END';
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.
END
my @words;
for my $sentence (split /\./, $paragraph) {
next if $sentence =~ /^\s*$/; # remove any empty line
push @words, (sort { lc $a cmp lc $b } split /\s+/, $sentence);
$words[-1] .= ".";
}
my $line = "";
for my $w (@words) {
$line .= "$w ";
if (length $line > MAX) {
say $line;
$line = "";
}
}
say $line;
This program displays the following output:
$ perl ./sentence-order.pl
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.
Task 2: Hot Day
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
For our tests, we’ll use the temperature.txt
file with the data provided above in the task specification.
Hot Day in Raku
We read the input file and store the data into an array of arrays, @daily-temps
. We then sort the array in ascending dates and output those where the temperature is more that the previous day temperature.
my @daily-temps;
for './temperature.txt'.IO.lines -> $line {
push @daily-temps, split /','\s/, $line;
}
my $temp = Inf;
for @daily-temps.sort({$^a leg $^b}) -> @record {
say @record[0] if @record[1] > $temp;
$temp = @record[1];
}
This program displays the following output:
$ raku ./hot-day.raku
2022-08-02
2022-08-05
2022-08-06
2022-08-08
2022-08-10
Hot Day in Perl
Again, this a simple port to Perl of the Raku program above. Please refer to the previous section if you need any explanations.
use strict;
use warnings;
use feature qw/say/;
my @daily_temps;
my $file_in = "./temperature.txt";
open my $IN, "<", $file_in or die "Cannot open $file_in $!";
while (my $line = <$IN>) {
chomp $line;
push @daily_temps, [ split /,\s/, $line ];
}
my $temp = 1e9;
for my $record (sort {$a->[0] cmp $b->[0]} @daily_temps) {
say $record->[0] if $record->[1] > $temp;
$temp = $record->[1];
}
This program displays the following output:
$ perl hot-day.pl
2022-08-02
2022-08-05
2022-08-06
2022-08-08
2022-08-10
Hot Day in Awk
It is possible to sort an array in awk, but, in the Unix (and awk) philosophy, it is better to use the Unix sort
function to sort the input before it is passed through a pipe to the awk program, so that we don’t even need to use an array and can process each input line in turn and print the dates that satisfy the temperature condition. This leads to a very short and concise program.
# Run as: sort temperature.txt | awk -f hot-day.awk
BEGIN {
temp = 1000
FS = ", "
}
{
if ($2 > temp) {
print $1
}
temp = $1
}
Output:
$ sort ./temperature.txt | awk -f ./hot-day.awk
2022-08-02
2022-08-05
2022-08-06
2022-08-08
2022-08-10
Hot Day in Julia
fh = open("./temperature.txt", "r")
lines = readlines(fh)
sorted_lines = sort(lines)
temp = 100000
for line in sorted_lines
(date, temp_str) = split(line, ", ")
curr_temp = parse(Int64, temp_str)
if curr_temp > temp
println(date)
end
global temp = curr_temp
end
Output:
$ julia ./hot-day.jl
2022-08-02
2022-08-05
2022-08-06
2022-08-08
2022-08-10
Hot Day in Python
lines = []
file_in = "./temperature.txt"
fh = open(file_in, "r")
for line in fh:
line.rstrip()
lines.append(line)
lines.sort();
temp = 1e9
for line in lines:
fields = line.split(',')
cur_temp = int(fields[1].strip())
if cur_temp > temp:
print(fields[0])
temp = cur_temp
Output:
$ python3 ./hot-day.py
2022-08-02
2022-08-05
2022-08-06
2022-08-08
2022-08-10
Wrapping up
The next week Perl Weekly Challenge will start soon. If you want to participate in this challenge, please check https://perlweeklychallenge.org/ and make sure you answer the challenge before 23:59 BST (British summer time) on September 18, 2022. And, please, also spread the word about the Perl Weekly Challenge if you can.
Leave a comment