jaro_distance.sf 1.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. #!/usr/bin/ruby
  2. #
  3. ## https://rosettacode.org/wiki/Jaro_distance
  4. #
  5. func jaro(s, t) {
  6. return 1 if (s == t)
  7. var s_len = s.len
  8. var t_len = t.len
  9. var match_distance = ((s_len `max` t_len) // 2 - 1)
  10. var s_matches = []
  11. var t_matches = []
  12. var matches = 0
  13. var transpositions = 0
  14. for i (^s_len) {
  15. var start = (0 `max` i-match_distance)
  16. var end = (i+match_distance `min` t_len-1)
  17. for k (start..end) {
  18. t_matches[k] && next
  19. s[i] == t[k] || next
  20. s_matches[i] = true
  21. t_matches[k] = true
  22. matches++
  23. break
  24. }
  25. }
  26. return 0 if (matches == 0)
  27. var k = 0
  28. for i (^s_len) {
  29. s_matches[i] || next
  30. while (!t_matches[k]) { ++k }
  31. s[i] == t[k] || ++transpositions
  32. ++k
  33. }
  34. ((matches / s_len) +
  35. (matches / t_len) +
  36. ((matches - transpositions/2) / matches)) / 3
  37. }
  38. for pair in [
  39. [%c"MARTHA", %c"MARHTA"],
  40. [%c"DIXON", %c"DICKSONX"],
  41. [%c"JELLYFISH", %c"SMELLYFISH"],
  42. ] {
  43. say "jaro(#{pair.map{.join.dump}.join(', ')}) = #{'%.10f' % jaro(pair...)}"
  44. }