#!/usr/bin/ruby
# Author: Daniel "Trizen" Șuteu
# License: GPLv3
# Date: 28 September 2014
# Website: https://github.com/trizen
# Find the unique prefixes for an array of arrays of strings
func abbrev(array, code=nil) {
var END = "#{{}}"; # some unique value
var CALL = (code != nil && code.is_a(Block));
var table = Hash.new;
array.each { |sub_array|
var ref = table;
sub_array.each { |item|
ref = (ref{item} \\= Hash.new);
};
ref{END} = sub_array;
}
var abbrevs = [];
func(hash) {
var keys = hash.keys.sort;
keys.each { |key|
key == END && next;
__FUNC__(hash{key});
if (keys.len > 1) {
var count = 0;
var ref = hash.delete(key);
while (var key = ref.keys[0]) {
key.is_a(String) || next;
key == END && do {
var arr = ref{key}.flip.slice(count).flip;
CALL ? code.call(arr) : abbrevs.append(arr);
break;
};
ref = ref{key};
count++;
}
}
}
}(table);
return abbrevs;
}
#
## Example: find the common directory from a list of dirs
#
var dirs = %w(
/home/user1/tmp/coverage/test
/home/user1/tmp/covert/operator
/home/user1/tmp/coven/members
);
var uniq = abbrev(dirs.map{.split('/')}).min_by{.len};
var dir = [uniq.pop, uniq.join('/')][1];
assert_eq('/home/user1/tmp', dir);
var words = %w(
deodorant
decor
decorat
decadere
plecare
placere
plecat
jaguar
);
assert_eq(
gather {
abbrev(words.map{.split(1)}, func(a) { say take(a.join) });
},
%w(deca decora deco deo j pla plecar plecat)
)