PWC166 - K-Directory Diff (Raku solution)

TL;DR

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(@dirs.map({list-from($_)}));
   for @lists Z @dirs -> ($l, $d) { $l.unshift: $d }
   return render-columns(@lists);
}

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

sub select-incompletes (@lists) {
   my (@retval, @sets);
   my $union = SetHash.new;
   my $intersection = SetHash.new(@lists[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 = @columns.map({$_».chars.max});
   my $format = @widths.map({"%-{$_}s"}).join(' | ');
   my $separator = $format.sprintf(@widths.map({'-' x $_}));
   my ($head, @retval) = (^@columns[0].elems).map(-> $i {
      $format.sprintf(@columns.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!