PWC166 - K-Directory Diff (Raku solution)


A Raku addendum to TASK #2 from The Weekly Challenge #166. Enjoy!

The algorithm is explained in previous post PWC166 - K-Directory Diff. ‘nuff said.

#!/usr/bin/env raku
use v6;

put k-directory-diff(< dir_a dir_b dir_c >);

sub k-directory-diff (*@dirs) {
   my @lists = select-incompletes({list-from($_)}));
   for @lists Z @dirs -> ($l, $d) { $l.unshift: $d }
   return render-columns(@lists);

sub list-from ($dir) {
   ${.basename ~ (.d ?? '/' !! '') }).Array

sub select-incompletes (@lists) {
   my (@retval, @sets);
   my $union =;
   my $intersection =[0].Slip);
   for @lists -> $list {
      my $set = set(@$list);
      $union ∪= $set;
      $intersection ∩= $set;
      @sets.push: $set;
      @retval.push: [];
   for $union.keys.sort({$^a cmp $^b}) -> $item {
      next if $item ∈ $intersection;
      for @retval Z @sets -> ($r, $s) {
         $r.push($item ∈ $s ?? $item !! '');
   return @retval;

sub render-columns (@columns) {
   my @widths ={$_».chars.max});
   my $format ={"%-{$_}s"}).join(' | ');
   my $separator = $format.sprintf({'-' x $_}));
   my ($head, @retval) = (^@columns[0].elems).map(-> $i {
   ($head, $separator, |@retval).join("\n");

The IO::Path thing is very handy. We have to add the trailing / character by the rules, otherwise the list-from function might be even shorter.

The select-incompletes follows the same algorithm as the Perl implementation, showing off the presence of a set implementation and support for Unicode characters for union, intersection, and test for an element belonging to the set. The availability of the Z operator is also very handy!

The rendering function is pretty much a translation too. As usual with Raku, I didn’t get it right from the beginning, because the @retval needs to be slipped before feeding it into join. Whatever.

So… stay safe everybody!

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