aboutsummaryrefslogtreecommitdiff
path: root/challenge-166/duncan-c-white
diff options
context:
space:
mode:
authordcw <d.white@imperial.ac.uk>2022-05-29 22:45:43 +0100
committerdcw <d.white@imperial.ac.uk>2022-05-29 22:45:43 +0100
commit2e9608e5d530cd4ef8c386ee52676f1126468429 (patch)
tree3c6fc0b70d6c2d7af8872d26c36b179dc17f0fd8 /challenge-166/duncan-c-white
parent1cf0a644be424d94932ec07420fff28019d8c8a9 (diff)
downloadperlweeklychallenge-club-2e9608e5d530cd4ef8c386ee52676f1126468429.tar.gz
perlweeklychallenge-club-2e9608e5d530cd4ef8c386ee52676f1126468429.tar.bz2
perlweeklychallenge-club-2e9608e5d530cd4ef8c386ee52676f1126468429.zip
imported my solutions to this week's tasks, no time to do C versions this week, I particularly enjoyed the second task
Diffstat (limited to 'challenge-166/duncan-c-white')
-rw-r--r--challenge-166/duncan-c-white/C/.build1
-rw-r--r--challenge-166/duncan-c-white/README101
-rw-r--r--challenge-166/duncan-c-white/bestfitdata48
-rwxr-xr-xchallenge-166/duncan-c-white/perl/ch-1.pl87
-rwxr-xr-xchallenge-166/duncan-c-white/perl/ch-2.pl107
-rw-r--r--challenge-166/duncan-c-white/perl/dir_a/Arial.ttf0
-rw-r--r--challenge-166/duncan-c-white/perl/dir_a/Comic_Sans.ttf0
-rw-r--r--challenge-166/duncan-c-white/perl/dir_a/Georgia.ttf0
-rw-r--r--challenge-166/duncan-c-white/perl/dir_a/Helvetica.ttf0
-rw-r--r--challenge-166/duncan-c-white/perl/dir_a/Impact.otf0
-rw-r--r--challenge-166/duncan-c-white/perl/dir_a/Verdana.ttf0
-rw-r--r--challenge-166/duncan-c-white/perl/dir_b/Arial.ttf0
-rw-r--r--challenge-166/duncan-c-white/perl/dir_b/Comic_Sans.ttf0
-rw-r--r--challenge-166/duncan-c-white/perl/dir_b/Courier_New.ttf0
-rw-r--r--challenge-166/duncan-c-white/perl/dir_b/Helvetica.ttf0
-rw-r--r--challenge-166/duncan-c-white/perl/dir_b/Impact.otf0
-rw-r--r--challenge-166/duncan-c-white/perl/dir_b/Tahoma.ttf0
-rw-r--r--challenge-166/duncan-c-white/perl/dir_b/Verdana.ttf0
-rw-r--r--challenge-166/duncan-c-white/perl/dir_c/Arial.ttf0
-rw-r--r--challenge-166/duncan-c-white/perl/dir_c/Courier_New.ttf0
-rw-r--r--challenge-166/duncan-c-white/perl/dir_c/Helvetica.ttf0
-rw-r--r--challenge-166/duncan-c-white/perl/dir_c/Impact.otf0
-rw-r--r--challenge-166/duncan-c-white/perl/dir_c/Monaco.ttf0
-rw-r--r--challenge-166/duncan-c-white/perl/dir_c/Verdana.ttf0
24 files changed, 250 insertions, 94 deletions
diff --git a/challenge-166/duncan-c-white/C/.build b/challenge-166/duncan-c-white/C/.build
deleted file mode 100644
index 295e8bb4c9..0000000000
--- a/challenge-166/duncan-c-white/C/.build
+++ /dev/null
@@ -1 +0,0 @@
-BUILD = ch-1 ch-2
diff --git a/challenge-166/duncan-c-white/README b/challenge-166/duncan-c-white/README
index c04719179d..c0f50441d9 100644
--- a/challenge-166/duncan-c-white/README
+++ b/challenge-166/duncan-c-white/README
@@ -1,64 +1,75 @@
-TASK 1: Scalable Vector Graphics (SVG)
+TASK 1: Hexadecimal Words
-Scalable Vector Graphics (SVG) are not made of pixels, but lines,
-ellipses, and curves, that can be scaled to any size without any loss
-of quality. If you have ever tried to resize a small JPG or PNG, you
-know what I mean by 'loss of quality'! What many people do not know
-about SVG files is, they are simply XML files, so they can easily be
-generated programmatically.
+As an old systems programmer, whenever I needed to come up with a 32-bit
+number, I would reach for the tired old examples like 0xDeadBeef and
+0xC0dedBad. I want more!
-For this task, you may use external library, such as Perl's SVG library,
-maintained in recent years by our very own Mohammad S Anwar. You can
-instead generate the XML yourself; it's actually quite simple. The
-source for the example image for Task #2 might be instructive.
+Write a program that will read from a dictionary and find 2- to 8-letter
+words that can be "spelled" in hexadecimal, with the addition of the
+following letter substitutions:
-Your task is to accept a series of points and lines in the following format, one per line, in arbitrary order:
+ o -> 0 (e.g., 0xf00d = "food")
+ l -> 1
+ i -> 1
+ s -> 5
+ t -> 7
-Point: x,y
-Line: x1,y1,x2,y2
+You can use your own dictionary or you can simply open
+../../../data/dictionary.txt (relative to your script's location in
+our GitHub repository) to access the dictionary of common words from
+Week #161.
-Example:
+Optional Extras (for an 0xAddedFee, of course!)
-53,10
-53,10,23,30
-23,30
+ Limit the number of "special" letter substitutions in any one result
+ to keep that result at least somewhat comprehensible. (0x51105010
+ is an actual example from my sample solution you may wish to avoid!)
-Then, generate an SVG file plotting all points, and all lines. If done
-correctly, you can view the output .svg file in your browser.
+ Find phrases of words that total 8 characters in length (e.g.,
+ 0xFee1Face), rather than just individual words.
-MY NOTES: ok. Having read the SVG Wikipedia page, it seems very easy (although I hate XML).
+MY NOTES: ok. Not a terribly fascinating task, forget the optional extras.
+Should be simple enough.
-GUEST LANGUAGE: As a bonus, I also had a go at translating ch-1.pl
-into C (look in the C directory for that).
+Task 2: K-Directory Diff
-Task 2: Line of Best Fit
+Given a few (three or more) directories (non-recursively), display a
+side-by-side difference of files that are missing from at least one of
+the directories. Do not display files that exist in every directory.
-When you have a scatter plot of points, a line of best fit is the line
-that best describes the relationship between the points, and is very
-useful in statistics. Otherwise known as linear regression, here is an
-example of what such a line might look like:
+Since the task is non-recursive, if you encounter a subdirectory, append
+a /, but otherwise treat it the same as a regular file.
-[image showing red best fit line on graph of black data points]
+Example
-The method most often used is known as the least squares method, as
-it is straightforward and efficient, but you may use any method that
-generates the correct result.
+Given the following directory structure:
-Calculate the line of best fit for the following 48 points:
+dir_a:
+Arial.ttf Comic_Sans.ttf Georgia.ttf Helvetica.ttf Impact.otf Verdana.ttf Old_Fonts/
-333,129 39,189 140,156 292,134 393,52 160,166 362,122 13,193
-341,104 320,113 109,177 203,152 343,100 225,110 23,186 282,102
-284,98 205,133 297,114 292,126 339,112 327,79 253,136 61,169
-128,176 346,72 316,103 124,162 65,181 159,137 212,116 337,86
-215,136 153,137 390,104 100,180 76,188 77,181 69,195 92,186
-275,96 250,147 34,174 213,134 186,129 189,154 361,82 363,89
+dir_b:
+Arial.ttf Comic_Sans.ttf Courier_New.ttf Helvetica.ttf Impact.otf Tahoma.ttf Verdana.ttf
-Using your rudimentary graphing engine from Task #1, graph all points, as well as the line of best fit.
+dir_c:
+Arial.ttf Courier_New.ttf Helvetica.ttf Impact.otf Monaco.ttf Verdana.ttf
-MY NOTES: seems pretty simple, https://www.mathsisfun.com/data/least-squares-regression.html has a good
-explanation of the method. I've put the above data, one point per line, in "bestfitdata" in the
-top-level directory.
+The output should look similar to the following:
-GUEST LANGUAGE: As a bonus, I also had a go at translating ch-2.pl
-into C (look in the C directory for that).
+dir_a | dir_b | dir_c
+-------------- | --------------- | ---------------
+Comic_Sans.ttf | Comic_Sans.ttf |
+ | Courier_New.ttf | Courier_New.ttf
+Georgia.ttf | |
+ | | Monaco.ttf
+Old_Fonts/ | |
+ | Tahoma.ttf |
+
+
+MY NOTES: this is much more appealing to me; right up my street. Generally,
+it seems pretty simple, build a "fileindirs" mapping from file -> a list of
+which directories it's in, and form a set of all named files, then iterate
+over the "all named files" set, skipping files present in all the dirs,
+then iterating over all the dirs, using the fileindirs info to determine
+which columns to leave blank. Need to auto-width each dir column, but that's
+trivial to do.
diff --git a/challenge-166/duncan-c-white/bestfitdata b/challenge-166/duncan-c-white/bestfitdata
deleted file mode 100644
index 132a3da095..0000000000
--- a/challenge-166/duncan-c-white/bestfitdata
+++ /dev/null
@@ -1,48 +0,0 @@
-333,129
-39,189
-140,156
-292,134
-393,52
-160,166
-362,122
-13,193
-341,104
-320,113
-109,177
-203,152
-343,100
-225,110
-23,186
-282,102
-284,98
-205,133
-297,114
-292,126
-339,112
-327,79
-253,136
-61,169
-128,176
-346,72
-316,103
-124,162
-65,181
-159,137
-212,116
-337,86
-215,136
-153,137
-390,104
-100,180
-76,188
-77,181
-69,195
-92,186
-275,96
-250,147
-34,174
-213,134
-186,129
-189,154
-361,82
-363,89
diff --git a/challenge-166/duncan-c-white/perl/ch-1.pl b/challenge-166/duncan-c-white/perl/ch-1.pl
new file mode 100755
index 0000000000..d1027ef22b
--- /dev/null
+++ b/challenge-166/duncan-c-white/perl/ch-1.pl
@@ -0,0 +1,87 @@
+#!/usr/bin/perl
+#
+# TASK 1: Hexadecimal Words
+#
+# As an old systems programmer, whenever I needed to come up with a 32-bit
+# number, I would reach for the tired old examples like 0xDeadBeef and
+# 0xC0dedBad. I want more!
+#
+# Write a program that will read from a dictionary and find 2- to 8-letter
+# words that can be "spelled" in hexadecimal, with the addition of the
+# following letter substitutions:
+#
+# o -> 0 (e.g., 0xf00d = "food")
+# l -> 1
+# i -> 1
+# s -> 5
+# t -> 7
+#
+# You can use your own dictionary or you can simply open
+# ../../../data/dictionary.txt (relative to your script's location in
+# our GitHub repository) to access the dictionary of common words from
+# Week #161.
+#
+# Optional Extras (for an 0xAddedFee, of course!)
+#
+# Limit the number of "special" letter substitutions in any one result
+# to keep that result at least somewhat comprehensible. (0x51105010
+# is an actual example from my sample solution you may wish to avoid!)
+#
+# Find phrases of words that total 8 characters in length (e.g.,
+# 0xFee1Face), rather than just individual words.
+#
+# MY NOTES: ok. Not a terribly fascinating task, forget the optional extras.
+# Should be simple enough.
+#
+
+use strict;
+use warnings;
+use feature 'say';
+use Getopt::Long;
+#use Data::Dumper;
+
+my %mapping = qw(a a b b c c d d e e f f o 0 l 1 i 1 s 5 t 7);
+
+=pod
+
+=head2 my $hexword = hexword( $word );
+
+Return the hex-word equivalent of $word iff $word is a hex-word, otherwise ""
+
+=cut
+sub hexword ($)
+{
+ my( $word ) = @_;
+ my $result = "";
+ foreach my $let (split(//, $word))
+ {
+ return "" unless $mapping{$let};
+ $result .= $mapping{$let};
+ }
+ return $result;;
+}
+
+my $debug=0;
+my $minlen=2;
+my $maxlen=8;
+die "Usage: form-hex-word [--debug] [--minlen min] [--maxlen max]\n"
+ unless GetOptions( "debug"=>\$debug,
+ "minlen=i"=>\$minlen,
+ "maxlen=i"=>\$maxlen ) && @ARGV==0;
+
+my $longest = "";
+open( my $in, '<', "../../../data/dictionary.txt" ) || die;
+while( <$in> )
+{
+ chomp;
+ my $len = length($_);
+ next unless $len >= $minlen && $len <= $maxlen;
+ $_ = lc($_);
+ my $hw = hexword( $_ );
+ next unless $hw;
+ $longest = $hw if length($hw) > length($longest);
+ say "$_ == $hw";
+}
+close( $in );
+
+say "longest: $longest";
diff --git a/challenge-166/duncan-c-white/perl/ch-2.pl b/challenge-166/duncan-c-white/perl/ch-2.pl
new file mode 100755
index 0000000000..46d4c8cdf9
--- /dev/null
+++ b/challenge-166/duncan-c-white/perl/ch-2.pl
@@ -0,0 +1,107 @@
+#!/usr/bin/perl
+#
+# Task 2: K-Directory Diff
+#
+# Given a few (three or more) directories (non-recursively), display a
+# side-by-side difference of files that are missing from at least one of
+# the directories. Do not display files that exist in every directory.
+#
+# Since the task is non-recursive, if you encounter a subdirectory, append
+# a /, but otherwise treat it the same as a regular file.
+#
+# Example
+#
+# Given the following directory structure:
+#
+# dir_a:
+# Arial.ttf Comic_Sans.ttf Georgia.ttf Helvetica.ttf Impact.otf Verdana.ttf Old_Fonts/
+#
+# dir_b:
+# Arial.ttf Comic_Sans.ttf Courier_New.ttf Helvetica.ttf Impact.otf Tahoma.ttf Verdana.ttf
+#
+# dir_c:
+# Arial.ttf Courier_New.ttf Helvetica.ttf Impact.otf Monaco.ttf Verdana.ttf
+#
+# The output should look similar to the following:
+#
+# dir_a | dir_b | dir_c
+# -------------- | --------------- | ---------------
+# Comic_Sans.ttf | Comic_Sans.ttf |
+# | Courier_New.ttf | Courier_New.ttf
+# Georgia.ttf | |
+# | | Monaco.ttf
+# Old_Fonts/ | |
+# | Tahoma.ttf |
+#
+#
+# MY NOTES: this is much more appealing to me; right up my street. Generally,
+# it seems pretty simple, build a "fileindirs" mapping from file -> a list of
+# which directories it's in, and form a set of all named files, then iterate
+# over the "all named files" set, skipping files present in all the dirs,
+# then iterating over all the dirs, using the fileindirs info to determine
+# which columns to leave blank. Need to auto-width each dir column, but that's
+# trivial to do.
+#
+
+use strict;
+use warnings;
+use feature 'say';
+use Getopt::Long;
+#use Function::Parameters;
+use List::Util qw(max);
+#use Data::Dumper;
+
+
+my $debug=0;
+die "Usage: k-diff [--debug] dir1 dir2 dir3..\n"
+ unless GetOptions( "debug"=>\$debug ) && @ARGV>=3;
+
+my @dirs = @ARGV;
+
+my %allset; # set of all files seen in any dir
+my %filesindirs;# mapping of filename -> list of dirs it's in
+my %dirwidth; # map dirname -> max width of any filename
+
+foreach my $dir (@dirs)
+{
+ opendir(my $dh, $dir) || die "Can't opendir $dir: $!\n";
+ my @files = map { -d "$dir/$_" ? "$_/" : $_ }
+ grep { $_ ne "." && $_ ne ".." }
+ readdir($dh);
+ $allset{$_}++ for @files;
+ foreach my $file (@files)
+ {
+ $filesindirs{$file} //= [];
+ my $aref = $filesindirs{$file};
+ push @$aref, $dir;
+ }
+ $dirwidth{$dir} = max map { length($_)+1 } @files;
+ closedir $dh;
+}
+
+my @cells;
+my @dashes;
+foreach my $dir (@dirs)
+{
+ my $w = $dirwidth{$dir};
+ push @cells, sprintf( "%-${w}s", $dir );
+ push @dashes, ('-' x $w);
+}
+say join( ' | ', @cells );
+say join( '-|-', @dashes );
+
+foreach my $file (sort keys %allset)
+{
+ my $aref = $filesindirs{$file};
+ next if @$aref == @dirs; # in all dirs
+ @cells = ();
+ my %indir = map { $_ => 1 } @$aref; #
+ foreach my $dir (@dirs)
+ {
+ my $w = $dirwidth{$dir};
+ my $str = $indir{$dir} ? $file : ' ';
+ $str = sprintf( "%-${w}s", $str );
+ push @cells, $str;
+ }
+ say join( ' | ', @cells );
+}
diff --git a/challenge-166/duncan-c-white/perl/dir_a/Arial.ttf b/challenge-166/duncan-c-white/perl/dir_a/Arial.ttf
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/challenge-166/duncan-c-white/perl/dir_a/Arial.ttf
diff --git a/challenge-166/duncan-c-white/perl/dir_a/Comic_Sans.ttf b/challenge-166/duncan-c-white/perl/dir_a/Comic_Sans.ttf
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/challenge-166/duncan-c-white/perl/dir_a/Comic_Sans.ttf
diff --git a/challenge-166/duncan-c-white/perl/dir_a/Georgia.ttf b/challenge-166/duncan-c-white/perl/dir_a/Georgia.ttf
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/challenge-166/duncan-c-white/perl/dir_a/Georgia.ttf
diff --git a/challenge-166/duncan-c-white/perl/dir_a/Helvetica.ttf b/challenge-166/duncan-c-white/perl/dir_a/Helvetica.ttf
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/challenge-166/duncan-c-white/perl/dir_a/Helvetica.ttf
diff --git a/challenge-166/duncan-c-white/perl/dir_a/Impact.otf b/challenge-166/duncan-c-white/perl/dir_a/Impact.otf
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/challenge-166/duncan-c-white/perl/dir_a/Impact.otf
diff --git a/challenge-166/duncan-c-white/perl/dir_a/Verdana.ttf b/challenge-166/duncan-c-white/perl/dir_a/Verdana.ttf
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/challenge-166/duncan-c-white/perl/dir_a/Verdana.ttf
diff --git a/challenge-166/duncan-c-white/perl/dir_b/Arial.ttf b/challenge-166/duncan-c-white/perl/dir_b/Arial.ttf
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/challenge-166/duncan-c-white/perl/dir_b/Arial.ttf
diff --git a/challenge-166/duncan-c-white/perl/dir_b/Comic_Sans.ttf b/challenge-166/duncan-c-white/perl/dir_b/Comic_Sans.ttf
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/challenge-166/duncan-c-white/perl/dir_b/Comic_Sans.ttf
diff --git a/challenge-166/duncan-c-white/perl/dir_b/Courier_New.ttf b/challenge-166/duncan-c-white/perl/dir_b/Courier_New.ttf
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/challenge-166/duncan-c-white/perl/dir_b/Courier_New.ttf
diff --git a/challenge-166/duncan-c-white/perl/dir_b/Helvetica.ttf b/challenge-166/duncan-c-white/perl/dir_b/Helvetica.ttf
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/challenge-166/duncan-c-white/perl/dir_b/Helvetica.ttf
diff --git a/challenge-166/duncan-c-white/perl/dir_b/Impact.otf b/challenge-166/duncan-c-white/perl/dir_b/Impact.otf
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/challenge-166/duncan-c-white/perl/dir_b/Impact.otf
diff --git a/challenge-166/duncan-c-white/perl/dir_b/Tahoma.ttf b/challenge-166/duncan-c-white/perl/dir_b/Tahoma.ttf
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/challenge-166/duncan-c-white/perl/dir_b/Tahoma.ttf
diff --git a/challenge-166/duncan-c-white/perl/dir_b/Verdana.ttf b/challenge-166/duncan-c-white/perl/dir_b/Verdana.ttf
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/challenge-166/duncan-c-white/perl/dir_b/Verdana.ttf
diff --git a/challenge-166/duncan-c-white/perl/dir_c/Arial.ttf b/challenge-166/duncan-c-white/perl/dir_c/Arial.ttf
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/challenge-166/duncan-c-white/perl/dir_c/Arial.ttf
diff --git a/challenge-166/duncan-c-white/perl/dir_c/Courier_New.ttf b/challenge-166/duncan-c-white/perl/dir_c/Courier_New.ttf
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/challenge-166/duncan-c-white/perl/dir_c/Courier_New.ttf
diff --git a/challenge-166/duncan-c-white/perl/dir_c/Helvetica.ttf b/challenge-166/duncan-c-white/perl/dir_c/Helvetica.ttf
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/challenge-166/duncan-c-white/perl/dir_c/Helvetica.ttf
diff --git a/challenge-166/duncan-c-white/perl/dir_c/Impact.otf b/challenge-166/duncan-c-white/perl/dir_c/Impact.otf
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/challenge-166/duncan-c-white/perl/dir_c/Impact.otf
diff --git a/challenge-166/duncan-c-white/perl/dir_c/Monaco.ttf b/challenge-166/duncan-c-white/perl/dir_c/Monaco.ttf
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/challenge-166/duncan-c-white/perl/dir_c/Monaco.ttf
diff --git a/challenge-166/duncan-c-white/perl/dir_c/Verdana.ttf b/challenge-166/duncan-c-white/perl/dir_c/Verdana.ttf
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/challenge-166/duncan-c-white/perl/dir_c/Verdana.ttf