The weekly challenge 234 - Task 1: Common Characters

 1 #!/usr/bin/perl
 2 # https://theweeklychallenge.org/blog/perl-weekly-challenge-234/#TASK1
 3 #
 4 # Task 1: Common Characters
 5 # =========================
 6 #
 7 # You are given an array of words made up of alphabetic characters only.
 8 #
 9 # Write a script to return all alphabetic characters that show up in all words
10 # including duplicates.
11 #
12 ## Example 1
13 ##
14 ## Input: @words = ("java", "javascript", "julia")
15 ## Output: ("j", "a")
16 #
17 ## Example 2
18 ##
19 ## Input: @words = ("bella", "label", "roller")
20 ## Output: ("e", "l", "l")
21 #
22 ## Example 3
23 ##
24 ## Input: @words = ("cool", "lock", "cook")
25 ## Output: ("c", "o")
26 #
27 ############################################################
28 ##
29 ## discussion
30 ##
31 ############################################################
32 #
33 # First, we split each word into its characters, which we count.
34 # Then, for each character in the first word, we take care the
35 # value for that character exists for all other words as well, just
36 # set to 0 if the character doesn't appear in the other word.
37 # Then we calculate the minimum of times each character is in each
38 # word, so we can calculate the minimum of occurences for each
39 # character.
40 # In the end, we put as many of each character into our result
41 # set as we found to be the minimum of occurences in each word.
42 
43 use strict;
44 use warnings;
45 use Data::Dumper;
46 
47 common_characters("java", "javascript", "julia");
48 common_characters("bella", "label", "roller");
49 common_characters("cool", "lock", "cook");
50 
51 sub common_characters {
52    my @words = @_;
53    print "Input: (" . join(", ", @words) . ")\n";
54    my $data;
55    foreach my $word (@words) {
56       my @chars = split //, $word;
57       foreach my $char (@chars) {
58          $data->{$word}->{$char}++;
59       }
60    }
61    my $min;
62    foreach my $char (keys %{$data->{$words[0]}}) {
63       foreach my $word (@words) {
64          $data->{$word}->{$char} //= 0;
65       }
66       $min->{$char} = min( map { $data->{$_}->{$char} } @words );
67    }
68    my @result;
69    foreach my $char (keys %{$data->{$words[0]}}) {
70       foreach my $count (1..$min->{$char}) {
71          push @result, $char;
72       }
73    }
74    print "Output: (" . join(", ", @result) . ")\n";
75 }
76 
77 sub min {
78    my @elems = @_;
79    my $result = shift @elems;
80    foreach my $elem (@elems) {
81       $result = $elem if $elem < $result;
82    }
83    return $result;
84 }