This is my response to The Weekly Challenge #181.
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.
I think we can safely assume that the indentation is for presentation purposes only, and not to be taken literally. If we also assume that the newlines are equally unimportant, we can get away with a very compact program.
File: sentence-order
#! /usr/bin/env raku
unit sub MAIN ($file where $file.IO.f && $file.IO.r = "paragraph.txt",
:v(:$verbose));
my @sentences = (slurp $file).split("."); # [1]
say ":sentences: { @sentences.raku}" if $verbose;
say @sentences>>.words>>.sort({ $^a.lc cmp $^b.lc })>>.join(" ").join(". ");
# ## 2 ############## # 3 ######################## # 4 ####### # 5 #######
[1]
Read the file (with slurp
), and split into an array on
.
(a period). The period is removed.
See
docs.raku.org/routine/slurp
for more information about siurp
.
See
docs.raku.org/routine/split
for more information about split
.
[2] Split each of the sentences - as we used >>.
instead
of the normal .
(a period) - into words (with word
).
See
docs.raku.org/routine/words
for more information about words
.
[3] Sort each of those lists (of words from each sentence), using the custom sort code specified. Note the placeholder variables.
[4] Join each list, now sorted, into a string with a single space between the words.
[5] And finally, join the strings (one for each sentence) with a period and a trailing space.
Verbose mode shows what is going on, partially. (I have added the colouring.)
$ ./sentence-order -v
:sentences: ["All he could think about was how it would all end", " There \
was\nstill a bit of uncertainty in the equation, but the basics\nwere \
there for anyone to see", " No matter how much he tried to\nsee the \
positive, it wasn't anywhere to be seen", " The end was\ncoming \
and it wasn't going to be pretty", "\n"]
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.
We got five sentences. The leading spaces and embedded newlines are removed by words
.
The last one is reduced to an empty list, and the join
beytween the lists gives us
a trailing newline.
Without verbose mode:
$ ./sentence-order
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.
Looking good.
As a oneliner(ish):
File: sentence-order-onelineish
#! /usr/bin/env raku
unit sub MAIN ($file where $file.IO.f && $file.IO.r = "paragraph.txt");
(slurp $file).split(".")>>.words>>.sort({ $^a.lc cmp $^b.lc })>>.join(" ") \
.join(". ").say;
Or as a true oneliner (if you ignore the crash-bang line), ditching the error handling:
File: sentence-order-oneliner
#! /usr/bin/env raku
(slurp @*ARGS[0] || "paragraph.txt").split(".")>>.words \
>>.sort({ $^a.lc cmp $^b.lc })>>.join(" ").join(". ").say;
#! /usr/bin/env perl
use strict;
use warnings;
use feature 'say';
use Getopt::Long;
use File::Slurp;
my $verbose = 0;
GetOptions("verbose" => \$verbose);
my $file = shift(@ARGV) || "paragraph.txt";
my $content = read_file($file);
my @sentences = split(/\./, $content);
say ":sentences: " . join("\n", map { '"' . $_ . '"' } @sentences)
if $verbose;
my @result;
for my $sentence (@sentences)
{
my @words = split(/\s+/, $sentence);
push(@result, join(" ", sort { lc $a cmp lc $b } @words));
}
say join(". ", @result);
Running it gives the same result as the Raku version:
$ ./sentence-order-perl
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.
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
File: hot-day
#! /usr/bin/env raku
unit sub MAIN ($file where $file.IO.f && $file.IO.r = "temperature.txt",
:v(:$verbose));
my @rows = $file.IO.lines; # [1]
my %measures; # [2]
for @rows -> $row # [3]
{
my ($date, $temperature) = $row.split(", "); # [3a]
%measures{$date} = $temperature; # [3b]
}
for sort keys %measures -> $date # [4]
{
my $prev = $date.Date.pred; # [5]
my $temp = %measures{$date}; # [6]
my $prev_temp = %measures{$prev}; # [7]
print ": Checking Date: $date (temp: $temp)" if $verbose;
if $prev_temp.defined # [8]
{
say " - $prev (temp $prev_temp)" if $verbose;
say $date if $temp > $prev_temp; # [8a]
}
elsif $verbose
{
say "";
}
}
[1] Read the daily temperature file.
[2] We ar going to store the temperatures here, with the date as key.
[3] For each row, split the row into the date and the temperature [3a], and add them to the hash [3b] (from [2]).
[4] For each date (sorted with the oldest first).
[5] Get the previuos date, using a Date
object and the
previous
method.
See
docs.raku.org/type/Date for more information about the Date
class.
[6] Get the temperature for the current day.
[7] and the previous one.
[8] If the previous day's temperature is defined, print the date if the current temperature is higher than this one [8a].
Running it:
$ ./hot-day
2022-08-02
2022-08-05
2022-08-06
2022-08-08
2022-08-10
Looking good.
With verbose mode:
$ ./hot-day -v
: Checking Date: 2022-08-01 (temp: 20)
: Checking Date: 2022-08-02 (temp: 25) - 2022-08-01 (temp 20)
2022-08-02
: Checking Date: 2022-08-03 (temp: 19) - 2022-08-02 (temp 25)
: Checking Date: 2022-08-04 (temp: 18) - 2022-08-03 (temp 19)
: Checking Date: 2022-08-05 (temp: 22) - 2022-08-04 (temp 18)
2022-08-05
: Checking Date: 2022-08-06 (temp: 24) - 2022-08-05 (temp 22)
2022-08-06
: Checking Date: 2022-08-07 (temp: 20) - 2022-08-06 (temp 24)
: Checking Date: 2022-08-08 (temp: 21) - 2022-08-07 (temp 20)
2022-08-08
: Checking Date: 2022-08-09 (temp: 10) - 2022-08-08 (temp 21)
: Checking Date: 2022-08-10 (temp: 28) - 2022-08-09 (temp 10)
2022-08-10
#! /usr/bin/env perl
use strict;
use warnings;
use feature 'say';
use Getopt::Long;
use File::Slurp;
use Date::Calc; # [1]
my $verbose = 0;
GetOptions("verbose" => \$verbose);
my $file = shift(@ARGV) || "temperature.txt";
my @rows = read_file($file, chomp => 1);
my %measures;
for my $row (@rows)
{
my ($date, $temperature) = split(", ", $row);
$measures{$date} = $temperature;
}
for my $date (sort keys %measures)
{
my $prev = sprintf("%04d-%02d-%02d",
Date::Calc::Add_Delta_Days(split("-", $date), -1));
my $temp = $measures{$date};
my $prev_temp = $measures{$prev};
print ": Checking Date: $date (temp: $temp)" if $verbose;
if (defined $prev_temp)
{
say " - $prev (temp $prev_temp)" if $verbose;
say $date if $temp > $prev_temp;
}
elsif ($verbose)
{
say "";
}
}
[1] The «Date::Calc» module does not give us Date objects, but working on string dates is ok.
Running it gives the same result as the Raku version:
$ ./hot-day-perl
2022-08-02
2022-08-05
2022-08-06
2022-08-08
2022-08-10
And that's it.