The weekly challenge 221 - Task 1: Good Strings

 1 #!/usr/bin/perl
 2 # https://theweeklychallenge.org/blog/perl-weekly-challenge-221/#TASK1
 3 #
 4 # Task 1: Good Strings
 5 # ====================
 6 #
 7 # You are given a list of @words and a string $chars.
 8 #
 9 ##  A string is good if it can be formed by characters from $chars, each character can be used only once.
10 #
11 #
12 # Write a script to return the sum of lengths of all good strings in words.
13 #
14 ## Example 1
15 ##
16 ## Input: @words = ("cat", "bt", "hat", "tree")
17 ##        $chars = "atach"
18 ## Output: 6
19 ##
20 ## The good strings that can be formed are "cat" and "hat" so the answer is 3 + 3 = 6.
21 #
22 ## Example 2
23 ##
24 ## Input: @words = ("hello", "world", "challenge")
25 ##        $chars = "welldonehopper"
26 ## Output: 10
27 ##
28 ## The strings that can be formed are "hello" and "world" so the answer is 5 + 5 = 10.
29 #
30 ############################################################
31 ##
32 ## discussion
33 ##
34 ############################################################
35 #
36 # For each word in the list, we calculate the length if it is a
37 # good string. Otherwise, we take 0 as the value. The result is
38 # the sum of all results from the individual strings.
39 # We calculate the length of the individual strings by first
40 # checking if each character in the word has at least the same
41 # amount of occurences in the "chars" word. We do this by
42 # creating a map of the characters in both the word and the
43 # "chars" string. If for each character in the word there
44 # is at least the same amount of the same character in the
45 # "chars" string, we add those up. If this isn't the case
46 # then we can return 0 for this word.
47 
48 use strict;
49 use warnings;
50 use Data::Dumper;
51 
52 good_strings( ["cat", "bt", "hat", "tree"], "atach" );
53 good_strings( ["hello", "world", "challenge"], "welldonehopper" );
54 
55 sub good_strings {
56    my ($words, $chars) = @_;
57    my $result = 0;
58    print "Input: (" . join(", ", @$words) . "); \"$chars\"\n";
59    foreach my $word (@$words) {
60       $result += good_string_result($word, $chars);
61    }
62    print "Output: $result\n";
63 }
64 
65 sub good_string_result {
66    my ($word, $chars) = @_;
67    my ($wordmap, $charmap);
68    my $result = 0;
69    map { $wordmap->{$_}++ } split //, $word;
70    map { $charmap->{$_}++ } split //, $chars;
71    foreach my $c  (keys %$wordmap) {
72       return 0 unless $charmap->{$c};
73       return 0 unless $charmap->{$c} >= $wordmap->{$c};
74       $result += $wordmap->{$c};
75    }
76    return $result;
77 }