aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--challenge-216/peter-campbell-smith/blog.txt1
-rwxr-xr-xchallenge-216/peter-campbell-smith/perl/ch-1.pl55
-rwxr-xr-xchallenge-216/peter-campbell-smith/perl/ch-2.pl103
3 files changed, 159 insertions, 0 deletions
diff --git a/challenge-216/peter-campbell-smith/blog.txt b/challenge-216/peter-campbell-smith/blog.txt
new file mode 100644
index 0000000000..776d8018e1
--- /dev/null
+++ b/challenge-216/peter-campbell-smith/blog.txt
@@ -0,0 +1 @@
+http://ccgi.campbellsmiths.force9.co.uk/challenge/216
diff --git a/challenge-216/peter-campbell-smith/perl/ch-1.pl b/challenge-216/peter-campbell-smith/perl/ch-1.pl
new file mode 100755
index 0000000000..4e6ac75dbc
--- /dev/null
+++ b/challenge-216/peter-campbell-smith/perl/ch-1.pl
@@ -0,0 +1,55 @@
+#!/usr/bin/perl
+
+use v5.16; # The Weekly Challenge - 2023-05-08
+use utf8; # Week 216 task 1 - Registration number
+use strict; # Peter Campbell Smith
+use warnings; # Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge
+
+use List::Uniq 'uniq';
+
+registration_number(['job', 'james', 'bjorg'], '007 JB');
+registration_number(['crack', 'road', 'rac'], 'C7 RA2');
+registration_number(['superlative', 'reply', 'parallel', 'ppeerrll',
+ 'pert', 'earl'], 'PERL 216');
+registration_number(['none', 'of', 'these', 'should', 'work'], '12345');
+
+sub registration_number {
+
+ my (@words, $reg_no, $sorted_reg_no, $word, $sorted_word, $rubric);
+
+ # initialise
+ @words = @{$_[0]};
+ $reg_no = $_[1];
+
+ # sort, eliminate non-letters, make unique and lower case $reg_no
+ $reg_no =~ s|[^a-z]||ig;
+ $sorted_reg_no = sort_word($reg_no);
+ $rubric = '';
+
+ # nothing will match if $sorted_reg_no is empty (eg $reg_no == '12345')
+ if ($sorted_reg_no) {
+
+ # loop over words
+ for $word (@words) {
+ $sorted_word = sort_word($word);
+
+ # remove from $sorted_word any letter not in reg_no
+ $sorted_word =~ s|[^$sorted_reg_no]||gi;
+
+ # and we have a result if $sorted_word and $sorted_reg_no are the same
+ $rubric .= qq['$word', ]
+ if ($sorted_word eq $sorted_reg_no);
+ }
+ }
+
+ say qq[\nInput: \@words = ('] . join(q[', '], @words) . qq['), \$reg = '$_[1]'];
+ say qq[Output: (] . substr($rubric, 0, -2) . q[)];
+}
+
+sub sort_word {
+
+ # returns unique letters in word, sorted and lower-cased
+
+ return join('', sort(uniq(split('', lc($_[0])))));
+}
+
diff --git a/challenge-216/peter-campbell-smith/perl/ch-2.pl b/challenge-216/peter-campbell-smith/perl/ch-2.pl
new file mode 100755
index 0000000000..765a0e1070
--- /dev/null
+++ b/challenge-216/peter-campbell-smith/perl/ch-2.pl
@@ -0,0 +1,103 @@
+#!/usr/bin/perl
+
+use v5.16; # The Weekly Challenge - 2023-05-08
+use utf8; # Week 216 task 2 - Word stickers
+use strict; # Peter Campbell Smith
+use warnings; # Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge
+
+word_stickers(['perl','raku','python'], 'peon');
+word_stickers(['love','hate','angry'], 'goat');
+word_stickers(['come','nation','delta'], 'accommodation');
+word_stickers(['nail', 'sited', 'belt', 'marsh'], 'antidisestablishmentarianism');
+
+sub word_stickers {
+
+ my ($best, $count, $how_many, $most, $need_to_match, $occurs, $occurs_in, $rubric, $s,
+ $s1, $stars, $ties, $times, $times_all, $times_here, $to_match, $word, $x, $x1, $z, %in_sticker, %in_word, %needed, %used, @stickers);
+
+ # initialise
+ @stickers = @{$_[0]};
+ $word = $_[1];
+ $rubric = '';
+ say qq[\nInput: \@stickers = ('] . join(qq[', '], @stickers) .
+ qq['), \$word = '$word'];
+
+ # create $in_word{$x} as quantity of $x in $word
+ while ($word =~ m|([a-z])|g) {
+ $in_word{$1} ++;
+ }
+
+ # create $in_sticker{$x}{$s} as quantity of $x in $stickers[$s]
+ for ($s = 0; $s < scalar @stickers; $s ++) {
+ while ($stickers[$s] =~ m|([a-z])|g) {
+ $in_sticker{$1}{$s} ++;
+ }
+ }
+
+ # loop over letters in $word
+ for $x (sort keys %in_word) {
+ next unless $in_word{$x} > 0;
+
+ # check for $x n times in stickers and >=n times in word
+ for $x (keys %in_word) {
+ $most = 0;
+
+ # find sticker with most $x - this may not be the best
+ $times_all = 0;
+ for ($s = 0; $s < scalar @stickers; $s ++) {
+ $times_here = ($in_sticker{$x}{$s} or 0);
+ $times_all += $times_here;
+ if ($times_here > $most) {
+ $most = $times_here;
+ $best = $s;
+ }
+ }
+
+ # check for impossibility (letter from word not in any sticker)
+ if ($most == 0) {
+ say qq[Output: 0 - '$x' not in any sticker];
+ return;
+ }
+
+ # if $x occurs more times in word than in stickers,
+ # need to add duplicate stickers
+ $need_to_match = $in_word{$x};
+ $z = 0;
+ while ($need_to_match > $times_all) {
+ $s1 = scalar @stickers;
+ $stickers[$s1] = $stickers[$best] . '*';
+ for $x1 (keys %in_word) {
+ $in_sticker{$x1}{$s1} = $in_sticker{$x1}{$best};
+ }
+ $need_to_match -= $in_sticker{$x}{$best};
+ }
+
+ # now we have enough stickers
+ $need_to_match = $in_word{$x};
+ for ($s = 0; $s < scalar @stickers; $s ++) {
+ next unless ($in_sticker{$x}{$s} or 0);
+ $to_match = $need_to_match > $in_sticker{$x}{$s} ?
+ $in_sticker{$x}{$s} : $need_to_match;
+ $need_to_match -= $to_match;
+ $used{$s} .= $x x $to_match;
+ $in_sticker{$x}{$s} = 0;
+ $in_word{$x} = 0;
+ $needed{$s} = 1;
+ last if $need_to_match <= 0;
+ }
+ $in_word{$x} = 0;
+ }
+ }
+
+ # format output
+ $count = 0;
+ for $s (keys %needed) {
+ $count ++;
+ }
+ say qq[Output: $count];
+ for $s (sort keys %used) {
+ say qq[ '$used{$s}' from '$stickers[$s]'];
+ $stars ++ if $stickers[$s] =~ m|\*|;
+ }
+ say qq[ * indicates duplicated sticker] if $stars;
+}