TL;DR

Here we are with TASK #1 from The Weekly Challenge #221. Enjoy!

# The challenge

You are given a list of @words and a string $chars. A string is good if it can be formed by characters from$chars, each character can be used only once.

Write a script to return the sum of lengths of all good strings in words.

Example 1

Input: @words = ("cat", "bt", "hat", "tree")
$chars = "atach" Output: 6 The good strings that can be formed are "cat" and "hat" so the answer is 3 + 3 = 6.  Example 2 Input: @words = ("hello", "world", "challenge")$chars = "welldonehopper"
Output: 10

The strings that can be formed are "hello" and "world" so the answer >     is 5 + 5 = 10.


# The questions

Given past challenges, one question is whether characters case matters or not. Additional questions would be:

• how should we handle accented characters?
• special characters, like quotation marks, hyphens, dots, etc.

# The solution

The Bag data structure fits perfectly, allowing us to check the inclusion via the aptly named âŠ† operator:

#!/usr/bin/env raku
use v6;
sub MAIN (*@words is copy) {
my $chars = @words.shift; say good-strings($chars, @words);
}

sub good-strings ($chars, @words) { my$cbag = $chars.comb.Bag; return @words.grep({ .comb.Bag âŠ†$cbag })Â».chars.sum;
}


Thereâ€™s no such thing in Perl, so we will leverage hashes to do the checks.

#!/usr/bin/env perl
use v5.24;
use warnings;
use experimental 'signatures';

say good_strings(@ARGV);

sub good_strings ($chars, @words) { my %available;$available{$_}++ for split m{}mxs,$chars;
my $retval = 0; WORD: for my$word (@words) {
my %residual;
for my $c (split m{}mxs,$word) {
$residual{$c} //= $available{$c} // 0;
next WORD if --$residual{$c} < 0;
}
$retval += length($word);
}
return \$retval;
}


Cheers and stay safe!

Comments? Octodon, , GitHub, Reddit, or drop me a line!