my class StrDistance is Cool {
    has Str $.before is built(:bind);
    has Str $.after is built(:bind);
    has Int $!distance;

    method Bool() {
        $.before ne $.after
    }

    multi method ACCEPTS(StrDistance:D: Mu \a) {
        self
    }

    method Numeric() {
        self.Int
    }

    method Str {
        $.after
    }

    multi method Int(StrDistance:D:) {
        $!distance //= do {
            my @s = *, |$.before.comb;
            my @t = *, |$.after.comb;
            my @d;
            @d[$_][ 0] = $_ for ^@s.end;
            @d[ 0][$_] = $_ for ^@t.end;

            my int $s_elems = @s.elems;
            my int $t_elems = @t.elems;
            loop (my int $i = 1; $i < $s_elems; $i = $i + 1) {
                loop (my int $j = 1; $j < $t_elems; $j = $j + 1) {
                    @d[$i][$j] = @s[$i] eq @t[$j]
                        ??   @d[$i-1][$j-1]    # No operation required when eq
                        !! ( @d[$i-1][$j  ],   # Deletion
                             @d[$i  ][$j-1],   # Insertion
                             @d[$i-1][$j-1],   # Substitution
                           ).min + 1;
                }
            }

            @d.tail.tail;
        }
    }
}

# vim: expandtab shiftwidth=4
