diff options
| author | dcw <d.white@imperial.ac.uk> | 2022-05-29 22:45:43 +0100 |
|---|---|---|
| committer | dcw <d.white@imperial.ac.uk> | 2022-05-29 22:45:43 +0100 |
| commit | 2e9608e5d530cd4ef8c386ee52676f1126468429 (patch) | |
| tree | 3c6fc0b70d6c2d7af8872d26c36b179dc17f0fd8 /challenge-166/duncan-c-white | |
| parent | 1cf0a644be424d94932ec07420fff28019d8c8a9 (diff) | |
| download | perlweeklychallenge-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')
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 |
