From 1018ced38ae62189adabafe461e4b269f802273d Mon Sep 17 00:00:00 2001 From: James Smith Date: Mon, 5 Dec 2022 07:23:57 +0000 Subject: Create ch-1.pl --- challenge-194/james-smith/perl/ch-1.pl | 36 ++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 challenge-194/james-smith/perl/ch-1.pl diff --git a/challenge-194/james-smith/perl/ch-1.pl b/challenge-194/james-smith/perl/ch-1.pl new file mode 100644 index 0000000000..c0583712de --- /dev/null +++ b/challenge-194/james-smith/perl/ch-1.pl @@ -0,0 +1,36 @@ +#!/usr/local/bin/perl + +use strict; + +use warnings; +use feature qw(say); +use Test::More; +use Benchmark qw(cmpthese timethis); + +my @TESTS = ( + ['?3:00',2,2], + ['1?:00',9,9], + ['2?:00',3,4], + ['12:?5',5,5] + ['12:5?',9,9] +); + +is( digit_2359( $_->[0] ), $_->[1] ) for @TESTS; +is( digit_2400( $_->[0] ), $_->[2] ) for @TESTS; +done_testing(); + +sub digit_2359 { + sub { + $_[0] eq '?' ? ( $_[1]<4 ? 2 : 1 ) + : $_[1] eq '?' ? ( $_[0]<2 ? 9 : 3 ) + : $_[3] eq '?' ? 5 : 9 + }->( split //, $_[0] ); +} + +sub digit_2400 { + sub { + $_[0] eq '?' ? ( $_[1]==4 && $_[3]==0 && $_[4]==0 || $_[1]<4 ? 2 : 1 ) + : $_[1] eq '?' ? ( $_[0]<2 ? 9 : $_[3]==0 && $_[4]==0 ? 4 : 3 ) + : $_[3] eq '?' ? 5 : 9 + }->( split //, $_[0] ); +} -- cgit From cf1853b24ea672c662df6926a4eb22509b82ae63 Mon Sep 17 00:00:00 2001 From: James Smith Date: Mon, 5 Dec 2022 07:25:11 +0000 Subject: Create ch-2.pl --- challenge-194/james-smith/perl/ch-2.pl | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 challenge-194/james-smith/perl/ch-2.pl diff --git a/challenge-194/james-smith/perl/ch-2.pl b/challenge-194/james-smith/perl/ch-2.pl new file mode 100644 index 0000000000..167860f910 --- /dev/null +++ b/challenge-194/james-smith/perl/ch-2.pl @@ -0,0 +1,18 @@ +#!/usr/local/bin/perl + +use strict; + +use warnings; +use feature qw(say); +use Test::More; +use Benchmark qw(cmpthese timethis); + +my @TESTS = ( ['abbc',1],['xyzyyxz',1],['xzxz',0] ); + +is( check( $_->[0] ), $_->[1] ) for @TESTS; +done_testing(); + +sub check { + my %sc; $sc{$_} ++ for split //,$_[0]; + sub { @_>2 && $_[0]==$_[1]+1 && $_[-1]==$_[1] ? 1 : 0 }->(sort {$b<=>$a} values %sc); +} -- cgit From 5f00ab4dff6383526bb2f3093e08f3128d6f8a83 Mon Sep 17 00:00:00 2001 From: James Smith Date: Mon, 5 Dec 2022 07:25:38 +0000 Subject: Create blog.txt --- challenge-194/james-smith/blog.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 challenge-194/james-smith/blog.txt diff --git a/challenge-194/james-smith/blog.txt b/challenge-194/james-smith/blog.txt new file mode 100644 index 0000000000..33001b6b41 --- /dev/null +++ b/challenge-194/james-smith/blog.txt @@ -0,0 +1,2 @@ + +https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-194/james-smith -- cgit From 6c6a5f74905e6e9e9a34f62143629a93bd88f75a Mon Sep 17 00:00:00 2001 From: James Smith Date: Mon, 5 Dec 2022 07:28:49 +0000 Subject: Update README.md --- challenge-194/james-smith/README.md | 114 ++++++++---------------------------- 1 file changed, 24 insertions(+), 90 deletions(-) diff --git a/challenge-194/james-smith/README.md b/challenge-194/james-smith/README.md index d73a9cf49b..105067118c 100644 --- a/challenge-194/james-smith/README.md +++ b/challenge-194/james-smith/README.md @@ -1,7 +1,7 @@ -[< Previous 192](https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-192/james-smith) | -[Next 194 >](https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-194/james-smith) +[< Previous 193](https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-193/james-smith) | +[Next 195 >](https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-195/james-smith) -# The Weekly Challenge 193 +# The Weekly Challenge 194 - *iffy* solutions You can find more information about this weeks, and previous weeks challenges at: @@ -15,109 +15,43 @@ You can find the solutions here on github at: https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-193/james-smith -# Task 1 - Binary string +# Task 1 - Digital Clock -***You are given an integer, `$n > 0`. Write a script to find all possible binary numbers of size `$n`.*** +***You are given time in the format `hh:mm` with one missing digit. Write a script to find the highest digit between `0`-`9` that makes it valid time.*** ## Solution -This weeks task 1 is relatively simple. (1) We need to work out what the minimum and maximum -integers are and then just print them padded to the right length. Thankfully Perl is great -at this as it is integral to it's design. - -The largest value is '(2^n)-1' and the template for `sprintf` is '`%0{n}b`'. Which gives us - -```perl -sub all_binary { ## Make a template so we don't have - my $t = "%0$_[0]b"; ## to do interpolation everytime - map { sprintf $t, $_ } 0 .. (1<<$_[0])-1 ## Need brackets as - is actioned -} ## before <<. -``` -# Task 2 - Odd String - -***You are given a list of strings of same length, `@s`. Write a script to find the odd string in the given list. Use positional value of alphabet starting with 0, i.e. `a = 0`, `b = 1`, ... `z = 25`.*** - -You are given a list of integers greater than or equal to zero, `@list`. Write a script to distribute the number so that each members are same. If you succeed then print the total moves otherwise print `-1` - -## Solution - -To find the unique string we note: - -If word one isn't equivalent to word 2 then the word we are looking for is one of these two (the one which doesn't match the 3rd word) -o/w we are looking for the first word that is not equivalent. - -### Try 1 - for every string compute a string signature - ```perl -sub sig_str { - my @Q = map { ord $_ } split //,$_[0]; - join '', map { chr(96 + $Q[$_]-$Q[$_+1]) } 0..$#Q-1 -} - -sub odd_string_sig { - my $x = sig_str( $_[0] ); - return $_[ $x eq sig_str( $_[2] ) ] if $x ne sig_str( $_[1] ); - splice@_,0,2; - $x eq sig_str( $_ ) || return $_ for @_ +sub digit_2359 { + sub { + $_[0] eq '?' ? ( $_[1]<4 ? 2 : 1 ) + : $_[1] eq '?' ? ( $_[0]<2 ? 9 : 3 ) + : $_[3] eq '?' ? 5 : 9 + }->( split //, $_[0] ); } ``` -### Try 2 - replace signature with an array ref, here we write an sig_check which compares a string against arrayref. +My original code allowed `24:00` as a valid value - this gave a slightly more complicated sub... ```perl -sub sig { - my @Q = map { ord $_ } split //,$_[0]; - [ map { $Q[$_]-$Q[$_+1] } 0..$#Q-1 ] -} - -sub sig_check { - my( $sig, $str ) = @_; - my @Q = map { ord $_ } split //,$str; - $Q[$_]-$Q[$_+1] == $sig->[$_] || return 0 for 0..$#Q-1; - return 1 -} - -sub odd_string_sig_check { - my $x = sig( $_[0] ); - return $_[ sig_check( $x, $_[2] ) ] if !sig_check( $x, $_[1] ); - splice@_,0,2; - sig_check( $x, $_ ) || return $_ for @_ +sub digit_2400 { + sub { + $_[0] eq '?' ? ( $_[1]==4 && $_[3]==0 && $_[4]==0 || $_[1]<4 ? 2 : 1 ) + : $_[1] eq '?' ? ( $_[0]<2 ? 9 : $_[3]==0 && $_[4]==0 ? 4 : 3 ) + : $_[3] eq '?' ? 5 : 9 + }->( split //, $_[0] ); } ``` -### Try 3... A bit outside in... +# Task 2 - Frequency Equalizer -We start by working out which are the equivalent words to the first word. +***You are given a string made of alphabetic characters only, `a`-`z`. Write a script to determine whether removing only one character can make the frequency of the remaining characters the same.*** -Any word is equivalent if it is in this list... So comparisons are light weight... +## Solution ```perl -sub odd_string_eqs { - my @Q = map { ord $_ } split//,$_[0]; - my $l=255; - $l > $_ && ($l=$_) for @Q; - my $h=0; - $h < $_ && ($h=$_) for @Q; - my %eqs = map { - my $o = $_; - join( '', map {chr $_+$o} @Q ) => 1 - } 97-$l .. 122-$h; - return $_[ exists $eqs{$_[2]} ] - unless exists $eqs{$_[1]}; - splice@_,0,2; - exists $eqs{$_} || return $_ for @_ +sub check { + my %sc; $sc{$_} ++ for split //,$_[0]; + sub { @_>2 && $_[0]==$_[1]+1 && $_[-1]==$_[1] ? 1 : 0 }->(sort {$b<=>$a} values %sc); } ``` -The lines prior to the `return` - compute this map. - -### Performance - -How much faster are these... depends on how far along the list you need to go until you find the unique element. -Testing a list of strings with the odd one in a random location - we saw: - -| Method | Speed up | -|----------------------- |--------: | -| signature | x 1.0 | -| signature array | x 1.4 | -| Equalivalent strings | x 2.5 | - -- cgit From 85fc1bf94b266eb1de8533c76bb7a0ca5a2a1041 Mon Sep 17 00:00:00 2001 From: James Smith Date: Mon, 5 Dec 2022 07:38:47 +0000 Subject: Update README.md --- challenge-194/james-smith/README.md | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/challenge-194/james-smith/README.md b/challenge-194/james-smith/README.md index 105067118c..5480e2db42 100644 --- a/challenge-194/james-smith/README.md +++ b/challenge-194/james-smith/README.md @@ -20,13 +20,21 @@ https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-193/ja ***You are given time in the format `hh:mm` with one missing digit. Write a script to find the highest digit between `0`-`9` that makes it valid time.*** ## Solution +Both solutions today use an ***IIFE*** (Immediately Invoked Function Expression) pronounced *iffy*. To remove the need for temporary variables. Each takes as input the result of an array method, here `split` and in the 2nd task `sort`. + +In this case we split the parameter into it's consitutant characters - the hours being in `0` & `1` and the minutes in `3` and `4`. Using a series of ternary operators we work out which position the "`?`" is in and work out what is the best digit for this place. + +If the "`?`" is in one of the minute slots this is easy as the value is either `5` or `9`. + +If it is in the hour slot we have to make sure the hour is less than 24. So if "`?`" is the first digit, we know that that can be a `2` only if the second digit is less than `4` and if it is in the second digit then the digit can only be `0` - `3` if the 1st digit is `2`. ```perl sub digit_2359 { sub { $_[0] eq '?' ? ( $_[1]<4 ? 2 : 1 ) : $_[1] eq '?' ? ( $_[0]<2 ? 9 : 3 ) - : $_[3] eq '?' ? 5 : 9 + : $_[3] eq '?' ? 5 + : 9 }->( split //, $_[0] ); } ``` @@ -38,7 +46,8 @@ sub digit_2400 { sub { $_[0] eq '?' ? ( $_[1]==4 && $_[3]==0 && $_[4]==0 || $_[1]<4 ? 2 : 1 ) : $_[1] eq '?' ? ( $_[0]<2 ? 9 : $_[3]==0 && $_[4]==0 ? 4 : 3 ) - : $_[3] eq '?' ? 5 : 9 + : $_[3] eq '?' ? 5 + : 9 }->( split //, $_[0] ); } ``` @@ -49,6 +58,12 @@ sub digit_2400 { ## Solution +Again we use and IIFE. This time taking the value of the sorted values from `%sc`. For the method to be true. The sorted values must be: + + * `n`, `n`, `n`, ...., `n`, `n+1` + +So we just need to check the 1st with the (n-1)st and the (n-1)st with the last! + ```perl sub check { my %sc; $sc{$_} ++ for split //,$_[0]; -- cgit From 9e183fb259a4f5cbd51796fe06a9b15b42195757 Mon Sep 17 00:00:00 2001 From: James Smith Date: Mon, 5 Dec 2022 08:20:41 +0000 Subject: Update README.md --- challenge-194/james-smith/README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/challenge-194/james-smith/README.md b/challenge-194/james-smith/README.md index 5480e2db42..579581f98f 100644 --- a/challenge-194/james-smith/README.md +++ b/challenge-194/james-smith/README.md @@ -58,15 +58,21 @@ sub digit_2400 { ## Solution -Again we use and IIFE. This time taking the value of the sorted values from `%sc`. For the method to be true. The sorted values must be: +Again we use and IIFE. This time taking the value of the sorted values from `%f` (being the frequencies of each letter). +For the method to be true. The sorted values must be: * `n`, `n`, `n`, ...., `n`, `n+1` -So we just need to check the 1st with the (n-1)st and the (n-1)st with the last! +In fact if we reverse the sort (switch `$a` and `$b` around in the comparison) we have: + + * `n+1`, `n`, `n`, ...., `n`, `n` + +So check to see if the first is one more than the second and the second is the same +as the last. ```perl sub check { - my %sc; $sc{$_} ++ for split //,$_[0]; - sub { @_>2 && $_[0]==$_[1]+1 && $_[-1]==$_[1] ? 1 : 0 }->(sort {$b<=>$a} values %sc); + my %f; $f{$_} ++ for split //, $_[0]; + sub { @_>2 && $_[0]==$_[1]+1 && $_[-1]==$_[1] }->(sort {$b<=>$a} values %f) || 0; } ``` -- cgit From 0d29be3c9b1a5c01572f9ee22796c3dd45acd952 Mon Sep 17 00:00:00 2001 From: James Smith Date: Mon, 5 Dec 2022 08:21:24 +0000 Subject: Update ch-2.pl --- challenge-194/james-smith/perl/ch-2.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/challenge-194/james-smith/perl/ch-2.pl b/challenge-194/james-smith/perl/ch-2.pl index 167860f910..c99ad2db52 100644 --- a/challenge-194/james-smith/perl/ch-2.pl +++ b/challenge-194/james-smith/perl/ch-2.pl @@ -13,6 +13,6 @@ is( check( $_->[0] ), $_->[1] ) for @TESTS; done_testing(); sub check { - my %sc; $sc{$_} ++ for split //,$_[0]; - sub { @_>2 && $_[0]==$_[1]+1 && $_[-1]==$_[1] ? 1 : 0 }->(sort {$b<=>$a} values %sc); + my %f; $f{$_} ++ for split //, $_[0]; + sub { @_>2 && $_[0]==$_[1]+1 && $_[-1]==$_[1] }->( sort {$b<=>$a} values %f ) || 0; } -- cgit From 70bc4f29beb9c6975ef65840c9bf99c43f893347 Mon Sep 17 00:00:00 2001 From: James Smith Date: Mon, 5 Dec 2022 08:23:46 +0000 Subject: Update ch-1.pl --- challenge-194/james-smith/perl/ch-1.pl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/challenge-194/james-smith/perl/ch-1.pl b/challenge-194/james-smith/perl/ch-1.pl index c0583712de..35d08c6689 100644 --- a/challenge-194/james-smith/perl/ch-1.pl +++ b/challenge-194/james-smith/perl/ch-1.pl @@ -23,14 +23,16 @@ sub digit_2359 { sub { $_[0] eq '?' ? ( $_[1]<4 ? 2 : 1 ) : $_[1] eq '?' ? ( $_[0]<2 ? 9 : 3 ) - : $_[3] eq '?' ? 5 : 9 + : $_[3] eq '?' ? 5 + : 9 }->( split //, $_[0] ); } sub digit_2400 { sub { - $_[0] eq '?' ? ( $_[1]==4 && $_[3]==0 && $_[4]==0 || $_[1]<4 ? 2 : 1 ) - : $_[1] eq '?' ? ( $_[0]<2 ? 9 : $_[3]==0 && $_[4]==0 ? 4 : 3 ) - : $_[3] eq '?' ? 5 : 9 + $_[0] eq '?' ? ( $_[1]<4 ? 2 : $_[1]==4 && $_[3]==0 && $_[4]==0 ? 2 : 1 ) + : $_[1] eq '?' ? ( $_[0]<2 ? 9 : $_[3]==0 && $_[4]==0 ? 4 : 3 ) + : $_[3] eq '?' ? 5 + : 9 }->( split //, $_[0] ); } -- cgit From a9ea6c43fba6620b202e52edb5616c14337962bf Mon Sep 17 00:00:00 2001 From: James Smith Date: Mon, 5 Dec 2022 08:24:09 +0000 Subject: Update README.md --- challenge-194/james-smith/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/challenge-194/james-smith/README.md b/challenge-194/james-smith/README.md index 579581f98f..50abcdd7c8 100644 --- a/challenge-194/james-smith/README.md +++ b/challenge-194/james-smith/README.md @@ -44,8 +44,8 @@ My original code allowed `24:00` as a valid value - this gave a slightly more co ```perl sub digit_2400 { sub { - $_[0] eq '?' ? ( $_[1]==4 && $_[3]==0 && $_[4]==0 || $_[1]<4 ? 2 : 1 ) - : $_[1] eq '?' ? ( $_[0]<2 ? 9 : $_[3]==0 && $_[4]==0 ? 4 : 3 ) + $_[0] eq '?' ? ( $_[1]<4 ? 2 : $_[1]==4 && $_[3]==0 && $_[4]==0 ? 2 : 1 ) + : $_[1] eq '?' ? ( $_[0]<2 ? 9 : $_[3]==0 && $_[4]==0 ? 4 : 3 ) : $_[3] eq '?' ? 5 : 9 }->( split //, $_[0] ); -- cgit