
(let ()
  (defun jaro (s1 s2)
    (let (mw mflags1 mflags2 fn-reset-mflags fn-reset-all-mflags fn-cnt-trans)
      (setq mflags1 (make-vector (length s1) nil))
      (setq mflags2 (make-vector (length s2) nil))
      (setq mw (1- (/ (max (length s1) (length s2)) 2)))
      (setq fn-reset-mflags
	    (lambda (idx)
	      (let ((start (max 0 (- idx mw)))
		    (end (min (1- (length s2)) (+ idx mw))))
		(cl-loop for i from start to end do
			 (when (and (not (elt mflags1 idx))
				    (not (elt mflags2 i)))
			   (when (equal (elt s1 idx) (elt s2 i))
			     (aset mflags1 idx 't)
			     (aset mflags2 i 't) ) ) ) ) ) )
      (setq fn-reset-all-mflags
	    (lambda ()
	      (dotimes (idx (length s1))
		(funcall fn-reset-mflags idx) ) ) )
      
      (setq fn-cnt-trans
	    (lambda ()
	      (let ((cur2 0) (transposition 0))
		(dotimes (cur1 (length s1))
		  (when (aref mflags1 cur1)
		    (while (not (aref mflags2 cur2))
		      (setq cur2 (1+ cur2)) )
		    (when (not (equal (aref s1 cur1)
				      (aref s2 cur2)))
		      ;;(message ">>>>>")
		      ;;(message "%d:%c" cur1 (aref s1 cur1))
		      ;;(message "%d:%c" cur2 (aref s2 cur2))
		      ;;(message "<<<<<")
		      (setq transposition (1+ transposition)) )
		    (setq cur2 (1+ cur2))
		    )
		  )
		transposition ) ) )
      
      ;;(funcall fn-reset-mflags 4)
      (funcall fn-reset-all-mflags)
      ;;(message "%s" mflags1)
      ;;(message "%s" mflags2)
      ;;(funcall fn-cnt-trans)
      (let ((m (seq-count (lambda (f) f) mflags1))
	    (tr (funcall fn-cnt-trans)))
	;;(message "matches: %s, transposition: %s, |s1|: %d |s2|: %d" m tr (length s1) (length s2))
	(if (= m 0)
	    0
	  (progn (/ (+ (/ (float m) (length s1)) (/ (float m) (length s2)) (/ (float (- m (/ (float tr) 2))) m) ) 3))
	  ) ) ) )
  
  ;;(jaro "MARTHA" "MARHTA")
  ;;(jaro "DIXON" "DICKSONX")
  ;;(jaro "JELLYFISH" "SMELLYFISH")

  (let ((params '(("MARTHA" "MARHTA")
		  ("DIXON" "DICKSONX")
		  ("JELLYFISH" "SMELLYFISH"))))
    (dolist (p params)
      (message "jaro(%s, %s) = %f"
	       (nth 0 p) (nth 1 p)
	       (jaro (nth 0 p) (nth 1 p)))
      )
    )
  
  )
