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!