Soundex is an algorithm for creating indices for words based on their pronunciation.



Task

The goal is for homophones to be encoded to the same representation so that they can be matched despite minor differences in spelling   (from the   soundex   Wikipedia article).

Caution

There is a major issue in many of the implementations concerning the separation of two consonants that have the same soundex code! According to the official Rules [[1]]. So check for instance if Ashcraft is coded to A-261.

 If a vowel (A, E, I, O, U) separates two consonants that have the same soundex code, the consonant to the right of the vowel is coded. Tymczak is coded as T-522 (T, 5 for the M, 2 for the C, Z ignored (see "Side-by-Side" rule above), 2 for the K). Since the vowel "A" separates the Z and K, the K is coded.
 If "H" or "W" separate two consonants that have the same soundex code, the consonant to the right of the vowel is not coded. Example: Ashcraft is coded A-261 (A, 2 for the S, C ignored, 6 for the R, 1 for the F). It is not coded A-226.


set names to ["Aschraft","Ashcroft","DiBenedetto","Euler","Gauss","Ghosh","Gutierrez",
	"Heilbronn","Hilbert","Honeyman","Jackson","Lee","LeGrand","Lissajous","Lloyd",
	"Moses","Pfister","Robert","Rupert","Rubin","Tymczak","VanDeusen","Van de Graaff","Wheaton"]
 
repeat with each name in names
	put !"[[name]] --> [[name's soundex]]"
end repeat
 
to handle soundex of aName
	delete space from aName -- remove spaces
	put the first character of aName into soundex
	replace every occurrence of <{letter:char},{:letter}> with "{:letter}" in aName -- collapse double letters
	delete "H" from aName
	delete "W" from aName
 
	set prevCode to 0
	repeat with each character ch in aName
		if ch is in ...
			... "BFPV" then set code to 1
			... "CGJKQSXZ" then set code to 2
			... "DT" then set code to 3
			... "L" then set code to 4
			... "MN" then set code to 5
			... "R" then set code to 6
			... else set code to 0
		end if
		if code isn't 0 and the counter > 1 and code isn't prevCode then put code after soundex
		put code into prevCode
	end repeat
	set soundex to the first 4 chars of (soundex & "000") -- fill in with 0's as needed
 
	set prefix to <("Van" or "Con" or "De" or "Di" or "La" or "Le") followed by a capital letter>
	if aName begins with prefix then
		put aName into nameWithoutPrefix
		delete the first occurrence of prefix in nameWithoutPrefix
		return [soundex, soundex of nameWithoutPrefix]
	end if
 
	return soundex
end soundex
 