diff options
| author | Dave Jacoby <jacoby.david@gmail.com> | 2019-12-10 18:59:59 -0500 |
|---|---|---|
| committer | Dave Jacoby <jacoby.david@gmail.com> | 2019-12-10 18:59:59 -0500 |
| commit | c0b8e1b35874b7c7a8f8e352110c5c576e2fadb0 (patch) | |
| tree | 304678c43f01b6ac59c025b854cff24948d73433 /challenge-038/dave-jacoby | |
| parent | 0b62deca1509247bdda0bb45d529677343f7b578 (diff) | |
| download | perlweeklychallenge-club-c0b8e1b35874b7c7a8f8e352110c5c576e2fadb0.tar.gz perlweeklychallenge-club-c0b8e1b35874b7c7a8f8e352110c5c576e2fadb0.tar.bz2 perlweeklychallenge-club-c0b8e1b35874b7c7a8f8e352110c5c576e2fadb0.zip | |
SOLVED!
Diffstat (limited to 'challenge-038/dave-jacoby')
| -rw-r--r-- | challenge-038/dave-jacoby/blog.txt | 1 | ||||
| -rw-r--r-- | challenge-038/dave-jacoby/perl5/ch-1.pl | 59 | ||||
| -rw-r--r-- | challenge-038/dave-jacoby/perl5/ch-2.pl | 161 |
3 files changed, 221 insertions, 0 deletions
diff --git a/challenge-038/dave-jacoby/blog.txt b/challenge-038/dave-jacoby/blog.txt new file mode 100644 index 0000000000..ff2f5895b1 --- /dev/null +++ b/challenge-038/dave-jacoby/blog.txt @@ -0,0 +1 @@ +https://jacoby.github.io/2019/12/10/words-and-dates-which-is-more-fun.html
\ No newline at end of file diff --git a/challenge-038/dave-jacoby/perl5/ch-1.pl b/challenge-038/dave-jacoby/perl5/ch-1.pl new file mode 100644 index 0000000000..a0ba00dcd4 --- /dev/null +++ b/challenge-038/dave-jacoby/perl5/ch-1.pl @@ -0,0 +1,59 @@ +#!/usr/bin/env perl + +use strict; +use warnings; +use utf8; +use feature qw{ postderef say signatures state switch }; +no warnings + qw{ experimental::postderef experimental::smartmatch experimental::signatures }; + +use Carp; +use DateTime; +use Try::Tiny; + +# handle command-line input +if (@ARGV) { say date_finder( $ARGV[0] ) } +# testing data +else { + for my $string (qw{2230120 1230120 1230231}) { + say date_finder($string) + } +} +exit; + +# break the date string into constituent parts, which will cause errors +# if ill-formatted, and then feed that into DateTime, for formatting, but +# also for catching non-existent dates, like 2220931, for example. +sub date_finder ( $string ) { + my ( $century, $year, $month, $day ) = $string =~ m{ + ^ # start of string + (\d) # century value 1-2 + (\d{2}) # year value 00-99 + (\d{2}) # month value 01-12 + (\d{2}) # day value 01-31, plus + $ # end of string + }mx; + + croak qq{Bad value: Century $century} if $century != 2 && $century != 1; + croak qq{Bad value: Month $month} if $month < 1 || $month > 12; + croak qq{Bad value: Day $day} if $day < 1 || $day > 31; + + try { + # here we make a DateTime object with the values give us + # and if those values are invalid, DateTime croaks, which + # we catch + my $y = ( $century == 2 ? '19' : '20' ) . $year; + my $date = DateTime->new( + year => $y, + month => $month, + day => $day, + time_zone => 'floating' + ); + return $date->ymd; + } + catch { + # catching the death of DateTime just to die our own way + # MIGHT be antisocial, but I accept it for now. + croak "Bad value: Input is not a day ($string)"; + }; +} diff --git a/challenge-038/dave-jacoby/perl5/ch-2.pl b/challenge-038/dave-jacoby/perl5/ch-2.pl new file mode 100644 index 0000000000..5199c56bee --- /dev/null +++ b/challenge-038/dave-jacoby/perl5/ch-2.pl @@ -0,0 +1,161 @@ +#!/usr/bin/env perl + +use strict; +use warnings; +use utf8; +use feature qw{ postderef say signatures state switch }; +no warnings + qw{ experimental::postderef experimental::smartmatch experimental::signatures }; + +use List::Util qw{ sum0 uniq }; +use Getopt::Long; + +my $verbose = 0; +GetOptions( + 'verbose' => \$verbose, +); + +my @tiles = get_tiles(); +@tiles = sort @tiles; +say join ' ', @tiles; +say '-------------'; + +my @list = permute_array(\@tiles); +my @list2; + +for my $array ( @list ) { + for my $l ( 0 .. 6 ) { + state $dict; + my @array2 = map { $array->[$_] } 0 .. $l; + my $word2 = join '', @array2; + next if $dict->{$word2}++; + push @list2, \@array2; + } +} + +my $best = ''; +my $top = 0; +for my $r ( @list2 ) { + my $word = join '', $r->@*; + my $score = score_word($word); + next if $score <1; + say join "\t", '', $score,$word if $verbose; + if ( $score > $top ) { + $best = $word; + $top = $score; + } +} + +say qq{ $best ($top)}; + +sub permute_array ( $array ) { + return $array if scalar $array->@* == 1; + my @response = map { + my $i = $_; + my $d = $array->[$i]; + my $copy->@* = $array->@*; + splice $copy->@*, $i, 1; + my @out = map { unshift $_->@*, $d; $_ } permute_array($copy); + @out + } 0 .. scalar $array->@* - 1; + return @response; +} + +sub get_tiles { + state $counts = counts(); + my @letters = split //, join '', map { $_ x $counts->{$_} } 'a' .. 'z'; + my @output; + for ( 1 .. 7 ) { + my $n = int rand scalar @letters; + my $l = $letters[$n]; + splice @letters, $n, 1; + push @output, $l; + } + return wantarray ? @output : \@output; +} + +sub score_word( $word ) { + state $words = words(); + state $counts = counts(); + state $scores = scores(); + return 0 unless length $word <= 7; + return 0 unless $words->{$word}; + for my $letter ( 'a' .. 'z' ) { + if ( $word =~ /$letter/ ) { + my $count = () = $word =~ /$letter/gi; + return 0 if $count > $counts->{$letter}; + } + } + return sum0 map { $scores->{$_} } split //, $word; +} + +sub words { + my $file = '/usr/share/dict/words'; + my $words; + if ( -f $file && open my $fh, '<', $file ) { + for my $word ( map { chomp; lc $_ } <$fh> ) { + $words->{$word} = 1; + } + } + return $words; +} + +sub counts { + my $counts; + map { $counts->{$_} = 2 } qw{ k q x }; + map { $counts->{$_} = 3 } qw{ d f g h j l o r v }; + map { $counts->{$_} = 4 } qw{ c m n }; + map { $counts->{$_} = 5 } qw{ b i p t u w y z }; + map { $counts->{$_} = 7 } qw{ s }; + map { $counts->{$_} = 8 } qw{ a }; + map { $counts->{$_} = 9 } qw{ e }; + return $counts; +} + +sub scores { + my $scores; + map { $scores->{$_} = 1 } qw{ a g i s u x z }; + map { $scores->{$_} = 2 } qw{ e j l r v y }; + map { $scores->{$_} = 3 } qw{ f d p w }; + map { $scores->{$_} = 4 } qw{ b n }; + map { $scores->{$_} = 5 } qw{ t o h m c }; + map { $scores->{$_} = 10 } qw{ k q }; + return $scores; +} + +__DATA__ + + + +Lets assume we have tiles as listed below, with an alphabet (A..Z) +printed on them. Each tile has a value, e.g. A (1 point), +B (4 points) etc. You are allowed to draw 7 tiles from the +lot randomly. Then try to form a word using the 7 tiles with +maximum points altogether. You don’t have to use all the 7 tiles +to make a word. You should try to use as many tiles as possible +to get the maximum points. + +For example, A (x8) means there are 8 tiles with letter A. +1 point + + A (x8), G (x3), I (x5), S (x7), U (x5), X (x2), Z (x5) + +2 points + + E (x9), J (x3), L (x3), R (x3), V (x3), Y (x5) + +3 points + + F (x3), D (x3), P (x5), W (x5) + +4 points + + B (x5), N (x4) + +5 points + + T (x5), O (x3), H (x3), M (x4), C (x4) + +10 points + + K (x2), Q (x2) |
