Hello Kanen,
Do you really want suggestions? :) Before that, I wanted to say great job on the improved routine. OK, here goes.
First: you should change the name of your function from
FastEditDistance to something which better describes what it is doing, like
get-friends.
Second: fix the bugs which cause
word to appear in the output list. This is caused by
word being regenerated multiple times by the swap and replace loops. I put changes in an updated version of the code, here below, to stop this from happening.
Third: cover your free variables with a
let or something. I think your free variables are
new-words and
tmpWord. On a related note, I also brought the binding for
alphabet into the function definition. But I am relying on the assumption that it is not needed anywhere else. I may be wrong.
Fourth: if the problem calls for using the Levenshtein metric as a basis for the definition of "friend", then you should remove the swap loop. (I have, in the code below.) According to your wiki cite, the Levenshtein doesn't allow the swap adjacent operation, but there is a variant called Damerau–Levenshtein which does.
Here is an updated version of the code which covers the issues discussed above:
Code: Select all
(define (get-friends word word-list)
(let ((new-words '())
(alphabet (explode "abcdefghijklmnopqrstuvwxyz"))
(tmpWord ""))
;; Deletes (removing one letter)
(for (i 0 (- (length word) 1))
(setf tmpWord word)
(pop tmpWord i)
(push tmpWord new-words -1))
;; Modifies (one letter to another)
(for (i 0 (- (length word) 1))
(set 'tmpWord word)
(dolist (a alphabet)
(when (not (= (word i) a))
(setf (tmpWord i) a)
(push tmpWord new-words -1))))
;; Inserts (add a letter)
(for (i 0 (length word))
(dolist (a alphabet)
(set 'tmpWord word)
(push (push a tmpWord i) new-words -1)))
(intersect new-words word-list)))
All in all, great job optimizing the routine. I imagine it takes a little while to get unwrapped around the axle from the initial notion that you needed to use the Levenshtein metric, when you didn't. I don't think I would have realized it as quickly as you. My hat's off to you, Sir! --Rick
P.S. -- Here is the updated swap loop code, should you need it. The index
i has to end at length(
word)-2. When
i is length(
word)-1, the code will regenerate
word.
Code: Select all
;; Swaps (swap adjacent letters)
(for (i 0 (- (length word) 2))
(set 'tmpWord word)
(push (push (pop tmpWord i) tmpWord (+ 1 i)) new-words -1))
(λx. x x) (λx. x x)