aboutsummaryrefslogtreecommitdiff
path: root/challenge-007
diff options
context:
space:
mode:
authorGustavo L. de M. Chaves <gustavo@cpqd.com.br>2019-05-08 22:28:40 -0300
committerGustavo L. de M. Chaves <gustavo@cpqd.com.br>2019-05-08 22:29:24 -0300
commit3ac4799328b78382bd071404cb508535c1118b9d (patch)
treea689ac0f12e635e2619818bdd1b5d606f7673539 /challenge-007
parent8ffb273586a482f26b3872d4c8b761300ca35798 (diff)
downloadperlweeklychallenge-club-3ac4799328b78382bd071404cb508535c1118b9d.tar.gz
perlweeklychallenge-club-3ac4799328b78382bd071404cb508535c1118b9d.tar.bz2
perlweeklychallenge-club-3ac4799328b78382bd071404cb508535c1118b9d.zip
Add Gustavo Chaves's solutions to challenge 007
Diffstat (limited to 'challenge-007')
-rwxr-xr-xchallenge-007/gustavo-chaves/perl5/ch-1.pl14
-rwxr-xr-xchallenge-007/gustavo-chaves/perl5/ch-2.pl86
2 files changed, 100 insertions, 0 deletions
diff --git a/challenge-007/gustavo-chaves/perl5/ch-1.pl b/challenge-007/gustavo-chaves/perl5/ch-1.pl
new file mode 100755
index 0000000000..d54ace4779
--- /dev/null
+++ b/challenge-007/gustavo-chaves/perl5/ch-1.pl
@@ -0,0 +1,14 @@
+#!/usr/bin/env perl
+
+# Print all the niven numbers from 0 to 50 inclusive, each on their own line. A
+# niven number is a non-negative number that is divisible by the sum of its
+# digits.
+
+use 5.026;
+use strict;
+use warnings;
+use List::Util 'sum';
+
+for (1 .. 50) {
+ say unless $_ % sum split //;
+}
diff --git a/challenge-007/gustavo-chaves/perl5/ch-2.pl b/challenge-007/gustavo-chaves/perl5/ch-2.pl
new file mode 100755
index 0000000000..ddb900251f
--- /dev/null
+++ b/challenge-007/gustavo-chaves/perl5/ch-2.pl
@@ -0,0 +1,86 @@
+#!/usr/bin/env perl
+
+# A word ladder is a sequence of words [w0, w1, …, wn] such that each word wi in
+# the sequence is obtained by changing a single character in the word wi-1. All
+# words in the ladder must be valid English words.
+
+use 5.026;
+use strict;
+use autodie;
+use warnings;
+use List::Util qw(reduce uniq);
+use Path::Tiny;
+
+# Implements Dijkstra's Algorith as described in
+# https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm#Pseudocode
+
+sub first_shortest_ladder {
+ my ($source, $target, $wordlist) = @_;
+
+ # Build an adjacency graph from $wordlist
+
+ my (%graph, %dist, %prev);
+
+ my $length = length $source;
+ for my $i (0 .. @$wordlist-2) {
+ my $word_i = $wordlist->[$i];
+ foreach my $word_j (@{$wordlist}[$i+1 .. @$wordlist-1]) {
+ my $distance = 0;
+ for (my $k = $length; $k >= 0; --$k) {
+ $distance += 1 if substr($word_i, $k, 1) ne substr($word_j, $k, 1);
+ }
+ if ($distance == 1) {
+ $graph{$word_i}{$word_j} = undef;
+ $graph{$word_j}{$word_i} = undef;
+ }
+ }
+ $dist{$word_i} = @$wordlist + 1; # infinity
+ $prev{$word_i} = undef;
+ }
+
+ $dist{$source} = 0;
+
+ while (%graph) {
+ my $u = reduce {$dist{$a} < $dist{$b} ? $a : $b} keys %graph;
+
+ my $neighbors = delete $graph{$u};
+
+ last if $u eq $target; # found a shortest path to $target
+
+ foreach my $v (grep {exists $graph{$_}} keys %$neighbors) {
+ my $alt = $dist{$u} + 1;
+ if ($alt < $dist{$v}) {
+ $dist{$v} = $alt;
+ $prev{$v} = $u;
+ }
+ }
+ }
+
+ # Return an empty list if no path was found to $target
+ return if exists $graph{$target};
+
+ my @path = ($target);
+
+ for (my $u = $target; $prev{$u}; $u = $prev{$u}) {
+ unshift @path, $prev{$u};
+ }
+
+ return @path;
+}
+
+@ARGV == 2 or die "Usage: $0 FROM TO\n";
+
+my ($source, $target) = map {lc} @ARGV;
+
+my $length = length $source;
+
+my @words =
+ uniq
+ sort
+ map {lc}
+ grep {length == $length}
+ path('/usr/share/dict/words')->lines({chomp => 1});
+
+my @ladder = first_shortest_ladder($source, $target, \@words);
+
+say join "\n", @ladder;