aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--challenge-057/athanasius/perl/Trie.pm132
-rw-r--r--challenge-057/athanasius/perl/ch-2.pl90
2 files changed, 222 insertions, 0 deletions
diff --git a/challenge-057/athanasius/perl/Trie.pm b/challenge-057/athanasius/perl/Trie.pm
new file mode 100644
index 0000000000..b0fa0f871f
--- /dev/null
+++ b/challenge-057/athanasius/perl/Trie.pm
@@ -0,0 +1,132 @@
+#!perl
+
+################################################################################
+=comment
+
+Trie
+
+=cut
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2020 PerlMonk Athanasius #
+#--------------------------------------#
+
+use strict;
+use warnings;
+
+#===============================================================================
+package Node;
+#===============================================================================
+
+#-------------------------------------------------------------------------------
+sub new
+#-------------------------------------------------------------------------------
+{
+ my ($class, $parent, $letter) = @_;
+ my %self =
+ (
+ parent => $parent,
+ letter => $letter,
+ children => [],
+ );
+
+ return bless \%self, $class;
+}
+
+#-------------------------------------------------------------------------------
+sub add_child
+#-------------------------------------------------------------------------------
+{
+ my ($self, $child) = @_;
+
+ push $self->{children}->@*, $child;
+}
+
+#-------------------------------------------------------------------------------
+sub get_parent
+#-------------------------------------------------------------------------------
+{
+ my ($self) = @_;
+
+ return $self->{parent};
+}
+
+#-------------------------------------------------------------------------------
+sub get_letter
+#-------------------------------------------------------------------------------
+{
+ my ($self) = @_;
+
+ return $self->{letter};
+}
+
+#-------------------------------------------------------------------------------
+sub get_child
+#-------------------------------------------------------------------------------
+{
+ my ($self, $letter) = @_;
+
+ for my $child ( $self->{children}->@* )
+ {
+ return $child if defined $child && $child->{letter} eq $letter;
+ }
+
+ return undef;
+}
+
+#-------------------------------------------------------------------------------
+sub num_children
+#-------------------------------------------------------------------------------
+{
+ my ($self) = @_;
+
+ return scalar $self->{children}->@*;
+}
+
+#===============================================================================
+package Trie;
+#===============================================================================
+
+#-------------------------------------------------------------------------------
+sub new
+#-------------------------------------------------------------------------------
+{
+ my ($class) = @_;
+ my %self = (root => Node->new(undef, ''));
+
+ return bless \%self, $class;
+}
+
+#-------------------------------------------------------------------------------
+sub insert_word
+#-------------------------------------------------------------------------------
+{
+ my ($self, $word) = @_;
+
+ my $node = $self->{root};
+
+ for my $letter (split //, $word)
+ {
+ my $child = $node->get_child($letter);
+
+ if (defined $child)
+ {
+ $node = $child;
+ }
+ else
+ {
+ my $new_child = Node->new($node, $letter);
+
+ $node->add_child($new_child);
+
+ $node = $new_child;
+ }
+ }
+
+ return $node;
+}
+
+################################################################################
+1;
+################################################################################
diff --git a/challenge-057/athanasius/perl/ch-2.pl b/challenge-057/athanasius/perl/ch-2.pl
new file mode 100644
index 0000000000..c22a4ddf22
--- /dev/null
+++ b/challenge-057/athanasius/perl/ch-2.pl
@@ -0,0 +1,90 @@
+#!perl
+
+################################################################################
+=comment
+
+Perl Weekly Challenge 057
+=========================
+
+Task #2
+-------
+*Shortest Unique Prefix*
+
+Write a script to find the *shortest unique prefix* for each word in the given
+list. The prefixes will not necessarily be of the same length.
+
+*Sample Input*
+
+ [ "alphabet", "book", "carpet", "cadmium", "cadeau", "alpine" ]
+
+*Expected Output*
+
+ [ "alph", "b", "car", "cadm", "cade", "alpi" ]
+
+=cut
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2020 PerlMonk Athanasius #
+#--------------------------------------#
+
+use strict;
+use warnings;
+use List::Util qw( max );
+use lib '.';
+use Trie;
+
+#-------------------------------------------------------------------------------
+BEGIN
+#-------------------------------------------------------------------------------
+{
+ $| = 1;
+ print "\n";
+}
+
+#===============================================================================
+MAIN:
+#===============================================================================
+{
+ print "Challenge 057, Task #2: Shortest Unique Prefix (Perl)\n\n";
+
+ my @words = qw( alphabet book carpet cadmium cadeau alpine );
+ my $width = max map { length } @words;
+
+ # Create a trie tree of the words, and a hash mapping each word to its last
+ # node in the trie
+
+ my $trie = Trie->new();
+ my %word_ends;
+
+ $word_ends{$_} = $trie->insert_word($_) for @words;
+
+ # Find and print the shortest unique prefix for each word
+
+ for my $word (@words)
+ {
+ my ($prefix, $last_letter);
+ my $in_prefix = 0;
+
+ for (my $node = $word_ends{$word}; $node; $node = $node->get_parent)
+ {
+ if ($in_prefix)
+ {
+ $prefix = $node->get_letter . $prefix;
+ }
+ elsif ($node->num_children > 1)
+ {
+ $prefix = $node->get_letter . $last_letter;
+ $in_prefix = 1;
+ }
+ else
+ {
+ $last_letter = $node->get_letter;
+ }
+ }
+
+ printf "%-*s --> %s\n", $width, $word, $prefix;
+ }
+}
+
+################################################################################