aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordcw <d.white@imperial.ac.uk>2020-05-31 23:37:25 +0100
committerdcw <d.white@imperial.ac.uk>2020-05-31 23:37:25 +0100
commit0eb6027c2a76f991bef17d58d5476455ad4c50f5 (patch)
treea4d6bb6266eb750cc25fa8dd6dd38795102c8a3b
parent385eea00ce8b1f68c2f7c0d3e9cd3b39a76f50f5 (diff)
downloadperlweeklychallenge-club-0eb6027c2a76f991bef17d58d5476455ad4c50f5.tar.gz
perlweeklychallenge-club-0eb6027c2a76f991bef17d58d5476455ad4c50f5.tar.bz2
perlweeklychallenge-club-0eb6027c2a76f991bef17d58d5476455ad4c50f5.zip
imported solution to first task, sorry no time to do second (and didn't much like the question anyway:-))
-rw-r--r--challenge-062/duncan-c-white/README54
-rwxr-xr-xchallenge-062/duncan-c-white/perl/ch-1.pl118
2 files changed, 146 insertions, 26 deletions
diff --git a/challenge-062/duncan-c-white/README b/challenge-062/duncan-c-white/README
index 0551c0a85d..736cbb1087 100644
--- a/challenge-062/duncan-c-white/README
+++ b/challenge-062/duncan-c-white/README
@@ -1,41 +1,43 @@
-Task 1: "Product SubArray
+Task 1: "Sort Email Addresses
-Given a list of 4 or more numbers, write a script to find the contiguous
-sublist that has the maximum product. The length of the sublist is
-irrelevant; your job is to maximize the product.
+Write a script that takes a list of email addresses (one per line) and sorts them first by the domain part of the email address, and then by the part to the left of the @ (known as the mailbox).
-Example
-
-Input: [ 2, 5, -1, 3 ]
-
-Output: [ 2, 5 ] which gives maximum product 10.
-"
+Note that the domain is case-insensitive, while the mailbox part is case sensitive. (Some email providers choose to ignore case, but that’s another matter entirely.)
-My notes: very straightforward.
+If your script is invoked with arguments, it should treat them as file names and read them in order, otherwise your script should read email addresses from standard input.
+Bonus
+Add a -u option which only includes unique email addresses in the output, just like sort -u.
+Example
-Task 2: "IPv4 Partition
+If given the following list:
-You are given a string containing only digits (0..9). The string should
-have between 4 and 12 digits.
+name@example.org
+rjt@cpan.org
+Name@example.org
+rjt@CPAN.org
+user@alpha.example.org
-Write a script to print every possible valid IPv4 address that can be
-made by partitioning the input string.
+Your script (without -u) would return:
-For the purpose of this challenge, a valid IPv4 address consists of four
-'octets' i.e. A, B, C and D, separated by dots (.).
+user@alpha.example.org
+rjt@cpan.org
+rjt@CPAN.org
+Name@example.org
+name@example.org
-Each octet must be between 0 and 255, and must not have any leading
-zeroes. (e.g., 0 is OK, but 01 is not.)
+With -u, the script would return:
-Example
+user@alpha.example.org
+rjt@CPAN.org
+Name@example.org
+name@example.org
+"
-Input: 25525511135,
+My notes: cool question. Will have a go!
-Output:
-255.255.11.135
-255.255.111.35
+Task 2: "N Queens - in 3D..
"
-My notes: sounds quite straightforward, nice problem.
+My notes: sorry, I'm rather busy, sounds like a horrible problem, not doing it.
diff --git a/challenge-062/duncan-c-white/perl/ch-1.pl b/challenge-062/duncan-c-white/perl/ch-1.pl
new file mode 100755
index 0000000000..031d7a9386
--- /dev/null
+++ b/challenge-062/duncan-c-white/perl/ch-1.pl
@@ -0,0 +1,118 @@
+#!/usr/bin/perl
+#
+# Task 1: "Sort Email Addresses
+#
+# Write a script that takes a list of email addresses (one per line)
+# and sorts them first by the domain part of the email address, and then
+# by the part to the left of the @ (known as the mailbox).
+#
+# Note that the domain is case-insensitive, while the mailbox part is case
+# sensitive. (Some email providers choose to ignore case, but that's
+# another matter entirely.)
+#
+# If your script is invoked with arguments, it should treat them as file
+# names and read them in order, otherwise your script should read email
+# addresses from standard input.
+#
+# Bonus
+#
+# Add a -u option which only includes unique email addresses in the output,
+# just like sort -u.
+#
+# Example
+#
+# If given the following list:
+#
+# name@example.org
+# rjt@cpan.org
+# Name@example.org
+# rjt@CPAN.org
+# user@alpha.example.org
+#
+# Your script (without -u) would return:
+#
+# user@alpha.example.org
+# rjt@cpan.org
+# rjt@CPAN.org
+# Name@example.org
+# name@example.org
+#
+# With -u, the script would return:
+#
+# user@alpha.example.org
+# rjt@CPAN.org
+# Name@example.org
+# name@example.org
+# "
+#
+# My notes: cool question. Will have a go! I also added '-i' meaning:
+# treat the mailname part as case-insensitive as well. Running this
+# script on the above input with -i and -u outputs only:
+#
+# user@alpha.example.org
+# rjt@CPAN.org
+# name@example.org
+#
+
+use strict;
+use warnings;
+use feature 'say';
+use Function::Parameters;
+use Getopt::Long;
+
+my $unique = 0;
+my $caseinsensitive = 0;
+my $result = GetOptions( "u" => \$unique, "i" => \$caseinsensitive );
+
+die "Usage: sort-email-addresses [-u] [-i] (addresses on input)\n"
+ unless $result;
+
+my @addr;
+while( <> )
+{
+ chomp;
+ s/\s+//g;
+ die "bad input $_\n" unless /@/;
+ push @addr, $_;
+}
+
+sub compare
+{
+ my( $aname, $adom ) = split( /@/, $a, 2 );
+ my( $bname, $bdom ) = split( /@/, $b, 2 );
+
+ # compare domains first, case insensitively
+ $adom = lc($adom);
+ $bdom = lc($bdom);
+ return $adom cmp $bdom if $adom ne $bdom;
+
+ # now compare names, case insensitively if $caseinsensitive
+ if( $caseinsensitive )
+ {
+ $aname = lc($aname);
+ $bname = lc($bname);
+ }
+ return $aname cmp $bname;
+}
+
+#
+# my $out = sanitize( $in );
+# Sanitize the email address $in, giving $out.
+# Sanitizing means:
+# - lowercasing every domain, because domains are case insensitive
+# - lowercasing every name IF $caseinsensitive
+#
+fun sanitize( $in )
+{
+ my( $name, $dom ) = split( /@/, $in, 2 );
+ $dom = lc($dom);
+ $name = lc($name) if $caseinsensitive;
+ return $name.'@'.$dom;
+}
+
+
+my %seen;
+@addr = grep { ! $seen{sanitize($_)}++ } @addr if $unique;
+@addr = sort compare @addr;
+
+say for @addr;