jaro_distance.sf 1.1 KB

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