Wikis / Unreal Wiki / Legacy:DoubleMetaPhone

This document implements a "sounds like" algorithm developed by Lawrence Philips which he published in the June, 2000 issue of C/C++ Users Journal.

Double Metaphone is an improved version of Philips' original Metaphone algorithm.

The UnrealScript implementation has been adapted from Stephen Woodbridge's PHP implementation by El Muerte.

Note: Because of the size of the algorithm there might be errors in it.

The algorithm

/**
	Returns the double metaphone value of in.
	The array always contains two values.
*/
static final function array<string> DoubleMetaPhone(coerce string in, optional int mlen)
{
	local array<string> res;
	local string prim, sec, tmp;
	local int cur, last, slen;
 
	if (mlen == 0) mlen = 4;
 	slen = Len(in);
 	last = slen-1;
 	in = caps(in$"     ");
	// skip this at beginning of word
	switch (Left(in, 2))
	{
		case "GN":
		case "KN":
		case "PN":
		case "WR":
		case "PS":
			cur++;
	}
 	// Initial 'X' is pronounced 'Z' e.g. 'Xavier'
 	if (Left(in, 1) == "X")
 	{
 		prim $= "S"; // 'Z' maps to 'S'
 		sec  $= "S";
 		cur++;
 	}
 	// main loop
 	while (len(prim) < mlen || len(sec) < mlen)
	{
		if (cur >= slen) break;
		switch (mid(in, cur, 1))
		{
			case "A":
			case "E":
			case "I":
			case "O":
			case "U":
			case "Y":
				if (cur == 0) // all init vowels now map to 'A'
				{
					prim $= "A";
					sec	 $= "A";
				}
				cur++;
				break;
 
			case "B": // '-mb', e.g. "dumb", already skipped over ...
				prim $= "P";
				sec  $= "P";
				if (mid(in, cur+1, 1) == "B") cur += 2;
				else cur++;
				break;
 
			case "Ç":
				prim $= "S";
				sec  $= "S";
				cur++;
				break;
 
			case "C": // various gremanic
				if ((cur > 1)
					&& (!is_vowel(in, cur-2))
					&& (mid(in, cur - 1, 3) == "ACH")
					&& ((mid(in, cur + 2, 1) != "I")
						&& ((mid(in, cur + 2, 1) != "E")
							|| smid(in, cur - 2, 6, tmp) == "BACHER")
							|| tmp == "MACHER"))
				{
					prim $= "K";
					sec  $= "K";
					cur += 2;
					break;
				}
 
				// special case 'caesar'
				if ((cur == 0) && (mid(in, cur, 6) == "CAESAR"))
				{
					prim $= "S";
					sec  $= "S";
					cur += 2;
					break;
				}
 
				// italian 'chianti'
				if (mid(in, cur, 4) == "CHIA")
				{
					prim $= "K";
					sec  $= "K";
					cur += 2;
					break;
				}
 
		  		if (mid(in, cur, 2) == "CH")
		  		{
					// find 'michael'
					if ((cur > 0) && (mid(in, cur, 4) == "CHAE"))
					{
						prim $= "K";
						sec  $= "X";
						cur += 2;
						break;
					}
 
					// greek roots e.g. 'chemistry', 'chorus'
					if ((cur == 0)
 						&& (smid(in, cur+1, 5, tmp) == "HARAC"
 							|| tmp == "HARIS")
						|| (smid(in, cur+1, 3, tmp) == "HOR"
							|| tmp == "HYM"
							|| tmp == "HIA"
							|| tmp == "HEM")
						&& (mid(in, 0, 5) != "CHORE"))
					{
						prim $= "K";
						sec  $= "K";
						cur += 2;
						break;
					}
 
					// germanic, greek, or otherwise 'ch' for 'kh' sound
					if ((	(smid(in, 0, 4, tmp) == "VAN ")
							|| (tmp == "VON ")
							|| (tmp == "SCH")
						)
						// 'architect' but not 'arch', orchestra', 'orchid'
						|| (	(smid(in, cur-2, 6, tmp) == "ORCHES")
								|| (tmp == "ARCHIT")
								|| (tmp == "ORCHID")
							)
						|| (InStr("TS", Mid(in, cur+2, 1)) > -1)
						|| (
							((InStr("AOUE", Mid(in, cur-1, 1)) > -1)
					 			|| (cur == 0)
							)
							// e.g. 'wachtler', 'weschsler', but not 'tichner'
							&& (InStr("LRNMBHFVW", Mid(in, cur+2, 1)) > -1))
						)
					{
						prim $= "K";
						sec  $= "K";
					}
					else {
						if (cur > 0)
						{
							if (mid(in, 0, 2) == "MC")
							{
								// e.g. 'McHugh'
								prim $= "K";
								sec  $= "K";
							}
							else {
								prim $= "X";
								sec  $= "K";
							}
						}
						else {
							prim $= "X";
							sec  $= "X";
						}
					}
					cur += 2;
					break;
				}
 
				// e.g. 'czerny'
				if (mid(in, cur, 2) == "CZ"
					&& mid(in, cur-2, 4) != "WICZ")
				{
					prim $= "S";
					sec  $= "X";
					cur += 2;
					break;
				}
 
				// e.g. 'focaccia'
				if (mid(in, cur + 1, 3) == "CIA")
				{
					prim $= "X";
					sec  $= "X";
					cur += 3;
					break;
				}
 
				// double 'C', but not McClellan'
				if (mid(in, cur, 2) == "CC"
						&& !((cur == 1)
							&& (mid(in, 0, 1) == "M")))
				{
					// 'bellocchio' but not 'bacchus'
					if ((InStr("IEH", mid(in, cur + 2, 1)) > -1)
						&& (mid(in, cur + 2, 2) != "HU"))
					{
			  			// 'accident', 'accede', 'succeed'
						if (((cur == 1)
							&& (mid(in, cur - 1, 1) == "A"))
							|| (smid(in, cur-1, 5, tmp) == "UCCEE")
							|| (tmp == "UCCES"))
						{
							prim $= "KS";
							sec  $= "KS";
							// 'bacci', 'bertucci', other italian
						}
						else {
							prim $= "X";
							sec  $= "X";
						}
						cur += 3;
						break;
					}
					else {
						// Pierce's rule
						prim $= "K";
						sec $= "K";
						cur += 2;
						break;
					}
				}
 
				if ((smid(in, cur, 2, tmp) == "CK")
					|| (tmp == "CG")
					|| (tmp == "CQ"))
				{
					prim $= "K";
					sec  $= "K";
					cur += 2;
					break;
				}
 
				if ((smid(in, cur, 2, tmp) == "CI")
					|| (tmp == "CE")
					|| (tmp == "CY"))
				{
					// italian vs. english
					if ((smid(in, cur, 3, tmp) == "CIO")
						|| (tmp == "CIE")
						|| (tmp == "CIA"))
					{
						prim $= "S";
						sec  $= "X";
					}
					else {
						prim $= "S";
						sec  $= "S";
					}
					cur += 2;
					break;
				}
 
				// else
				prim $= "K";
				sec  $= "K";
 
				// name sent in 'mac caffrey', 'mac gregor'
				if ((smid(in, cur+1, 2, tmp) == " C")
					|| (tmp == " Q")
					|| (tmp == " G"))
				{
					cur += 3;
				}
				else {
					if ((InStr("CKQ", mid(in, cur + 1, 1)) > -1)
						&& !((smid(in, cur+1, 2, tmp) == "CE")
							|| (tmp == "CI"))
						)
					{
						cur += 2;
					}
					else {
						cur++;
					}
				}
				break;
 
			case "D":
				if (mid(in, cur, 2) == "DG")
				{
					if (InStr("IEY", mid(in, cur + 2, 1)) > -1)
					{
						// e.g. 'edge'
						prim $= "J";
						sec  $= "J";
						cur += 3;
						break;
					}
					else {
						// e.g. 'edgar'
						prim $= "TK";
						sec  $= "TK";
						cur += 2;
						break;
					}
				}
 
				if ((smid(in, cur, 2, tmp) == "DT")
					|| (tmp == "DD"))
				{
					prim $= "T";
					sec  $= "T";
					cur += 2;
					break;
				}
 
				// else
				prim $= "T";
				sec  $= "T";
				cur++;
				break;
 
			case "F":
				if (mid(in, cur + 1, 1) == "F") cur += 2;
				else cur++;
				prim $= "F";
				sec  $= "F";
				break;
 
			// TODO: optimize
			case "G":
				if (mid(in, cur + 1, 1) == "H")
				{
					if ((cur > 0) && !is_vowel(in, cur-1))
					{
						prim $= "K";
						sec  $= "K";
						cur += 2;
						break;
					}
 
					if (cur < 3)
					{
						// 'ghislane', 'ghiradelli'
						if (cur == 0)
						{
							if (mid(in, cur + 2, 1) == "I")
							{
								prim $= "J";
								sec  $= "J";
							}
							else {
								prim $= "K";
								sec  $= "K";
							}
							cur += 2;
							break;
						}
					}
 
					// Parker's rule (with some further refinements) - e.g. 'hugh'
					if (((cur > 1) && (InStr("BHD", mid(in, cur - 2, 1)) > -1))
						// e.g. 'bough'
						|| ((cur > 2) && (InStr("BHD", mid(in, cur - 3, 1)) > -1))
						// e.g. 'broughton'
						|| ((cur > 3) && (InStr("BH", mid(in, cur - 4, 1)) > -1)))
					{
						cur += 2;
						break;
					}
					else {
						// e.g. 'laugh', 'McLaughlin', 'cough', 'gough', 'rough', 'tough'
						if ((cur > 2)
							&& (Mid(in, cur - 1, 1) == "U")
							&& (InStr("CGLRT", mid(in, cur - 3, 1)) > -1))
						{
							prim $= "F";
							sec  $= "F";
						}
						else {
							if ((cur > 0) && mid(in, cur - 1, 1) != "I")
							{
								prim $= "K";
								sec  $= "K";
							}
							cur += 2;
							break;
						}
					}
				}
 
				if (mid(in, cur + 1, 1) == "N")
				{
					if ((cur == 1) && is_vowel(in, 0) && !Slavo_Germanic(in))
					{
						prim $= "KN";
						sec  $= "N";
					}
					else {
						// not e.g. 'cagney'
						if ((mid(in, cur + 2, 2) != "EY")
							&& (mid(in, cur + 1) != "Y")
							&& !Slavo_Germanic(in))
						{
							prim $= "N";
							sec  $= "KN";
						}
						else {
							prim $= "KN";
							sec  $= "KN";
						}
					}
					cur += 2;
					break;
				}
 
				// 'tagliaro'
				if ((mid(in, cur + 1, 2) == "LI") && !Slavo_Germanic(in))
				{
					prim $= "KL";
					sec  $= "L";
					cur += 2;
					break;
				}
 
				// -ges-, -gep-, -gel- at beginning
				if ((cur == 0)
					&& ((mid(in, cur + 1, 1) == "Y")
						|| ((smid(in, cur + 1, 2, tmp) == "ES")
							|| (tmp == "EP")
							|| (tmp == "EB")
							|| (tmp == "EL")
							|| (tmp == "EY")
							|| (tmp == "IB")
							|| (tmp == "IL")
							|| (tmp == "IN")
							|| (tmp == "IE")
							|| (tmp == "EI")
							|| (tmp == "ER"))
						)
					)
				{
					prim $= "K";
					sec  $= "J";
					cur += 2;
					break;
				}
 
				// -ger-, -gy-
				if (((mid(in, cur + 1, 2) == "ER")
					|| (mid(in, cur + 1, 1) == "Y"))
					&& !(smid(in, 0, 6, tmp) == "DANGER"
						|| tmp == "RANGER"
						|| tmp == "MANGER"
					)
					&& (InStr("EI", mid(in, cur-1, 1)) == -1)
					&& !(smid(in, cur-1, 3, tmp) == "RGY"
						|| tmp == "OGY"
					))
				{
					prim $= "K";
					sec  $= "J";
					cur += 2;
					break;
				}
 
				// italian e.g. 'biaggi'
				if ((InStr("EIY", mid(in, cur + 1, 1)) > -1)
					|| smid(in, cur-1, 4, tmp) == "AGGI"
					|| tmp == "OGGI")
				{
					// obvious germanic
					if (((smid(in, 0, 4, tmp) == "VAN "
							|| tmp == "VON ")
						|| (mid(in, 0, 3) == "SCH"))
						|| (mid(in, cur + 1, 2) == "ET"))
					{
						prim $= "K";
						sec  $= "K";
					}
					else {
						// always soft if french ending
						if (mid(in, cur + 1, 4) == "IER ")
						{
							prim $= "J";
							sec  $= "J";
						}
						else {
							prim $= "J";
							sec  $= "K";
						}
					}
					cur += 2;
					break;
				}
 
				if (mid(in, cur +1, 1) == "G") cur += 2;
				else cur++;
 
				prim $= "K";
				sec  $= "K";
				break;
 
			case "H":
				// only keep if first & before vowel or btw. 2 vowels
				if (((cur == 0) || is_vowel(in, cur - 1)) && is_vowel(in, cur + 1))
				{
					prim $= "H";
					sec  $= "H";
					cur += 2;
				}
				else cur++;
				break;
 
   			case "J":
				// obvious spanish, 'jose', 'san jacinto'
				if ((mid(in, cur, 4) == "JOSE")
					|| (mid(in, 0, 4) == "SAN "))
				{
					if (((cur == 0) && (mid(in, cur + 4, 1) == " "))
						|| (mid(in, 0, 4) == "SAN "))
					{
						prim $= "H";
						sec  $= "H";
					}
					else {
						prim $= "J";
						sec  $= "H";
					}
					cur++;
					break;
				}
 
				if ((cur == 0) && (mid(in, cur, 4) != "JOSE"))
				{
					prim $= "J";  // Yankelovich/Jankelowicz
					sec  $= "A";
				}
				else {
					// spanish pron. of .e.g. 'bajador'
					if (is_vowel(in, cur - 1)
						&& !Slavo_Germanic(in)
						&& ((mid(in, cur + 1, 1) == "A")
						|| (mid(in, cur + 1, 1) == "O")))
					{
						prim $= "J";
						sec  $= "H";
					}
					else {
						if (cur == last)
						{
							prim $= "J";
							sec  $= "";
						}
						else {
							if ((InStr("LTKSNMBZ", mid(in, cur + 1, 1)) == -1)
								&& (InStr("SKL", mid(in, cur - 1, 1)) == -1) )
							{
								prim $= "J";
								sec  $= "J";
							}
						}
					}
				}
 
				if (mid(in, cur + 1, 1) == "J") // it could happen
					cur += 2;
				else
					cur++;
				break;
 
			case "K":
				if (mid(in, cur + 1, 1) == "K") cur += 2;
				else cur++;
				prim $= "K";
				sec  $= "K";
				break;
 
			case "L":
				if (mid(in, cur + 1, 1) == "L")
				{
					// spanish e.g. 'cabrillo', 'gallegos'
					if (((cur == (slen - 3))
						&& (smid(in, cur-1, 4, tmp) == "ILLO"
							|| tmp == "ILLA"
							|| tmp == "ALLE"
						)
						|| (
							((smid(in, last-1, 2, tmp) == "AS"
								|| tmp == "OS")
								|| (InStr("AO", mid(in, last, 1)) > -1)
							)
							&& (mid(in, cur - 1, 4) == "ALLE")
							)
						))
					{
						prim $= "L";
						sec  $= "";
						cur += 2;
						break;
					}
					cur += 2;
				} else cur++;
				prim $= "L";
				sec  $= "L";
				break;
 
			case "M":
				if (((mid(in, cur-1, 3) == "UMB")
					&& (((cur + 1) == last)
					|| (mid(in, cur+2, 2) == "ER")))
					// 'dumb', 'thumb'
					|| (mid(in, cur + 1, 1) == "M"))
				{
					cur += 2;
				}
				else {
					cur++;
				}
				prim $= "M";
				sec  $= "M";
				break;
 
			case "N":
				if (mid(in, cur + 1, 1) == "N") cur += 2;
				else cur++;
				prim $= "N";
				sec  $= "N";
				break;
 
			case "Ñ":
				cur++;
				prim $= "N";
				sec  $= "N";
				break;
 
			case "P":
				if (mid(in, cur + 1, 1) == "H")
				{
					cur += 2;
					prim $= "F";
					sec  $= "F";
					break;
				}
 
				// also account for "campbell" and "raspberry"
				if (InStr("PB", Mid(in, cur + 1, 1)) > -1)
					cur += 2;
				else
					cur++;
				prim $= "P";
				sec  $= "P";
				break;
 
   			case "Q":
				if (mid(in, cur + 1, 1) == "Q") cur += 2;
				else cur++;
				prim $= "K";
				sec  $= "K";
				break;
 
			case "R":
				// french e.g. 'rogier', but exclude 'hochmeier'
				if ((cur == last)
					&& !Slavo_Germanic(in)
					&& (mid(in, cur - 2, 2) == "IE")
					&& !(smid(in, cur-4, 2, tmp) == "ME"
						|| tmp == "MA"
					))
				{
					prim $= "";
					sec  $= "R";
				}
				else {
					prim $= "R";
					sec  $= "R";
				}
				if (mid(in, cur + 1, 1) == "R") cur += 2;
				else cur++;
				break;
 
			case "S":
				// special cases 'island', 'isle', 'carlisle', 'carlysle'
				if ((smid(in, cur - 1, 3, tmp) == "ISL")
					|| (tmp == "YSL"))
				{
					cur++;
					break;
				}
 
				// special case 'sugar-'
				if ((cur == 0) && (mid(in, cur, 5) == "SUGAR"))
				{
					prim $= "X";
					sec  $= "S";
					cur++;
					break;
				}
 
				if (mid(in, cur, 2) == "SH")
				{
					// germanic
					if (smid(in, cur + 1, 4, tmp) == "HEIM"
						|| tmp == "HOEK"
						|| tmp == "HOLM"
						|| tmp == "HOLZ")
					{
						prim $= "S";
						sec  $= "S";
					}
					else {
						prim $= "X";
						sec  $= "X";
					}
					cur += 2;
					break;
				}
 
				// italian & armenian
				if (smid(in, cur, 3, tmp) == "SIO"
					|| tmp == "SIA"
					|| mid(in, cur, 4) == "SIAN")
				{
					if (!Slavo_Germanic(in))
					{
						prim $= "S";
						sec  $= "X";
					}
					else {
						prim $= "S";
						sec  $= "S";
					}
					cur += 3;
					break;
				}
 
				// german & anglicisations, e.g. 'smith' match 'schmidt', 'snider' match 'schneider'
				// also, -sz- in slavic language altho in hungarian it is pronounced 's'
				if ((
						(cur == 0)
						&& (InStr("MNLW", mid(in, cur + 1, 1)) > -1)
					)
					|| mid(in, cur + 1, 1) == "Z")
				{
					prim $= "S";
					sec  $= "X";
					if (mid(in, cur + 1, 1) == "Z")	cur += 2;
					else cur++;
					break;
				}
 
				if (mid(in, cur, 2) == "SC")
				{
					// Schlesinger's rule
					if (mid(in, cur + 2, 1) == "H")
					{
						// dutch origin, e.g. 'school', 'schooner'
						if (smid(in, cur + 3, 2, tmp) == "OO"
							|| tmp == "ER"
							|| tmp == "EN"
							|| tmp == "UY"
							|| tmp == "ED"
							|| tmp == "EM")
						{
							// 'schermerhorn', 'schenker'
							if (smid(in, cur + 3, 2, tmp) == "ER"
								|| tmp == "EN")
							{
								prim $= "X";
								sec  $= "SK";
							} else {
								prim $= "SK";
								sec  $= "SK";
							}
							cur += 3;
							break;
						} else {
							if ((cur == 0)
								&& !is_vowel(in, 3)
								&& (mid(in, cur + 3, 1) != "W"))
							{
								prim $= "X";
								sec  $= "S";
							} else {
								prim $= "X";
								sec  $= "X";
							}
							cur += 3;
							break;
						}
 
						if (InStr("IEY", mid(in, cur + 2, 1)) > -1)
						{
							prim $= "S";
							sec  $= "S";
							cur += 3;
							break;
						}
					}
 
					// else
					prim $= "SK";
					sec  $= "SK";
					cur += 3;
					break;
				}
 
				// french e.g. 'resnais', 'artois'
				if ((cur == last)
					&& (
						smid(in, cur-2, 2, tmp) == "AI"
						|| tmp == "OI"
					))
				{
					prim $= "";
					sec  $= "S";
				} else {
					prim $= "S";
					sec  $= "S";
				}
 
				if (InStr("SZ", mid(in, cur + 1, 1)) > -1)
					cur += 2;
				else
					cur++;
				break;
 
			case "T":
				if (mid(in, cur, 4) == "TION")
				{
					prim $= "X";
					sec  $= "X";
					cur += 3;
					break;
				}
 
				if (smid(in, cur, 3, tmp) == "TIA"
					|| tmp == "TCH")
				{
					prim $= "X";
					sec  $= "X";
					cur += 3;
					break;
				}
 
				if ((mid(in, cur, 2) == "TH")
					|| (mid(in, cur, 3) == "TTH"))
				{
					// special case 'thomas', 'thames' or germanic
					if (smid(in, cur + 2, 2, tmp) == "OM"
						|| tmp == "AM"
						|| smid(in, 0, 4, tmp) == "VAN"
						|| tmp == "VON"
						|| mid(in, 0, 3) == "SCH")
					{
						prim $= "T";
						sec  $= "T";
					} else {
						prim $= "O";
						sec  $= "T";
					}
					cur += 2;
					break;
				}
 
				if (InStr("TD", mid(in, cur + 1, 1)) > -1)
					cur += 2;
				else
					cur++;
				prim $= "T";
				sec  $= "T";
				break;
 
			case "V":
				if (mid(in, cur + 1, 1) == "V")
					cur += 2;
				else
					cur++;
				prim $= "F";
				sec  $= "F";
				break;
 
			case "W":
				// can also be in middle of word
				if (mid(in, cur, 2) == "WR") {
					prim $= "R";
					sec  $= "R";
					cur += 2;
					break;
				}
 
				if ((cur == 0)
					&& (is_vowel(in, cur + 1)
						|| mid(in, cur, 2) == "WH"))
				{
					// Wasserman should match Vasserman
					if (is_vowel(in, cur + 1))
					{
						prim $= "A";
						sec  $= "F";
					}
					else {
						// need Uomo to match Womo
						prim $= "A";
						sec  $= "A";
					}
				}
 
				// Arnow should match Arnoff
				if (((cur == last)
						&& is_vowel(in, cur - 1))
					|| smid(in, cur - 1, 5, tmp) =="EWSKI"
					|| tmp == "EWSKY"
					|| tmp == "OWSKI"
					|| tmp == "OWSKY"
					|| mid(in, 0, 3) == "SCH")
				{
					prim $= "";
					sec  $= "F";
					cur++;
					break;
				}
 
				// polish e.g. 'filipowicz'
				if (smid(in, cur, 4, tmp) == "WICZ"
					|| tmp == "WITZ")
				{
					prim $= "TS";
					sec  $= "FX";
					cur += 4;
					break;
				}
 
				// else skip it
				cur++;
				break;
 
			case "X":
				// french e.g. breaux
				if (!((cur == last)
					&& (smid(in, cur - 3, 3, tmp) == "IAU"
						|| tmp == "EAU"
						|| smid(in, cur - 2, 2, tmp) == "AU"
						|| tmp == "OU")))
				{
					prim $= "KS";
					sec  $= "KS";
				}
 
				if (InStr("CX", mid(in, cur + 1, 1)) > -1)
					cur += 2;
				else
					cur++;
				break;
 
 
			case "Z":
				// chinese pinyin e.g. 'zhao'
				if (mid(in, cur + 1, 1) == "H")
				{
					prim $= "J";
					sec  $= "J";
					cur += 2;
					break;
				}
				else
					if (smid(in, cur + 1, 2, tmp) == "ZO"
						|| tmp == "ZI"
						|| tmp == "ZA"
						|| (Slavo_Germanic(in)
						&& ((cur > 0) && mid(in, cur - 1, 1) != "T")))
					{
					prim $= "S";
					sec  $= "TS";
				} else {
					prim $= "S";
					sec  $= "S";
				}
 
				if (mid(in, cur + 1, 1) == "Z")
					cur += 2;
				else
					cur++;
				break;
 
			default:
				cur++;
		}
 	}
 
 	res[0] = Left(prim, mlen);
 	res[1] = Left(sec, mlen);
 	return res;
}

