unique_prefixes.sf 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. #!/usr/bin/ruby
  2. # Author: Daniel "Trizen" Șuteu
  3. # License: GPLv3
  4. # Date: 28 September 2014
  5. # Website: https://github.com/trizen
  6. # Find the unique prefixes for an array of arrays of strings
  7. func abbrev(array, code=nil) {
  8. var END = "#{{}}"; # some unique value
  9. var CALL = (code != nil && code.is_a(Block));
  10. var table = Hash.new;
  11. array.each { |sub_array|
  12. var ref = table;
  13. sub_array.each { |item|
  14. ref = (ref{item} \\= Hash.new);
  15. };
  16. ref{END} = sub_array;
  17. }
  18. var abbrevs = [];
  19. func(hash) {
  20. var keys = hash.keys.sort;
  21. keys.each { |key|
  22. key == END && next;
  23. __FUNC__(hash{key});
  24. if (keys.len > 1) {
  25. var count = 0;
  26. var ref = hash.delete(key);
  27. while (var key = ref.keys[0]) {
  28. key.is_a(String) || next;
  29. key == END && do {
  30. var arr = ref{key}.flip.slice(count).flip;
  31. CALL ? code.call(arr) : abbrevs.append(arr);
  32. break;
  33. };
  34. ref = ref{key};
  35. count++;
  36. }
  37. }
  38. }
  39. }(table);
  40. return abbrevs;
  41. }
  42. #
  43. ## Example: find the common directory from a list of dirs
  44. #
  45. var dirs = %w(
  46. /home/user1/tmp/coverage/test
  47. /home/user1/tmp/covert/operator
  48. /home/user1/tmp/coven/members
  49. );
  50. var uniq = abbrev(dirs.map{.split('/')}).min_by{.len};
  51. var dir = [uniq.pop, uniq.join('/')][1];
  52. assert_eq('/home/user1/tmp', dir);
  53. var words = %w(
  54. deodorant
  55. decor
  56. decorat
  57. decadere
  58. plecare
  59. placere
  60. plecat
  61. jaguar
  62. );
  63. assert_eq(
  64. gather {
  65. abbrev(words.map{.split(1)}, func(a) { say take(a.join) });
  66. },
  67. %w(deca decora deco deo j pla plecar plecat)
  68. )