aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--challenge-004/james-smith/README.md70
-rw-r--r--challenge-004/james-smith/perl5/ch-1.pl1
-rw-r--r--challenge-004/james-smith/perl5/ch-2.pl38
-rw-r--r--challenge-004/james-smith/perl6/ch-1.p61
-rw-r--r--challenge-004/james-smith/perl6/ch-2.p627
5 files changed, 85 insertions, 52 deletions
diff --git a/challenge-004/james-smith/README.md b/challenge-004/james-smith/README.md
index 4a9b029e85..27d23b6119 100644
--- a/challenge-004/james-smith/README.md
+++ b/challenge-004/james-smith/README.md
@@ -5,70 +5,36 @@ solutions) to try out some of the cool features that Perl 6 gives over
Perl 5 - especially as it is basically a new language with new syntactic
sugar....
-# Problem 2
-
-Wierdly I think problem 2 is the easier one this week.
-
-I wrote this twice, the second solution I'm using minimizes memory
-usage by extends the array rather than copying a new one. We just
-loop through the array adding the next value to the current one
-and then unshift the first 1 to the array.
-
-Can't see an easy neat way of doing it differently in Perl 5 and 6 -
-but I do like
-
-1. the MAIN function in perl which clears up how CLI
-parameters are pulled into the code and
-
-1. the arbitrary precision
-integers... (no more "e+" notation)
-
# Problem 1
-## Perl 5
-
-This was an interesting challenge - and still working out if I have
-the optimal solution, again I'll write an iterator which gets the
-next number and call this multiple times to get the list....
+This is quirky same code between Perl 5 and Perl 6 produce different output - Perl 6 displays one more digit of Pi... so we need to extend the script by one byte (adding ";") to the end of the line...
-To find the next one we have to find the first number larger than the
-current largest number in the list - which is a multiple of 5, 3 or 2
-of an entry already in the list...
+```
+perl -Mfeature=say perl5/ch-1.pl
+perl6 perl6/ch-1.p6
+```
-The loop we use is interesting as it contains `next`, `last` and `redo`
-commands. Firstly how it works - we are looking for numbers whose
-multiples are larger than the largest value.
+# Problem 2
-* so we start looping through the list looking for multiples of 5 (we
-will get to a larger value first when multiplying by 5). We use `next`
-here to short cut the loop until we have reached a larger value...
+## Perl 5
-* we then store this, and then continue with the next highest factor.
+This is a nice problem - I solved this in Perl 5 in two ways - firstly with nested loops - but this requires a label (which is ugly code) to break out of the inner loop and get to the next word. The neater solution requires encapsulating the inner loop inside a function and calling that. Returning true if the word can be matched and false otherwise.
- * If there are no factors left we use `last` to exit the loop and
- and "add" the value to the hamming array.
-
- * If there are factors left we need to continue the loop with the
- new value - BUT - we need to re-check the current element from the
- hamming array. We do this with `redo` which repeats the loop with
- the same value...
+The first part collects together the counts of the letters and the second loops through each of the words to see if there are sufficient letters.
-* once we have a new value we store it on the array and return it...
+The loop is destructive of the counts array so we pass a copy into the function rather than the usual pass by reference.. This effectively clones the counts array so we don't have to do this explicitly
-This method means we only loop through less than once rather than
-looping through for 2, 3 & 5....
+```
+perl perl5/ch-2.pl back < /usr/share/dict/british-english-insane
+```
## Perl 6
-I'm new to Perl 6 and so looking for what features of the language
-give me an advantage of Perl 5 which I've been programming for over
-20 years now...
-
-So I looked at using a generator with lazy evaluation using
-`lazy gather` and `take` to generate the values... Looks interesting
-as a "programming construct" but again like last weeks use of
-currying - does not particularly look efficient in this case.
-
+Similar code to perl 5 - just fixing syntactic sugar. Perl6 though passes by reference (which you have to do explicitly in Perl 5) so you need to clone the counts array before passing it to checkword.
+The other change is split - you don't use the empty regex "//" to perform the split - rather the empty string (something frowned upon in Perl5) and to remove the rogue white-space split adds you need to include the additional flag `:skip-empty`
+```
+perl6 perl6/ch-2.p6 back < /usr/share/dict/british-english-insane
+```
diff --git a/challenge-004/james-smith/perl5/ch-1.pl b/challenge-004/james-smith/perl5/ch-1.pl
new file mode 100644
index 0000000000..82b653795c
--- /dev/null
+++ b/challenge-004/james-smith/perl5/ch-1.pl
@@ -0,0 +1 @@
+say 2*atan2 1,0
diff --git a/challenge-004/james-smith/perl5/ch-2.pl b/challenge-004/james-smith/perl5/ch-2.pl
new file mode 100644
index 0000000000..216374e9d7
--- /dev/null
+++ b/challenge-004/james-smith/perl5/ch-2.pl
@@ -0,0 +1,38 @@
+use strict;
+use warnings;
+use feature qw(say);
+
+## Read in letters from command line... and store in %c...
+## We split each argument so words can be passed in rather
+## than individual letters if required...
+
+my %counts; $counts{lc$_}++ for map{split//} @ARGV;
+
+for my $word (<STDIN>) { chomp $word;
+ say $word if checkword(lc$word,%counts);
+}
+
+## Check the word to see if it can be made up from letters
+## use passing a hash by value to clone the counts so we
+## don't destroy it through each loop {the method is
+## destructive!}
+
+sub checkword { my($w,%c)=@_;
+ for(split//,$w) {return if --$c{$_}<0}
+ return 1
+}
+
+## Below is the first try - not as elegant - but no function
+## calls - just needs to use labels to jump out of inner for
+## loop
+##
+## my $c;
+## $c->{lc $_}++ foreach @ARGV;
+## WORD: while (my $w=<STDIN>) {
+## chomp $w;
+## my %t = %{$c};
+## for (split //,lc $w) {
+## next WORD if --$t{$_} < 0;
+## }
+## say $w;
+## }
diff --git a/challenge-004/james-smith/perl6/ch-1.p6 b/challenge-004/james-smith/perl6/ch-1.p6
new file mode 100644
index 0000000000..6a3ec1d7f6
--- /dev/null
+++ b/challenge-004/james-smith/perl6/ch-1.p6
@@ -0,0 +1 @@
+say 2*atan2 1,0;
diff --git a/challenge-004/james-smith/perl6/ch-2.p6 b/challenge-004/james-smith/perl6/ch-2.p6
new file mode 100644
index 0000000000..1b2ad01c7c
--- /dev/null
+++ b/challenge-004/james-smith/perl6/ch-2.p6
@@ -0,0 +1,27 @@
+use strict;
+
+## Read in letters from command line... and store in %c...
+## We split each argument so words can be passed in rather
+## than individual letters if required...
+
+my %counts;
+for @*ARGS -> $w {
+ %counts{lc $_}++ for split '',$w, :skip-empty;
+}
+
+for $*IN.lines() -> $word {
+ my %copy = %counts.clone;
+ say $word if checkword(lc($word),%copy);
+}
+
+## Check the word to see if it can be made up from letters
+## use passing a hash by value to clone the counts so we
+## don't destroy it through each loop {the method is
+## destructive!}
+
+sub checkword($word,%copy_counts) {
+ for (split '',$word, :skip-empty) -> $letter {
+ return if --%copy_counts{$letter} < 0;
+ }
+ return 1;
+}