PWC 220

PWC 220

I switched to Raku this week. Both challenges are easier to tackle with Raku.

Challenge 1 (Common characters)

We are given a list of words, and asked to return a sorted list of the characters that are found in every word in the list (ignoring case). Here is the subroutine:

sub common_characters( @words ) {
    [(&)] @words.map( {$_.lc.comb.Set} )
}

For each word in @words, lowercase it, then split into characters, then store each unique character in a set. Then working on the resulting list of sets, call the reduce meta-operator [..] on the set intersection "(&)" operator, i.e., call [(&)] or "reduce using intersection" on the list of sets, to get the intersection of every set, or the characters that are found in every set. This returns a set, whose say method automatically prints the elements in sorted order (one of the task specifications).

Challenge 2 (Squareful)

We are given a list of integers @ints say. We are asked to identify every permutation of the list where every pair of adjacent elements adds up to a perfect square.

One could use an easy-to-code brute force approach where we check the condition for every possible permutation, though this is O(N!) and does not scale well. Somewhat more difficult is an O(N^2) approach that finds every pair of elements in @ints that adds up to a perfect square, and then uses this to construct the required permutations. 

I use the easy approach since all the test examples have just 3 elements, though I explicitly restrict my Raku subroutine to lists with three elements, to signal that the approach will not scale up. Here is my squareful subroutine with a couple of helper subroutines:

multi sub is_perfect_square( Int $a, Int $b ) {
    ($a+$b).sqrt %% 1;
}

multi sub is_perfect_square( @ints ) {
    ( [&&] (0 .. @ints-2).map( {&is_perfect_square( @ints[$_], @ints[$_+1] ) } ) );   
}

sub squareful (@ints where @ints.elems==3) {
    @ints.permutations
.unique( :with(&[eqv]) ).grep( {$_.&is_perfect_square} );
}

The subroutine &is_perfect_square taking two integer arguments checks if their sum is a perfect square. The subroutine &is_perfect_square taking an array as argument checks if every pair of adjacent elements adds up to a perfect square (by calling &is_perfect_square on each pair of adjacent elements). Finally, the subroutine &squareful calls &is_perfect_square on every permutation of @ints, and returns a list of those permutations that return True. This list can potentially contain duplicates, since the Raku permutations operator treats identical elements of a list as if they are different elements, so that for example,  (2,2,2).permutations returns six (identical) permutations rather than just a single permutation. So we call unique to eliminate duplicates.


Comments

Popular posts from this blog

PWC 227

PWC 234

PWC 249