diff options
| author | Flavio Poletti <flavio@polettix.it> | 2022-04-19 22:36:47 +0200 |
|---|---|---|
| committer | Flavio Poletti <flavio@polettix.it> | 2022-04-19 22:36:47 +0200 |
| commit | b6961c307f4f474347720f3c25044652ecce060e (patch) | |
| tree | 7426f01cb8e920ebc7402908eaa9031010eb6dcd /challenge-161 | |
| parent | ccb9e0b8e0008e5fa71768a88620ec0478a8ffaf (diff) | |
| download | perlweeklychallenge-club-b6961c307f4f474347720f3c25044652ecce060e.tar.gz perlweeklychallenge-club-b6961c307f4f474347720f3c25044652ecce060e.tar.bz2 perlweeklychallenge-club-b6961c307f4f474347720f3c25044652ecce060e.zip | |
Add polettix's solution to challenge-161
Diffstat (limited to 'challenge-161')
| -rw-r--r-- | challenge-161/polettix/blog.txt | 1 | ||||
| -rw-r--r-- | challenge-161/polettix/blog1.txt | 1 | ||||
| -rw-r--r-- | challenge-161/polettix/perl/ch-1.pl | 20 | ||||
| -rw-r--r-- | challenge-161/polettix/perl/ch-2.pl | 65 | ||||
| -rw-r--r-- | challenge-161/polettix/raku/ch-1.raku | 19 | ||||
| -rw-r--r-- | challenge-161/polettix/raku/ch-2.raku | 56 |
6 files changed, 162 insertions, 0 deletions
diff --git a/challenge-161/polettix/blog.txt b/challenge-161/polettix/blog.txt new file mode 100644 index 0000000000..a3ed1c7ff8 --- /dev/null +++ b/challenge-161/polettix/blog.txt @@ -0,0 +1 @@ +https://github.polettix.it/ETOOBUSY/2022/04/19/pwc161-abecedarian-words/ diff --git a/challenge-161/polettix/blog1.txt b/challenge-161/polettix/blog1.txt new file mode 100644 index 0000000000..e9277bccbf --- /dev/null +++ b/challenge-161/polettix/blog1.txt @@ -0,0 +1 @@ +https://github.polettix.it/ETOOBUSY/2022/04/20/pwc161-pangrams/ diff --git a/challenge-161/polettix/perl/ch-1.pl b/challenge-161/polettix/perl/ch-1.pl new file mode 100644 index 0000000000..6df98b1cf7 --- /dev/null +++ b/challenge-161/polettix/perl/ch-1.pl @@ -0,0 +1,20 @@ +#!/usr/bin/env perl +use v5.24; +use warnings; +use experimental 'signatures'; +no warnings 'experimental::signatures'; + +say join ' ', all_sorted_abecedarian_in(shift); + +sub all_sorted_abecedarian_in ($dictionary) { + sort { length($a) <=> length($b) } all_abecedarian_in($dictionary); +} + +sub all_abecedarian_in ($dictionary) { + open my $fh, '<:encoding(utf-8)', $dictionary or die "open(): $!\n"; + grep { is_abecedarian($_) } map { s{\s+\z}{}rmxs } readline $fh; +} + +sub is_abecedarian ($word) { + fc $word eq join '', sort split m{}mxs, fc $word; +} diff --git a/challenge-161/polettix/perl/ch-2.pl b/challenge-161/polettix/perl/ch-2.pl new file mode 100644 index 0000000000..3dd7ee14ee --- /dev/null +++ b/challenge-161/polettix/perl/ch-2.pl @@ -0,0 +1,65 @@ +#!/usr/bin/env perl +use v5.24; +use warnings; +use experimental 'signatures'; +no warnings 'experimental::signatures'; + +use HTTP::Tiny; +use constant DEFAULT_BOOK_URL => + 'https://www.gutenberg.org/cache/epub/308/pg308.txt'; +use FindBin '$Bin'; +use List::Util 'sum'; + +# Assume Unixish filesystem +my $dictionary_file = shift // "$Bin/../../../data/dictionary.txt"; +my $book_url = shift // DEFAULT_BOOK_URL; + +my $dictionary = read_dictionary($dictionary_file); +my $book = get_stuff($book_url); +my $model = markov_model($book, $dictionary); + +my ($src, $word, %hits, @trail); +while (keys(%hits) < 26) { + $src = $model->{$word // ''} // $dictionary; + push @trail, $word = random_word_draw($src); + ++$hits{$_} for split m{}mxs, $word; +} + +say join ' ', @trail; + +sub random_word_draw ($weighted_candidates) { + my $total = sum values $weighted_candidates->%*; + my $draw = rand $total; # definitely space for improvement... + for my $word (keys $weighted_candidates->%*) { + $draw -= $weighted_candidates->{$word}; + return $word if $draw < 0; + } + die "unreached, hopefully\n"; +} + +sub read_dictionary ($filename) { + open my $fh, '<:encoding(utf-8)', $filename or die "open(): $!\n"; + return { map {chomp; $_ => 1} readline $fh }; +} + +sub get_stuff ($url) { + my $response = HTTP::Tiny->new->get($url); + die "$response->{status} $response->{reason}\n" + unless $response->{success}; + return $response->{content}; +} + +sub markov_model ($text, $dictionary) { + my $previous = undef; + my %successors_for; + for my $word (split m{[^a-z]+}mxs, lc $text) { + if ($dictionary->{$word}) { + $successors_for{$previous}{$word}++ if defined $previous; + $previous = $word; + } + else { + $previous = undef; # restart + } + } + return \%successors_for; +} diff --git a/challenge-161/polettix/raku/ch-1.raku b/challenge-161/polettix/raku/ch-1.raku new file mode 100644 index 0000000000..0ca3310b45 --- /dev/null +++ b/challenge-161/polettix/raku/ch-1.raku @@ -0,0 +1,19 @@ +#!/usr/bin/env raku +use v6; +sub MAIN (Str:D $dictionary) { + all-sorted-abecedarian-in($dictionary).put; +} + +sub all-sorted-abecedarian-in (Str $dictionary) { + all-abecedarian-in($dictionary).sort({$^a.chars <=> $^b.chars}).Array; +} + +sub all-abecedarian-in (Str $dictionary) { + $dictionary.IO.lines.grep({is-abecedarian($_)}).Array; +} + +sub is-abecedarian (Str $word) { + $word.fc.comb.sort.join('') eq $word.fc; +} + +# be chill or annoy forty bossy nosy cops diff --git a/challenge-161/polettix/raku/ch-2.raku b/challenge-161/polettix/raku/ch-2.raku new file mode 100644 index 0000000000..248be9c7b5 --- /dev/null +++ b/challenge-161/polettix/raku/ch-2.raku @@ -0,0 +1,56 @@ +#!/usr/bin/env raku +use v6; +use HTTP::Tiny; + +constant \DEFAULT_BOOK_URL = + 'https://www.gutenberg.org/cache/epub/308/pg308.txt'; + +sub MAIN (Str:D $dictionary-file, Str:D $book-url = DEFAULT_BOOK_URL) { + my $dictionary = read-dictionary($dictionary-file); + my $book = get-stuff($book-url); + my $model = markov-model($book, $dictionary); + + my ($src, $word, %hits); + my @trail = gather while %hits.elems < 26 { + $src = $model{$word // ''} // $dictionary; + take $word = random-word-draw($src); + ++%hits{$_} for $word.comb; + }; + @trail.join(' ').put; +} + +sub random-word-draw ($weighted-candidates) { + my $total = $weighted-candidates.values.sum; + my $draw = $total.rand; + for $weighted-candidates.kv -> $word, $weight { + $draw -= $weight; + return $word if $draw < 0; + } + die "unreached, hopefully\n"; +} + +sub read-dictionary ($filename) { + $filename.IO.words.map({$_ => 1}).Hash; +} + +sub get-stuff ($url) { + my $response = HTTP::Tiny.new.get($url); + die "$response<status> $response<reason>\n" + unless $response<success>; + return $response<content>.decode; +} + +sub markov-model ($text, $dictionary) { + my $previous = Nil; + my $successors-for; + for $text.lc.split(/<-[ a..z ]>/) -> $word { + if $dictionary{$word}:exists { + $successors-for{$previous}{$word}++ if defined $previous; + $previous = $word; + } + else { + $previous = Nil; # restart + } + } + return $successors-for; +} |
