aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad S Anwar <Mohammad.Anwar@yahoo.com>2019-06-09 09:25:14 +0100
committerGitHub <noreply@github.com>2019-06-09 09:25:14 +0100
commit3602f68f35bd8bc9b3632e7bd38225e3dbf66476 (patch)
treea5fc00f077350996ba77b3ade815cd6a82395203
parent0a25e39af9e85466956da97808fe589703da2cf0 (diff)
parent9232205b74dbb9c02dec10e8dcd50098623057c3 (diff)
downloadperlweeklychallenge-club-3602f68f35bd8bc9b3632e7bd38225e3dbf66476.tar.gz
perlweeklychallenge-club-3602f68f35bd8bc9b3632e7bd38225e3dbf66476.tar.bz2
perlweeklychallenge-club-3602f68f35bd8bc9b3632e7bd38225e3dbf66476.zip
Merge pull request #232 from PerlMonk-Athanasius/new-branch
On branch new-branch
-rw-r--r--challenge-011/athanasius/perl5/ch-1.pl75
-rw-r--r--challenge-011/athanasius/perl5/ch-2.pl78
-rw-r--r--challenge-011/athanasius/perl5/ch-3.pl327
3 files changed, 480 insertions, 0 deletions
diff --git a/challenge-011/athanasius/perl5/ch-1.pl b/challenge-011/athanasius/perl5/ch-1.pl
new file mode 100644
index 0000000000..0d502980a0
--- /dev/null
+++ b/challenge-011/athanasius/perl5/ch-1.pl
@@ -0,0 +1,75 @@
+#!perl
+
+################################################################################
+=comment
+
+Perl Weekly Challenge 011
+=========================
+
+Challenge #1
+------------
+
+Write a script that computes the equal point in the Fahrenheit and Celsius
+scales, knowing that the freezing point of water is 32 °F and 0 °C, and that the
+boiling point of water is 212 °F and 100 °C. This challenge was proposed by
+*Laurent Rosenfeld*.
+
+=cut
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2019 Perlmonk Athanasius #
+#--------------------------------------#
+
+use strict;
+use warnings;
+use utf8;
+use Const::Fast;
+
+const my $FAHRENHEIT_FREEZING => 32;
+const my $FAHRENHEIT_BOILING => 212;
+const my $CELSIUS_FREEZING => 0;
+const my $CELSIUS_BOILING => 100;
+
+$| = 1;
+
+MAIN:
+{
+ # At the equal point, degrees Fahrenheit (f) equal degrees Celsius, so
+ # f = f × ((212 - 32) / 100) + 32
+ # => f × (1 - 9/5) = 32
+ # => f = 32 / -4/5
+ # = -40.
+
+ my $equal = $FAHRENHEIT_FREEZING /
+ (1 - (($FAHRENHEIT_BOILING - $FAHRENHEIT_FREEZING) / $CELSIUS_BOILING));
+
+ printf "\nThe equal point is %3.1f°\n", $equal;
+ printf "This is %s by conversion from Celsius to Fahrenheit\n",
+ $equal == c2f($equal) ? 'confirmed' : 'refuted';
+ printf "This is %s by conversion from Fahrenheit to Celsius\n",
+ $equal == f2c($equal) ? 'confirmed' : 'refuted';
+}
+
+# Convert Celsius to Fahrenheit
+
+sub c2f
+{
+ my ($degrees_celsius) = @_;
+
+ return ($degrees_celsius *
+ (($FAHRENHEIT_BOILING - $FAHRENHEIT_FREEZING) / $CELSIUS_BOILING)) +
+ $FAHRENHEIT_FREEZING
+}
+
+# Convert Fahrenheit to Celsius
+
+sub f2c
+{
+ my ($degrees_fahrenheit) = @_;
+
+ return ($degrees_fahrenheit - $FAHRENHEIT_FREEZING) *
+ ($CELSIUS_BOILING / ($FAHRENHEIT_BOILING - $FAHRENHEIT_FREEZING));
+}
+
+################################################################################
diff --git a/challenge-011/athanasius/perl5/ch-2.pl b/challenge-011/athanasius/perl5/ch-2.pl
new file mode 100644
index 0000000000..7f6a6c727e
--- /dev/null
+++ b/challenge-011/athanasius/perl5/ch-2.pl
@@ -0,0 +1,78 @@
+#!perl
+
+################################################################################
+=comment
+
+Perl Weekly Challenge 011
+=========================
+
+Challenge #2
+------------
+
+Write a script to create an Indentity Matrix for the given size. For example, if
+the size is 4, then create Identity Matrix 4x4. For more information about
+*Indentity Matrix*, please read the
+[ https://en.wikipedia.org/wiki/Identity_matrix |wiki] page.
+
+=cut
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2019 Perlmonk Athanasius #
+#--------------------------------------#
+
+use strict;
+use warnings;
+use Const::Fast;
+use Scalar::Util::Numeric qw( isint );
+
+const my $DEFAULT_SIZE => 4;
+const my $MAX_SIZE => 39; # Adjust for the target console
+
+$| = 1;
+
+MAIN:
+{
+ my $size = $ARGV[0] // $DEFAULT_SIZE;
+ my $matrix = identity_matrix($size);
+
+ print "\nIdentity Matrix of size $size:\n";
+ print_matrix($matrix);
+}
+
+sub identity_matrix
+{
+ my ($size) = @_;
+
+ die "Invalid matrix size $size, stopped"
+ unless isint($size) && $size > 0;
+
+ die "Matrix size $size is too wide to be properly displayed, stopped"
+ if $size > $MAX_SIZE;
+
+ my $matrix;
+
+ for my $i (0 .. $size - 1)
+ {
+ $matrix->[$i][$_] = ($i == $_) ? 1 : 0 for 0 .. $size - 1;
+ }
+
+ return $matrix;
+}
+
+sub print_matrix
+{
+ my ($matrix) = @_;
+ my $size = scalar @$matrix;
+
+ if ($size == 1)
+ {
+ print '[', $matrix->[0][0], "]\n";
+ }
+ else
+ {
+ print '|', join( ' ', $matrix->[$_]->@* ), "|\n" for 0 .. $size - 1;
+ }
+}
+
+################################################################################
diff --git a/challenge-011/athanasius/perl5/ch-3.pl b/challenge-011/athanasius/perl5/ch-3.pl
new file mode 100644
index 0000000000..8b9fed40ed
--- /dev/null
+++ b/challenge-011/athanasius/perl5/ch-3.pl
@@ -0,0 +1,327 @@
+#!perl
+
+################################################################################
+=comment
+
+Perl Weekly Challenge 011
+=========================
+
+Challenge #3
+------------
+
+Using [ https://openweathermap.org/current |Open Weather Map API], write a
+script to fetch the current weather for an arbitrary city. Note that you will
+need to sign up for Open Weather Map's free tier and then wait a couple hours
+before your API key will be valid. This challenge was proposed by *Joelle
+Maslak*. The API challenge is *optional* but would love to see your solution.
+
+=cut
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2019 Perlmonk Athanasius #
+#--------------------------------------#
+
+use strict;
+use warnings;
+use utf8;
+use Const::Fast;
+use DateTime;
+use Getopt::Long;
+use JSON;
+use LWP::UserAgent ();
+
+const my $API_KEY => '22314778a05bf583f56cda402fce02eb';
+const my $TIMEOUT => 30; # seconds
+const my $URL => 'http://api.openweathermap.org/data/2.5/weather?q=';
+const my $URL_ID => 'http://api.openweathermap.org/data/2.5/weather?id=';
+const my $S_PER_MIN => 60;
+const my $MIN_PER_H => 60;
+const my $S_PER_HR => $S_PER_MIN * $MIN_PER_H;
+const my $ABSZERO_C => -273.15;
+const my $ABSZERO_F => -459.67;
+const my $K_PER_F => 9 / 5;
+const my $USAGE => "\nUsage: perl $0 --city <string> --country <string>\n" .
+ " or perl $0 --city_id <positive integer>\n" .
+ " or perl $0 --help\n";
+
+$| = 1;
+
+MAIN:
+{
+ my ($city_id, $city, $country, $help, $response);
+
+ GetOptions
+ (
+ 'city_id=i' => \$city_id,
+ 'city=s' => \$city,
+ 'country=s' => \$country,
+ 'help' => \$help,
+
+ ) or die $USAGE;
+
+ die $USAGE if $help ||
+ !(defined $city_id || (defined $city && defined $country));
+
+ $response = get_weather($city_id, $city, $country);
+
+ if ($response->is_success)
+ {
+ report($city_id, $city, $country, $response);
+ }
+ else
+ {
+ die "\nError: ", $response->status_line, "\n";
+ }
+}
+
+sub get_weather
+{
+ my ($city_id, $city, $country) = @_;
+
+ my $url = defined($city_id) ? "$URL_ID$city_id" : "$URL$city,$country";
+ $url .= "&APPID=$API_KEY";
+ my $ua = LWP::UserAgent->new(timeout => $TIMEOUT);
+ my $resp = $ua->get($url);
+
+ return $resp;
+}
+
+sub report
+{
+ my ($city_id, $city, $country, $response) = @_;
+
+ my $json = JSON->new->allow_nonref;
+ my $weather = $json->decode($response->{_content});
+ my $location = defined($city_id) ? "city with ID $city_id" :
+ "$city, $country";
+
+ print "\nDetails of the current weather for $location:\n";
+
+ report_location($weather);
+ report_weather ($weather);
+ report_temps ($weather);
+ report_snow ($weather);
+ report_rain ($weather);
+ report_wind ($weather);
+ report_pressure($weather);
+ report_times ($weather);
+}
+
+sub report_location
+{
+ my ($weather) = @_;
+ my $city = $weather->{name};
+ my $country = $weather->{sys}{country};
+ my $id = $weather->{id};
+ my $latitude = $weather->{coord}{lat};
+ $latitude = sprintf "%.2f°%s", abs($latitude),
+ ($latitude < 0 ? 'S' : 'N') if defined $latitude;
+ my $longitude = $weather->{coord}{lon};
+ $longitude = sprintf "%.2f°%s", abs($longitude),
+ ($longitude < 0 ? 'W' : 'E') if defined $longitude;
+
+ if (defined $city || defined $country || defined $id || defined $latitude ||
+ defined $longitude)
+ {
+ print "\nLocation\n";
+ printf " City: %s\n", $city // 'N/A';
+ printf " Country code: %s\n", $country // 'N/A';
+ printf " City ID: %d\n", $id // 'N/A';
+ printf " Latitude: %s\n", $latitude // 'N/A';
+ printf " Longitude: %s\n", $longitude // 'N/A';
+ }
+}
+
+sub report_weather
+{
+ my ($weather) = @_;
+ my $description = $weather->{weather}[0]{description};
+ my $summary = $weather->{weather}[0]{main};
+ $summary .= ' (' . $description . ')' if defined $summary &&
+ defined $description;
+ my $cloudiness = $weather->{clouds}{all};
+ $cloudiness .= '%' if defined $cloudiness;
+ my $humidity = $weather->{main}{humidity};
+ $humidity .= '%' if defined $humidity;
+ my $visibility = $weather->{visibility};
+ $visibility = commify($visibility) . ' m' if defined $visibility;
+
+ if (defined $summary || defined $cloudiness || defined $humidity ||
+ defined $visibility)
+ {
+ print "\nWeather\n";
+ printf " Summary: %s\n", $summary // 'N/A';
+ printf " Cloudiness: %s\n", $cloudiness // 'N/A';
+ printf " Humidity: %s\n", $humidity // 'N/A';
+ printf " Visibility: %s\n", $visibility // 'N/A';
+ }
+}
+
+sub report_temps
+{
+ my ($weather) = @_;
+
+ my $min = $weather->{main}{temp_min};
+ $min = sprintf("%2.0f°C (%.0f°F)", k2c($min), k2f($min)) if defined $min;
+ my $max = $weather->{main}{temp_max};
+ $max = sprintf("%2.0f°C (%.0f°F)", k2c($max), k2f($max)) if defined $max;
+ my $cur = $weather->{main}{temp};
+ $cur = sprintf("%2.0f°C (%.0f°F)", k2c($cur), k2f($cur)) if defined $cur;
+
+ if (defined $min || defined $max || defined $cur)
+ {
+ print "\nTemperatures\n";
+ printf " Minimum: %s\n", $min // 'N/A';
+ printf " Maximum: %s\n", $max // 'N/A';
+ printf " Current: %s\n", $cur // 'N/A';
+ }
+}
+
+sub report_snow
+{
+ my ($weather) = @_;
+ my $snow_1h = $weather->{snow}{'1h'};
+ $snow_1h .= ' mm' if defined $snow_1h;
+ my $snow_3h = $weather->{snow}{'3h'};
+ $snow_3h .= ' mm' if defined $snow_3h;
+
+ if (defined $snow_1h || defined $snow_3h)
+ {
+ print "\nSnow\n";
+ printf " Volume (1 hr): %s\n", $snow_1h // 'N/A';
+ printf " Volume (3 hr): %s\n", $snow_3h // 'N/A';
+ }
+}
+
+sub report_rain
+{
+ my ($weather) = @_;
+ my $rain_1h = $weather->{rain}{'1h'};
+ $rain_1h .= ' mm' if defined $rain_1h;
+ my $rain_3h = $weather->{rain}{'3h'};
+ $rain_3h .= ' mm' if defined $rain_3h;
+
+ if (defined $rain_1h || defined $rain_3h)
+ {
+ print "\nRain\n";
+ printf " Volume (1 hr): %s\n", $rain_1h // 'N/A';
+ printf " Volume (3 hr): %s\n", $rain_3h // 'N/A';
+ }
+}
+
+sub report_wind
+{
+ my ($weather) = @_;
+ my $speed = $weather->{wind}{speed};
+ $speed = sprintf("%.1f m/s", $speed) if defined $speed;
+ my $direction = $weather->{wind}{deg};
+ $direction = sprintf("%d°", $direction) if defined $direction;
+
+ if (defined $speed || defined $direction)
+ {
+ print "\nWind\n";
+ printf " Speed: %s\n", $speed // 'N/A';
+ printf " Direction: %s\n", $direction // 'N/A';
+ }
+}
+
+sub report_pressure
+{
+ my ($weather) = @_;
+ my $pressure = $weather->{main}{pressure};
+ $pressure = commify($pressure) . ' hPa' if defined $pressure;
+ my $sea_level = $weather->{main}{sea_level};
+ $sea_level = commify($sea_level) . ' hPa' if defined $sea_level;
+ my $grnd_level = $weather->{main}{grnd_level};
+ $grnd_level = commify($grnd_level) . ' hPa' if defined $grnd_level;
+
+ if (defined $pressure || defined $sea_level || defined $grnd_level)
+ {
+ print "\nAir pressure\n";
+ printf " Sea level: %s\n", $pressure if defined $pressure;
+ printf " Sea level: %s\n", $sea_level if defined $sea_level;
+ printf " Ground level: %s\n", $grnd_level if defined $grnd_level;
+ }
+}
+
+sub report_times
+{
+ my ($weather) = @_;
+ my $seconds = $weather->{timezone};
+ my ($current, $sunrise, $sunset, $timezone);
+
+ if (defined $seconds)
+ {
+ $timezone = DateTime::Duration->new(seconds => $seconds);
+ $current = DateTime->from_epoch(epoch => $weather->{dt});
+
+ if (defined $current)
+ {
+ $current->add_duration($timezone);
+ $current = $current->hms . ', ' . $current->ymd;
+ }
+
+ $sunrise = DateTime->from_epoch(epoch => $weather->{sys}{sunrise});
+
+ if (defined $sunrise)
+ {
+ $sunrise->add_duration($timezone);
+ $sunrise = $sunrise->hms . ', ' . $sunrise->ymd;
+ }
+
+ $sunset = DateTime->from_epoch(epoch => $weather->{sys}{sunset});
+
+ if (defined $sunset)
+ {
+ $sunset->add_duration($timezone);
+ $sunset = $sunset->hms . ', ' . $sunset->ymd;
+ }
+
+ my $hours = abs int ($seconds / $S_PER_HR);
+ my $minutes = abs int(($seconds % $S_PER_HR) / $S_PER_MIN);
+ $timezone = sprintf "UTC%s%02d:%02d", (($seconds < 0) ? '-' : '+'),
+ $hours, $minutes;
+ }
+
+ if (defined $timezone || defined $current || defined $sunrise ||
+ defined $sunset)
+ {
+ print "\nTimes (local)\n";
+ printf " Timezone: %s\n", $timezone // 'N/A';
+ printf " Current: %s\n", $current // 'N/A';
+ printf " Sunrise: %s\n", $sunrise // 'N/A';
+ printf " Sunset: %s\n", $sunset // 'N/A';
+ }
+}
+
+# Convert temperature in Kelvin to degrees Celsius
+
+sub k2c
+{
+ my ($kelvin) = @_;
+
+ return $kelvin + $ABSZERO_C;
+}
+
+# Convert temperature in Kelvin to degrees Fahranheit
+
+sub k2f
+{
+ my ($kelvin) = @_;
+
+ return ($kelvin * $K_PER_F) + $ABSZERO_F;
+}
+
+# Separate groups of 3 digits (in the integer part of a number) with commas
+
+sub commify
+{
+ my ($string) = @_;
+
+ # Regex from perlfaq5: "How can I output my numbers with commas added?"
+
+ return $string =~ s/(^\d+?(?=(?>(?:\d{3})+)(?!\d))|\G\d{3}(?=\d))/$1,/gr;
+}
+
+################################################################################