Helper functions

/**
	Same as mid, except that is has a 4th param that will also get the result. <br />
	Use this for caching the result.
*/
static final function string smid(coerce string in, int off, int len, out string s)
{
	s = mid(in, off, len);
	return s;
}
 
/**
	returns true if the character at pos is a vowel.
*/
static final function bool is_vowel(coerce string in, int pos)
{
	return (InStr("AEIOUY", mid(in, pos, 1)) > -1);
}
 
/**
	helper function for the metaphone algorithm to determain if this word is
	"slave germanic"
*/
static final function bool Slavo_Germanic(coerce string in)
{
	return (InStr(in, "W") > -1)
		|| (InStr(in, "K") > -1)
		|| (InStr(in, "CZ") > -1)
		|| (InStr(in, "WITZ") > -1);
}

Copyright

   Copyright 2004, Michiel Hendriks <elmuerte@drunksnipers.com>
   All rights reserved.

   This UnrealScript translation is based heavily on the PHP 
   implementation by Stephen Woodbridge <woodbri@swoodbridge.com>, 
   which in turn is based on the C implementation
   by Maurice Aubrey <maurice@hevanet.com>, which in turn
   is based heavily on the C++ implementation by
   Lawrence Philips and incorporates several bug fixes courtesy
   of Kevin Atkinson <kevina@users.sourceforge.net>.

   This module is free software; you may redistribute it and/or
   modify it under the same terms as Perl itself.

The Perl Artistic License.

Note that that page currently appears to be blank, the Perl Artistic License is almost similar to the Artistic License

Wormbo: Erm... Perl?

El Muerte: Yeah go figure, just pasting a long the license notice. The implementation of Maurice Aubrey has been released under that license, and so is the PHP implementation, thus this implementation should also be released under the same license. The license isn't very restrictive, it allows you to do even more than the LesserOpenUnrealModLicense would do.

Related Topics

Page Categories

Page Information

2022-11-20T20:27:20.221801Z 2004-08-19T13:15:28Z El Muerte * https://wiki.beyondunreal.com/Legacy:DoubleMetaPhone Attribution-NonCommercial-ShareAlike 3.0