Soundex: Difference between revisions

60,131 bytes added ,  3 months ago
m
m (→‎{{header|Wren}}: Minor tidy)
 
(43 intermediate revisions by 29 users not shown)
Line 5:
 
;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   [[wp:soundex|thesoundex   WPWikipedia article]]).
<br><br>
 
;Caution:
Line 12 ⟶ 11:
* 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.
<br><br>
 
=={{header|11l}}==
{{trans|Java}}
 
<syntaxhighlight lang="11l">V inv_code = [
‘1’ = [‘B’, ‘F’, ‘P’, ‘V’],
‘2’ = [‘C’, ‘G’, ‘J’, ‘K’, ‘Q’, ‘S’, ‘X’, ‘Z’],
‘3’ = [‘D’, ‘T’],
‘4’ = [‘L’],
‘5’ = [‘M’, ‘N’],
‘6’ = [‘R’]
]
 
[Char = Char] _code
L(k, arr) inv_code
L(el) arr
_code[el] = k
 
F soundex(s)
V code = String(s[0].uppercase())
V previous = :_code.get(s[0].uppercase(), Char("\0"))
 
L(c) s[1..]
V current = :_code.get(c.uppercase(), Char("\0"))
I current != "\0" & current != previous
code ‘’= current
previous = current
 
R (code‘0000’)[0.<4]
 
print(soundex(‘Soundex’))
print(soundex(‘Example’))
print(soundex(‘Sownteks’))
print(soundex(‘Ekzampul’))</syntaxhighlight>
 
{{out}}
<pre>
S532
E251
S532
E251
</pre>
 
=={{header|360 Assembly}}==
{{trans|VBScript}}
An example of the use of the TR opcode (translate) and the uppercase trick by 'or' with space (X'40').
<langsyntaxhighlight lang="360asm">* Soundex 02/04/2017
SOUNDEX CSECT
USING SOUNDEX,R13 base register
Line 96 ⟶ 138:
ORG
YREGS
END SOUNDEX</langsyntaxhighlight>
{{out}}
<pre>
Line 116 ⟶ 158:
16 EXAMPLE E251
</pre>
 
 
=={{header|Ada}}==
<langsyntaxhighlight Adalang="ada">with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Characters.Handling; use Ada.Characters.Handling;
Line 160 ⟶ 201:
Put_Line(To_String(cases(i))&" = "&toSoundex(To_String(cases(i))));
end loop;
end Soundex;</langsyntaxhighlight>
{{out}}
<pre>Soundex = S532
Line 196 ⟶ 237:
Note: The only non-standard prelude functions used are to lower, is alpha, and is digit.
These are easy enough to write, vide [[String case#ALGOL 68|String case]]
<langsyntaxhighlight Algol68lang="algol68"> PROC soundex = (STRING s) STRING:
BEGIN
PROC encode = (CHAR c) CHAR:
Line 260 ⟶ 301:
printf(($g, 1x, g, 1x$, expected output OF soundex test[i], output));
printf(($b("ok", "not ok"), 1l$, output = expected output OF soundex test[i]))
OD</langsyntaxhighlight>
 
=={{header|ANSI Standard BASICArturo}}==
 
{{trans|BBC Basic}}
<syntaxhighlight lang="rebol">code: #[
Note: Line numbers (strict ANSI interpretation), LET and the variable after NEXT are not optional.
"aeiouy": `W`
"bfpv": `1`
"cgjkqsxz": `2`
"dt": `3`
"l": `4`
"mn": `5`
"r": `6`
]
 
getCode: function [ch][
loop keys code 'k [
if contains? k lower to :string ch -> return code\[k]
]
return ` `
]
 
soundex: function [str][
result: new to :string first str
 
prev: getCode first str
loop.with:'i str 'c [
curr: getCode c
if curr <> ` ` [
if and? curr <> `W`
curr <> prev -> 'result ++ curr
prev: curr
]
]
 
if? 4 < size result ->
result: new slice result 0 3
else [
do.times: 4-size result ->
'result ++ `0`
]
return result
]
 
loop ["Robert", "Rupert", "Rubin", "Ashcraft", "Ashcroft", "Tymczak",
"Pfister", "Honeyman", "Moses", "O'Mally", "O'Hara", "D day"] 'name ->
print [pad name 10 "->" soundex name]</syntaxhighlight>
 
{{out}}
 
<pre> Robert -> R163
Rupert -> R163
Rubin -> R150
Ashcraft -> A261
Ashcroft -> A261
Tymczak -> T522
Pfister -> P236
Honeyman -> H555
Moses -> M220
O'Mally -> O540
O'Hara -> O600
D day -> D000</pre>
 
<lang ANSI>100 DECLARE EXTERNAL FUNCTION FNSoundex$
110
120 DATA Ashcraft, Ashcroft, Gauss, Ghosh, Hilbert, Heilbronn, Lee, Lloyd
130 DATA Moses, Pfister, Robert, Rupert, Rubin, Tymczak, Soundex, Example
140 FOR i = 1 TO 16
150 READ name$
160 PRINT """"; name$; """"; TAB(15); FNsoundex$(name$)
170 NEXT i
180 END
190
200 EXTERNAL FUNCTION FNsoundex$(name$)
210 LET name$ = UCASE$(name$)
220 LET n$ = "01230129022455012623019202"
230 LET s$ = name$(1:1)
240 LET p = VAL(n$(ORD(s$) - 64 : ORD(s$) - 64))
250 FOR i = 2 TO LEN(name$)
260 LET n = VAL(n$(ORD(name$(i:i)) - 64: ORD(name$(i:i)) - 64))
270 IF n <> 0 AND n <> 9 AND n <> p THEN LET s$ = s$ & STR$(n)
280 IF n <> 9 THEN LET p = n
290 NEXT i
300 LET s$ = s$ & "000"
310 LET FNSoundex$ = s$(1:4)
320 END FUNCTION</lang>
 
=={{header|AutoHotkey}}==
{{trans|VBScript}}
<langsyntaxhighlight AutoHotkeylang="autohotkey">getCode(c){
If c in B,F,P,V
return 1
Line 329 ⟶ 403:
}
 
MsgBox % Soundex("Soundex") "`n" Soundex("Sowndeks") "`n" Soundex("Ashcroft") "`n" Soundex("Ashkrofd")</langsyntaxhighlight>
 
=={{header|AWK}}==
Line 335 ⟶ 409:
The soundex function is embedded in a program to build a table of soundex "homonyms".
 
<langsyntaxhighlight lang="awk">#!/usr/bin/awk -f
BEGIN {
subsep = ", "
Line 394 ⟶ 468:
}
}
</syntaxhighlight>
</lang>
 
 
Line 449 ⟶ 523:
</pre>
 
=={{header|BBC BASIC}}==
==={{header|ANSI BASIC}}===
<lang bbcbasic> DATA Ashcraft, Ashcroft, Gauss, Ghosh, Hilbert, Heilbronn, Lee, Lloyd
{{trans|BBC Basic}}
{{works with|Decimal BASIC}}
Note: Line numbers (strict ANSI interpretation), <code>LET</code> and the variable after <code>NEXT</code> are obligatory.
<syntaxhighlight lang="basic">100 DECLARE EXTERNAL FUNCTION FNSoundex$
110
120 DATA Ashcraft, Ashcroft, Gauss, Ghosh, Hilbert, Heilbronn, Lee, Lloyd
130 DATA Moses, Pfister, Robert, Rupert, Rubin, Tymczak, Soundex, Example
140 FOR i = 1 TO 16
150 READ name$
160 PRINT """"; name$; """"; TAB(15); FNsoundex$(name$)
170 NEXT i
180 END
190
200 EXTERNAL FUNCTION FNsoundex$(name$)
210 LET name$ = UCASE$(name$)
220 LET n$ = "01230129022455012623019202"
230 LET s$ = name$(1:1)
240 LET p = VAL(n$(ORD(s$) - 64 : ORD(s$) - 64))
250 FOR i = 2 TO LEN(name$)
260 LET n = VAL(n$(ORD(name$(i:i)) - 64: ORD(name$(i:i)) - 64))
270 IF n <> 0 AND n <> 9 AND n <> p THEN LET s$ = s$ & STR$(n)
280 IF n <> 9 THEN LET p = n
290 NEXT i
300 LET s$ = s$ & "000"
310 LET FNSoundex$ = s$(1:4)
320 END FUNCTION</syntaxhighlight>
{{out}}
<pre>"Ashcraft" A261
"Ashcroft" A261
"Gauss" G200
"Ghosh" G200
"Hilbert" H416
"Heilbronn" H416
"Lee" L000
"Lloyd" L300
"Moses" M220
"Pfister" P236
"Robert" R163
"Rupert" R163
"Rubin" R150
"Tymczak" T522
"Soundex" S532
"Example" E251
</pre>
 
==={{header|BBC BASIC}}===
<syntaxhighlight lang="bbcbasic"> DATA Ashcraft, Ashcroft, Gauss, Ghosh, Hilbert, Heilbronn, Lee, Lloyd
DATA Moses, Pfister, Robert, Rupert, Rubin, Tymczak, Soundex, Example
FOR i% = 1 TO 16
Line 477 ⟶ 598:
IF C% >= 97 IF C% <= 122 MID$(A$,A%,1) = CHR$(C%-32)
NEXT
= A$</langsyntaxhighlight>
{{out}}
<pre>
Line 503 ⟶ 624:
The word to translate is read from stdin, and its corresponding soundex encoding is written to stdout.
 
<langsyntaxhighlight lang="befunge">>:~>:48*\`#v_::"`"`\"{"\`*v
^$$_v#!*`*8 8\`\"["::-**84<
>$1^>:88*>v>$$1->vp7+2\"0"<
Line 511 ⟶ 632:
v$$:$$_^#\<1!-"0"<^1,<g7:<<
v??????????????????????????
v01230120022455012623010202</langsyntaxhighlight>
 
{{out}} (multiple runs)
Line 530 ⟶ 651:
Ashcraft
A226</pre>
 
=={{header|BQN}}==
 
Defines a Soundex function which returns a string. The split function is used for generating input data.
 
<syntaxhighlight lang="bqn">ToUpper ← -⟜(32×1="a{"⊸⍋)
Split ← ((⊢-˜+`׬)∘=⊔⊢)
replace ← ⟨
"AEIOUYHW"
"BFPV"
"CGJKQSXZ"
"DT"
"L"
"MN"
"R"
 
Soundex ← ⊑∾{'0'+»⟜0‿0‿0⊑¨0⊸≠⊸/(0≠⊑)⊸↓⊑¨(¯1+·+`1»≠⟜«)⊸⊔∾/¨<˘⍉>replace∊˜¨<ToUpper 𝕩}
 
names ← ' ' Split "Lloyd Woolcock Donnell Baragwanath Williams Ashcroft Euler Ellery Gauss Ghosh Hilbert Heilbronn Knuth Kant Ladd Lukasiewicz Lissajous"
vals ← ' ' Split "L300 W422 D540 B625 W452 A226 E460 E460 G200 G200 H416 H416 K530 K530 L300 L222 L222"
 
•Show >(⊢ ⋈ Soundex)¨names
•Show vals≡Soundex¨names</syntaxhighlight>
<syntaxhighlight lang="bqn">┌─
╵ "Lloyd" "L300"
"Woolcock" "W422"
"Donnell" "D540"
"Baragwanath" "B625"
"Williams" "W452"
"Ashcroft" "A226"
"Euler" "E460"
"Ellery" "E460"
"Gauss" "G200"
"Ghosh" "G200"
"Hilbert" "H416"
"Heilbronn" "H416"
"Knuth" "K530"
"Kant" "K530"
"Ladd" "L300"
"Lukasiewicz" "L222"
"Lissajous" "L222"
1</syntaxhighlight>
 
=={{header|C}}==
Some string examples and rules from [[http://www.archives.gov/research/census/soundex.html]].
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Line 629 ⟶ 794:
 
return 0;
}</langsyntaxhighlight>
 
=={{header|C sharp}}==
 
<langsyntaxhighlight lang="c sharp">using System;
using System.Collections.Generic;
using System.Linq;
Line 732 ⟶ 897:
}
}
}</langsyntaxhighlight>
 
{{out}}
Line 763 ⟶ 928:
VanDeusen -> V532 (True)
Ashcraft -> A261 (True)
</pre>
 
=={{header|C++}}==
<syntaxhighlight lang="c">
#include <iostream> // required for debug code in main() only
#include <iomanip> // required for debug code in main() only
#include <string>
 
std::string soundex( char const* s )
{
static char const code[] = { 0, -1, 1, 2, 3, -1, 1, 2, 0, -1, 2, 2, 4, 5, 5, -1, 1, 2, 6, 2, 3, -1, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0 };
 
if( !s || !*s )
return std::string();
 
std::string out( "0000" );
out[0] = (*s >= 'a' && *s <= 'z') ? *s - ('a' - 'A') : *s;
++s;
 
char prev = code[out[0] & 0x1F]; // first letter, though not coded, can still affect next letter: Pfister
for( unsigned i = 1; *s && i < 4; ++s )
{
if( (*s & 0xC0) != 0x40 ) // process only letters in range [0x40 - 0x7F]
continue;
auto const c = code[*s & 0x1F];
if( c == prev )
continue;
 
if( c == -1 )
prev = 0; // vowel as separator
else if( c )
{
out[i] = c + '0';
++i;
prev = c;
}
}
return out;
}
 
int main()
{
static char const * const names[][2] =
{
{"Ashcraft", "A261"},
{"Burroughs", "B620"},
{"Burrows", "B620"},
{"Ekzampul", "E251"},
{"Ellery", "E460"},
{"Euler", "E460"},
{"Example", "E251"},
{"Gauss", "G200"},
{"Ghosh", "G200"},
{"Gutierrez", "G362"},
{"Heilbronn", "H416"},
{"Hilbert", "H416"},
{"Jackson", "J250"},
{"Kant", "K530"},
{"Knuth", "K530"},
{"Ladd", "L300"},
{"Lee", "L000"},
{"Lissajous", "L222"},
{"Lloyd", "L300"},
{"Lukasiewicz", "L222"},
{"O'Hara", "O600"},
{"Pfister", "P236"},
{"Soundex", "S532"},
{"Sownteks", "S532"},
{"Tymczak", "T522"},
{"VanDeusen", "V532"},
{"Washington", "W252"},
{"Wheaton", "W350"}
};
 
for( auto const& name : names )
{
auto const sdx = soundex( name[0] );
std::cout << std::left << std::setw( 16 ) << name[0] << std::setw( 8 ) << sdx << (sdx == name[1] ? " ok" : " ERROR") << std::endl;
}
return 0;
}
 
</syntaxhighlight>
{{out|Example output}}
<pre>
Ashcraft A261 ok
Burroughs B620 ok
Burrows B620 ok
Ekzampul E251 ok
Ellery E460 ok
Euler E460 ok
Example E251 ok
Gauss G200 ok
Ghosh G200 ok
Gutierrez G362 ok
Heilbronn H416 ok
Hilbert H416 ok
Jackson J250 ok
Kant K530 ok
Knuth K530 ok
Ladd L300 ok
Lee L000 ok
Lissajous L222 ok
Lloyd L300 ok
Lukasiewicz L222 ok
O'Hara O600 ok
Pfister P236 ok
Soundex S532 ok
Sownteks S532 ok
Tymczak T522 ok
VanDeusen V532 ok
Washington W252 ok
Wheaton W350 ok
</pre>
 
=={{header|Caché ObjectScript}}==
 
<langsyntaxhighlight lang="cos">
Class Utils.Phonetic [ Abstract ]
{
Line 777 ⟶ 1,055:
 
}
</syntaxhighlight>
</lang>
{{out|Examples}}
<pre>
Line 814 ⟶ 1,092:
=={{header|Clipper/XBase++}}==
 
<langsyntaxhighlight Clipperlang="clipper/XBasexbase++">FUNCTION Soundex(cWord)
 
/*
Line 877 ⟶ 1,155:
RETURN(nMatch)
 
*******************************************************************************</langsyntaxhighlight>
--[[User:Clippersolutions|Clippersolutions]] 23:14, 4 November 2010 (UTC)--[[User:Clippersolutions|Clippersolutions]] 23:14, 4 November 2010 (UTC)
 
=={{header|Clojure}}==
<langsyntaxhighlight Clojurelang="clojure">(defn get-code [c]
(case c
(\B \F \P \V) 1
Line 900 ⟶ 1,178:
(remove nil? ,)
(take 4 ,)
(apply str ,)))))</langsyntaxhighlight>
 
Bug here? The distinct function eliminates duplicates. What is needed in Soundex is to eliminate consecutive duplicates.
 
<syntaxhighlight lang="clojure">
<lang Clojure>
;;; With proper consecutive duplicates elimination
 
Line 931 ⟶ 1,209:
(recur (apply str first-char (rest the-rest)))
(let [soundex-nums (reduce reduce-fn [] the-rest)]
(apply str first-char (take 3 (conj soundex-nums 0 0 0)))))))</langsyntaxhighlight>
 
=={{header|CLU}}==
<syntaxhighlight lang="clu">lower = proc (c: char) returns (char)
if c >= 'A' & c <= 'Z' then
c := char$i2c(32 + char$c2i(c))
end
return(c)
end lower
 
soundex = proc (name: string) returns (string)
own coding: array[string] := array[string]$
[0:"aeiou","bfpv","cgjkqsxz","dt","l","mn","r"]
nums: array[int] := array[int]$[]
for i: int in int$from_to(1, string$size(name)) do
c: char := lower(name[i])
for n: int in array[string]$indexes(coding) do
if string$indexc(c, coding[n]) ~= 0 then
array[int]$addh(nums, n)
break
end
end
end
filtered: array[int] := array[int]$[]
for i: int in array[int]$indexes(nums) do
if nums[i]=0 cor i=1 then continue end
if nums[i]~=nums[i-1] then
array[int]$addh(filtered,nums[i])
end
end
code: string := string$c2s(name[1])
for i: int in array[int]$elements(filtered) do
if string$size(code) >= 4 then break end
code := code || int$unparse(i)
end
while string$size(code) < 4 do
code := code || "0"
end
return(code)
end soundex
 
start_up = proc ()
test = struct[name, code: string]
po: stream := stream$primary_output()
tests: array[test] := array[test]$[
test${name:"Ashcraft", code:"A261"},
test${name:"Burroughs", code:"B620"},
test${name:"Burrows", code:"B620"},
test${name:"Ekzampul", code:"E251"},
test${name:"Ellery", code:"E460"},
test${name:"Euler", code:"E460"},
test${name:"Example", code:"E251"},
test${name:"Gauss", code:"G200"},
test${name:"Ghosh", code:"G200"},
test${name:"Gutierrez", code:"G362"},
test${name:"Heilbronn", code:"H416"},
test${name:"Hilbert", code:"H416"},
test${name:"Jackson", code:"J250"},
test${name:"Kant", code:"K530"},
test${name:"Knuth", code:"K530"},
test${name:"Ladd", code:"L300"},
test${name:"Lee", code:"L000"},
test${name:"Lissajous", code:"L222"},
test${name:"Lloyd", code:"L300"},
test${name:"Lukasiewicz", code:"L222"},
test${name:"O'Hara", code:"O600"},
test${name:"Pfister", code:"P236"},
test${name:"Soundex", code:"S532"},
test${name:"Sownteks", code:"S532"},
test${name:"Tymczak", code:"T522"},
test${name:"VanDeusen", code:"V532"},
test${name:"Washington", code:"W252"},
test${name:"Wheaton", code:"W350"}
]
for t: test in array[test]$elements(tests) do
stream$putleft(po, t.name, 12)
stream$puts(po, " -> ")
c: string := soundex(t.name)
stream$puts(po, c)
if c ~= t.code
then stream$putl(po, " (Wrong!)")
else stream$putl(po, " (OK)")
end
end
end start_up</syntaxhighlight>
{{out}}
<pre style='height:50ex;'>Ashcraft -> A261 (OK)
Burroughs -> B620 (OK)
Burrows -> B620 (OK)
Ekzampul -> E251 (OK)
Ellery -> E460 (OK)
Euler -> E460 (OK)
Example -> E251 (OK)
Gauss -> G200 (OK)
Ghosh -> G200 (OK)
Gutierrez -> G362 (OK)
Heilbronn -> H416 (OK)
Hilbert -> H416 (OK)
Jackson -> J250 (OK)
Kant -> K530 (OK)
Knuth -> K530 (OK)
Ladd -> L300 (OK)
Lee -> L000 (OK)
Lissajous -> L222 (OK)
Lloyd -> L300 (OK)
Lukasiewicz -> L222 (OK)
O'Hara -> O600 (OK)
Pfister -> P236 (OK)
Soundex -> S532 (OK)
Sownteks -> S532 (OK)
Tymczak -> T522 (OK)
VanDeusen -> V532 (OK)
Washington -> W252 (OK)
Wheaton -> W350 (OK)</pre>
 
=={{header|COBOL}}==
Line 938 ⟶ 1,335:
{{works with|IBM Enterprise COBOL for z/OS}}
 
<langsyntaxhighlight lang="cobol"> **** sndxtest *********************************************
* Demonstrate the soundex encoding functions.
***************************************************************
Line 1,086 ⟶ 1,483:
else move 0 to char-sdx-code
end-if.
End program sndxchar.</langsyntaxhighlight>
 
{{out}}
Line 1,121 ⟶ 1,518:
 
=={{header|Common Lisp}}==
<langsyntaxhighlight lang="lisp">(defun get-code (c)
(case c
((#\B #\F #\P #\V) #\1)
Line 1,142 ⟶ 1,539:
(push cg o)
finally
(return (subseq (coerce (nreverse `(#\0 #\0 #\0 ,@o)) 'string) 0 4))))))</langsyntaxhighlight>
 
=={{header|Crystal}}==
{{trans|VBScript}}
<langsyntaxhighlight lang="ruby"># version 0.21.1
 
def get_code(c : Char)
Line 1,203 ⟶ 1,600:
pairs.each { |pair|
puts "#{pair[0].ljust(9)} -> #{pair[1]} -> #{soundex(pair[0]) == pair[1]}"
}</langsyntaxhighlight>
 
{{out}}
Line 1,228 ⟶ 1,625:
===Standard Version===
The D standard library (Phobos) contains a soundex function:
<langsyntaxhighlight lang="d">import std.stdio: writeln;
import std.string: soundex;
 
Line 1,242 ⟶ 1,639:
assert(soundex("Ashcroft") == "A261");
assert(soundex("Tymczak") == "T522");
}</langsyntaxhighlight>
It works according to this document:
http://www.archives.gov/publications/general-info-leaflets/55.html
Line 1,251 ⟶ 1,648:
This version uses dynamic heap allocations in some places (replace, toupper, several string join) to allow a higher level style of coding, but this function may also be written to perform zero heap allocations. It may even return a char[4] by value, or use a given buffer like the C version.
 
<langsyntaxhighlight lang="d">import std.array, std.string, std.ascii, std.algorithm, std.range;
 
/**
Line 1,311 ⟶ 1,708:
}
 
void main() {}</langsyntaxhighlight>
 
=={{header|Delphi}}==
<syntaxhighlight lang="delphi">program SoundexDemo;
<lang Delphi>
program SoundexDemo;
 
{$APPTYPE CONSOLE}
 
uses
System.StrUtils;
SysUtils,
StrUtils;
 
begin
Writeln(Soundex('SoundexAshcraft'));
Writeln(Soundex('ExampleTymczak'));
end.</syntaxhighlight>
Writeln(Soundex('Sownteks'));
Writeln(Soundex('Ekzampul'));
Readln;
end.
</lang>
{{out}}
<pre>
A261
S532
T522
E251
S532
E251
</pre>
 
=={{header|EasyLang}}==
{{trans|Java}}
<syntaxhighlight>
trans$ = "01230120022455012623010202"
func$ code c$ .
c = strcode c$ - 64
if c > 26
c -= 32
.
return substr trans$ c 1
.
func$ soundex s$ .
code$ = substr s$ 1 1
prev$ = code code$
for i = 2 to len s$
cur$ = code substr s$ i 1
if cur$ <> "" and cur$ <> "0" and cur$ <> prev$
code$ &= cur$
.
prev$ = cur$
.
return substr code$ & "0000" 1 4
.
for v$ in [ "Soundex" "Example" "Sownteks" "Ekzampul" ]
print soundex v$
.
</syntaxhighlight>
 
 
=={{header|Elixir}}==
{{trans|Erlang}}
<langsyntaxhighlight lang="elixir">defmodule Soundex do
def soundex([]), do: []
def soundex(str) do
Line 1,379 ⟶ 1,797:
IO.puts Soundex.soundex("Example")
IO.puts Soundex.soundex("Sownteks")
IO.puts Soundex.soundex("Ekzampul")</langsyntaxhighlight>
 
{{out}}
Line 1,391 ⟶ 1,809:
=={{header|Erlang}}==
This implements the US Census rules, where W and H are ignored but, unlike vowels, are not separators.
<langsyntaxhighlight Erlanglang="erlang">-module(soundex).
-export([soundex/1]).
 
Line 1,436 ⟶ 1,854:
$0
end.
</syntaxhighlight>
</lang>
 
=={{header|F_Sharp|F#}}==
<langsyntaxhighlight FSharplang="fsharp">module Soundex
 
let soundex (s : string) =
Line 1,487 ⟶ 1,905:
 
0
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,524 ⟶ 1,942:
Wheaton W350 W350
</pre>
 
=={{header|Factor}}==
<syntaxhighlight lang="factor">USE: soundex
"soundex" soundex ! S532
"example" soundex ! E251
"ciondecks" soundex ! C532
"ekzampul" soundex ! E251</syntaxhighlight>
 
=={{header|Forth}}==
This implements the US Census rules, where W and H are ignored but, unlike vowels, aren't separators. Further corner cases welcome...
 
<langsyntaxhighlight lang="forth">: alpha-table create does> swap 32 or [char] a - 0 max 26 min + 1+ c@ ;
 
alpha-table soundex-code
Line 1,569 ⟶ 1,994:
s" Burroughs" soundex cr type \ B620
s" Burrows" soundex cr type \ B620 (W test) (any Welsh names?)
s" O'Hara" soundex cr type \ O600 (punctuation test)</langsyntaxhighlight>
 
=={{header|Go}}==
WP article rules, plus my interpretation for input validation.
<lang go>package main
 
=={{header|FreeBASIC}}==
import (
{{trans|PureBasic}}
"errors"
<syntaxhighlight lang="freebasic">
"fmt"
Function getCode(c As String) As String
"unicode"
If Instr("BFPV", c) Then Return "1"
)
If Instr("CGJKQSXZ", c) Then Return "2"
If Instr("DT", c) Then Return "3"
If "L" = c Then Return "4"
If Instr("MN", c) Then Return "5"
If "R" = c Then Return "6"
If Instr("HW", c) Then Return "."
End Function
 
Function Soundex(palabra As String) As String
var code = []byte("01230127022455012623017202")
palabra = Ucase(palabra)
Dim As String code = Mid(palabra,1,1)
Dim As String previo = getCode(Left(palabra, 1)) ''""
Dim As String actual
For i As Byte = 2 To (Len(palabra) + 1)
actual = getCode(Mid(palabra, i, 1))
If actual = "." Then Continue For
If Len(actual) > 0 And actual <> previo Then code &= actual
previo = actual
If Len(code) = 4 Then Exit For
Next i
If Len(code) < 4 Then code &= String(4,"0")
Return Left(code,4)
End Function
 
Dim As String nombre
func soundex(s string) (string, error) {
For i As Byte var= sx1 [4]byteTo 20
varRead sxi intnombre
Print """"; nombre; """"; Tab(15); Soundex(nombre)
var cx, lastCode byte
Next i
for i, c := range s {
 
switch {
Data "Aschraft", "Ashcroft", "Euler", "Gauss", "Ghosh", "Hilbert", "Heilbronn", "Lee", "Lissajous", "Lloyd"
case !unicode.IsLetter(c):
Data "Moses", "Pfister", "Robert", "Rupert", "Rubin", "Tymczak", "VanDeusen", "Wheaton", "Soundex", "Example"
if c < ' ' || c == 127 {
Sleep
return "", errors.New("ASCII control characters disallowed")
</syntaxhighlight>
}
if i == 0 {
return "", errors.New("initial character must be a letter")
}
lastCode = '0'
continue
case c >= 'A' && c <= 'Z':
cx = byte(c - 'A')
case c >= 'a' && c <= 'z':
cx = byte(c - 'a')
default:
return "", errors.New("non-ASCII letters unsupported")
}
// cx is valid letter index at this point
if i == 0 {
sx[0] = cx + 'A'
sxi = 1
continue
}
switch x := code[cx]; x {
case '7', lastCode:
case '0':
lastCode = '0'
default:
sx[sxi] = x
if sxi == 3 {
return string(sx[:]), nil
}
sxi++
lastCode = x
}
}
if sxi == 0 {
return "", errors.New("no letters present")
}
for ; sxi < 4; sxi++ {
sx[sxi] = '0'
}
return string(sx[:]), nil
}
 
func main() {
for _, s := range []string{
"Robert", // WP test case = R163
"Rupert", // WP test case = R163
"Rubin", // WP test case = R150
"ashcroft", // WP test case = A261
"ashcraft", // s and c combine across h, t not needed
"moses", // s's don't combine across e
"O'Mally", // apostrophe allowed, adjacent ll's combine
"d jay", // spaces allowed
"R2-D2", // digits, hyphen allowed
"12p2", // just not in leading position
"naïve", // non ASCII disallowed
"", // empty string disallowed
"bump\t", // ASCII control characters disallowed
} {
if x, err := soundex(s); err == nil {
fmt.Println("soundex", s, "=", x)
} else {
fmt.Printf("\"%s\" fail. %s\n", s, err)
}
}
}</lang>
{{out}}
<pre>
soundex Robert = R163
soundex Rupert = R163
soundex Rubin = R150
soundex ashcroft = A261
soundex ashcraft = A261
soundex moses = M220
soundex O'Mally = O540
soundex d jay = D200
soundex R2-D2 = R300
"12p2" fail. initial character must be a letter
"naïve" fail. non-ASCII letters unsupported
"" fail. no letters present
"bump " fail. ASCII control characters disallowed
</pre>
 
=={{header|FutureBasic}}==
<langsyntaxhighlight lang="futurebasic">include "NSLog.incl"
include "ConsoleWindow"
 
def tab 12
_soundexNil$ = "0000"
 
local fn SoundexCode( charCode as unsigned char ) as unsigned char
local mode
select charCode
local fn Soundex( codeWord as Str255 ) as Str255
case _"B", _"F", _"P", _"V"
dim as long i,u
dim as unsigned char charCode,lastCode = _"1"
case _"C", _"G", _"J", _"K", _"Q", _"S", _"X", _"Z"
dim as Str31 outputStr
charCode = _"2"
case _"D", _"T"
charCode = _"3"
case _"L"
charCode = _"4"
case _"M", _"N"
charCode = _"5"
case _"R"
charCode = _"6"
case else
charCode = 0
end select
end fn = charCode
 
local fn SoundexCodeForWord( codeWord as CFStringRef ) as CFStringRef
outputStr = _soundexNil$
NSUInteger i
 
unsigned char charCode, lastCode
if codeWord[0] = _nil then exit fn
CFStringRef outputStr = @"0000"
 
CFMutableStringRef tempStr
UppercaseStripDiacritics( @codeWord[1], codeWord[0], _smCurrentScript )
 
if ( len(codeWord) == 0 ) then exit fn
outputStr[1] = codeWord[1]
charCode = outputStr[1] : gosub "getSoundexCode"
tempStr = fn MutableStringWithCapacity(0)
lastCode = charCode
codeWord = ucase(fn StringByApplyingTransform( codeWord, NSStringTransformStripDiacritics, NO ))
i = 1 : u = 1
 
MutableStringAppendString( tempStr, left(codeWord,1) )
while i <= codeWord[0]
charCode i++= :fn charCode =StringCharacterAtIndex( codeWord[i] :, gosub0 "getSoundexCode")
if charCode >= 0fn andSoundexCode( lastCodecharCode <> charCode)
u++ : outputStr[u]lastCode = charCode
i = 0
if u = 4 then exit while
while i < len(codeWord) - 1
end if
i++
lastCode = charCode
charCode = fn StringCharacterAtIndex( codeWord, i )
wend
charCode = fn SoundexCode( charCode )
 
if ( charCode > 0 and lastCode != charCode )
exit fn
MutableStringAppendString( tempStr, fn StringWithFormat( @"%c",charCode ) )
 
if ( len(tempStr) == 4 ) then break
"getSoundexCode"
end if
 
select lastCode = charCode
wend
case _"B", _"F", _"P", _"V"
charCode = _"1"
while ( len(tempStr) < 4 )
case _"C", _"G", _"J", _"K", _"Q", _"S", _"X", _"Z"
MutableStringAppendString( tempStr, @"0" )
charCode = _"2"
wend
case _"D", _"T"
charCode = _"3"
outputStr = fn StringWithString( tempStr )
case _"L"
charCode = _"4"
case _"M", _"N"
charCode = _"5"
case _"R"
charCode = _"6"
case else
charCode = 0
end select
return
end fn = outputStr
 
CFArrayRef names
dim as Str255 nameStr, testName(100)
CFStringRef name
dim as long i
 
names = @[
testName(0) = "Smith "
@"Smith",@"Johnson",@"Williams",@"Jones",@"Brown",@"Davis",@"Miller",@"Wilson",@"Moore",@"Taylor",
testName(1) = "Johnson "
@"Anderson",@"Thomas",@"Jackson",@"White",@"Harris",@"Martin",@"Thompson",@"Garcia",@"Martinez",@"Robinson",
testName(2) = "Williams "
@"Clark",@"Rodriguez",@"Lewis",@"Lee",@"Walker",@"Hall",@"Allen",@"Young",@"Hernandez",@"King",
testName(3) = "Jones "
@"Wright",@"Lopez",@"Hill",@"Scott",@"Green",@"Adams",@"Baker",@"Gonzalez",@"Nelson",@"Carter",
testName(4) = "Brown "
@"Mitchell",@"Perez",@"Roberts",@"Turner",@"Phillips",@"Campbell",@"Parker",@"Evans",@"Edwards",@"Collins",
testName(5) = "Davis "
@"Stewart",@"Sanchez",@"Morris",@"Rogers",@"Reed",@"Cook",@"Morgan",@"Bell",@"Murphy",@"Bailey",
testName(6) = "Miller "
@"Rivera",@"Cooper",@"Richardson",@"Cox",@"Howard",@"Ward",@"Torres",@"Peterson",@"Gray",@"Ramirez",
testName(7) = "Wilson "
@"James",@"Watson",@"Brooks",@"Kelly",@"Sanders",@"Price",@"Bennett",@"Wood",@"Barnes",@"Ross",
testName(8) = "Moore "
@"Henderson",@"Coleman",@"Jenkins",@"Perry",@"Powell",@"Long",@"Patterson",@"Hughes",@"Flores",@"Washington",
testName(9) = "Taylor "
@"Butler",@"Simmons",@"Foster",@"Gonzales",@"Bryant",@"Alexander",@"Russell",@"Griffin",@"Diaz",@"Hayes"
testName(10) = "Anderson "
]
testName(11) = "Thomas "
testName(12) = "Jackson "
testName(13) = "White "
testName(14) = "Harris "
testName(15) = "Martin "
testName(16) = "Thompson "
testName(17) = "Garcia "
testName(18) = "Martinez "
testName(19) = "Robinson "
testName(20) = "Clark "
testName(21) = "Rodriguez "
testName(22) = "Lewis "
testName(23) = "Lee "
testName(24) = "Walker "
testName(25) = "Hall "
testName(26) = "Allen "
testName(27) = "Young "
testName(28) = "Hernandez "
testName(29) = "King "
testName(30) = "Wright "
testName(31) = "Lopez "
testName(32) = "Hill "
testName(33) = "Scott "
testName(34) = "Green "
testName(35) = "Adams "
testName(36) = "Baker "
testName(37) = "Gonzalez "
testName(38) = "Nelson "
testName(39) = "Carter "
testName(40) = "Mitchell "
testName(41) = "Perez "
testName(42) = "Roberts "
testName(43) = "Turner "
testName(44) = "Phillips "
testName(45) = "Campbell "
testName(46) = "Parker "
testName(47) = "Evans "
testName(48) = "Edwards "
testName(49) = "Collins "
testName(50) = "Stewart "
testName(51) = "Sanchez "
testName(52) = "Morris "
testName(53) = "Rogers "
testName(54) = "Reed "
testName(55) = "Cook "
testName(56) = "Morgan "
testName(57) = "Bell "
testName(58) = "Murphy "
testName(59) = "Bailey "
testName(60) = "Rivera "
testName(61) = "Cooper "
testName(62) = "Richardson "
testName(63) = "Cox "
testName(64) = "Howard "
testName(65) = "Ward "
testName(66) = "Torres "
testName(67) = "Peterson "
testName(68) = "Gray "
testName(69) = "Ramirez "
testName(70) = "James "
testName(71) = "Watson "
testName(72) = "Brooks "
testName(73) = "Kelly "
testName(74) = "Sanders "
testName(75) = "Price "
testName(76) = "Bennett "
testName(77) = "Wood "
testName(78) = "Barnes "
testName(79) = "Ross "
testName(80) = "Henderson "
testName(81) = "Coleman "
testName(82) = "Jenkins "
testName(83) = "Perry "
testName(84) = "Powell "
testName(85) = "Long "
testName(86) = "Patterson "
testName(87) = "Hughes "
testName(88) = "Flores "
testName(89) = "Washington "
testName(90) = "Butler "
testName(91) = "Simmons "
testName(92) = "Foster "
testName(93) = "Gonzales "
testName(94) = "Bryant "
testName(95) = "Alexander "
testName(96) = "Russell "
testName(97) = "Griffin "
testName(98) = "Diaz "
testName(99) = "Hayes "
 
NSLogSetTabInterval( 80 )
print "Soundex codes for 100 popular American surnames:"
NSLog( @"Soundex codes for %ld popular American surnames:",fn ArrayCount(names) )
for i = 0 to 99
for name in names
nameStr = testName(i)
NSLog( @"%@\t= %@",name,fn SoundexCodeForWord(name) )
print nameStr, "= "; fn Soundex( nameStr )
next
 
NSLog(@"")
print
print "Soundex codes for similar sounding names:"
 
NSLog( @"Soundex codes for similar sounding names:" )
print " Stuart = "; fn Soundex( "Stuart" )
printNSLog( @"Stewart Stuart\t= %@"; , fn SoundexSoundexCodeForWord( @"StewartStuart" ) )
printNSLog( @"Steward Stewart\t= %@";, fn SoundexSoundexCodeForWord( @"StewardStewart" ) )
printNSLog( @" Seward Steward\t= %@";, fn SoundexSoundexCodeForWord( @"SewardSteward" ) )
NSLog( @"Seward\t= %@" , fn SoundexCodeForWord( @"Seward" ) )
 
HandleEvents</syntaxhighlight>
</lang>
 
Output:
Line 1,958 ⟶ 2,236:
Steward = S363
Seward = S630
</pre>
 
=={{header|Go}}==
WP article rules, plus my interpretation for input validation.
<syntaxhighlight lang="go">package main
 
import (
"errors"
"fmt"
"unicode"
)
 
var code = []byte("01230127022455012623017202")
 
func soundex(s string) (string, error) {
var sx [4]byte
var sxi int
var cx, lastCode byte
for i, c := range s {
switch {
case !unicode.IsLetter(c):
if c < ' ' || c == 127 {
return "", errors.New("ASCII control characters disallowed")
}
if i == 0 {
return "", errors.New("initial character must be a letter")
}
lastCode = '0'
continue
case c >= 'A' && c <= 'Z':
cx = byte(c - 'A')
case c >= 'a' && c <= 'z':
cx = byte(c - 'a')
default:
return "", errors.New("non-ASCII letters unsupported")
}
// cx is valid letter index at this point
if i == 0 {
sx[0] = cx + 'A'
sxi = 1
continue
}
switch x := code[cx]; x {
case '7', lastCode:
case '0':
lastCode = '0'
default:
sx[sxi] = x
if sxi == 3 {
return string(sx[:]), nil
}
sxi++
lastCode = x
}
}
if sxi == 0 {
return "", errors.New("no letters present")
}
for ; sxi < 4; sxi++ {
sx[sxi] = '0'
}
return string(sx[:]), nil
}
 
func main() {
for _, s := range []string{
"Robert", // WP test case = R163
"Rupert", // WP test case = R163
"Rubin", // WP test case = R150
"ashcroft", // WP test case = A261
"ashcraft", // s and c combine across h, t not needed
"moses", // s's don't combine across e
"O'Mally", // apostrophe allowed, adjacent ll's combine
"d jay", // spaces allowed
"R2-D2", // digits, hyphen allowed
"12p2", // just not in leading position
"naïve", // non ASCII disallowed
"", // empty string disallowed
"bump\t", // ASCII control characters disallowed
} {
if x, err := soundex(s); err == nil {
fmt.Println("soundex", s, "=", x)
} else {
fmt.Printf("\"%s\" fail. %s\n", s, err)
}
}
}</syntaxhighlight>
{{out}}
<pre>
soundex Robert = R163
soundex Rupert = R163
soundex Rubin = R150
soundex ashcroft = A261
soundex ashcraft = A261
soundex moses = M220
soundex O'Mally = O540
soundex d jay = D200
soundex R2-D2 = R300
"12p2" fail. initial character must be a letter
"naïve" fail. non-ASCII letters unsupported
"" fail. no letters present
"bump " fail. ASCII control characters disallowed
</pre>
 
=={{header|Groovy}}==
<langsyntaxhighlight lang="groovy">
def soundex(s) {
def code = ""
Line 1,985 ⟶ 2,365:
println(soundex("Example"))
println(soundex("Ekzampul"))
</syntaxhighlight>
</lang>
 
=={{header|Haskell}}==
{{libheader|Text.PhoneticCode.Soundex}}
<langsyntaxhighlight lang="haskell">import Text.PhoneticCode.Soundex
 
main :: IO ()
main =
mapM_ print $
((,) <*> soundexSimple) <$> ["Soundex", "Example", "Sownteks", "Ekzampul"]</langsyntaxhighlight>
{{Out}}
<pre>("Soundex","S532")
Line 2,002 ⟶ 2,382:
 
=={{header|Icon}} and {{header|Unicon}}==
<langsyntaxhighlight lang="icon">procedure main(arglist) # computes soundex of each argument
every write(x := !arglist, " => ",soundex(x))
end
Line 2,022 ⟶ 2,402:
while name[upto('.',name)] := "" # kill .
return left(name,4,"0")
end</langsyntaxhighlight>
{{libheader|Icon Programming Library}} implements [http://www.cs.arizona.edu/icon/library/procs/soundex.htm soundex]. The above version is an adaptation of that procedure
 
=={{header|IS-BASIC}}==
<syntaxhighlight lang="is-basic">100 PROGRAM "Soundex.bas"
110 FOR I=1 TO 20
120 READ NAME$
130 PRINT """";NAME$;"""";TAB(20);SOUNDEX$(NAME$)
140 NEXT
150 DEF SOUNDEX$(NAME$)
160 NUMERIC I,N,P
170 LET NAME$=UCASE$(NAME$):LET S$=NAME$(1)
180 LET N$="01230129022455012623019202"
190 LET P=VAL(N$(ORD(S$)-64))
200 FOR I=2 TO LEN(NAME$)
210 LET N=VAL(N$(ORD(NAME$(I))-64))
220 IF N<>0 AND N<>9 AND N<>P THEN LET S$=S$&STR$(N)
230 IF N<>9 THEN LET P=N
240 NEXT
250 LET S$=S$&"000"
260 LET SOUNDEX$=S$(1:4)
270 END DEF
280 DATA Aschraft,Ashcroft,Euler,Gauss,Ghosh,Hilbert,Heilbronn,Lee,Lissajous,Lloyd
290 DATA Moses,Pfister,Robert,Rupert,Rubin,Tymczak,VanDeusen,Wheaton,Soundex,Example</syntaxhighlight>
 
=={{header|J}}==
'''Solution'''
<langsyntaxhighlight lang="j">removeDups =: {.;.1~ (1 , }. ~: }: )
codes =: ;: 'BFPV CGJKQSXZ DT L MN R HW'
Line 2,033 ⟶ 2,435:
if. 0=# k=.toupper y do. '0' return. end.
({.k), ,": ,. 3 {. 0-.~ }. removeDups 7 0:`(I.@:=)`]} , k >:@I.@:(e. &>)"0 _ codes
)</langsyntaxhighlight>
'''Usage'''
<langsyntaxhighlight lang="j">names=: 'Lloyd Woolcock Donnell Baragwanath Williams Ashcroft Euler Ellery Gauss Ghosh Hilbert Heilbronn Knuth Kant Ladd Lukasiewicz Lissajous'
soundexNames=: 'L300 W422 D540 B625 W452 A226 E460 E460 G200 G200 H416 H416 K530 K530 L300 L222 L222'
 
Line 2,044 ⟶ 2,446:
B625
W452
....</langsyntaxhighlight>
'''Test'''
<langsyntaxhighlight lang="j"> soundexNames-:(soundex &.>) &. ;: names
1</langsyntaxhighlight>
 
=={{header|Java}}==
{{trans|VBScript}}
<langsyntaxhighlight lang="java">public static void main(String[] args){
System.out.println(soundex("Soundex"));
System.out.println(soundex("Example"));
Line 2,094 ⟶ 2,496:
soundex = (code + "0000").substring(0, 4);
return soundex;
}</langsyntaxhighlight>
{{out}}
<pre>S532
Line 2,105 ⟶ 2,507:
===ES5===
==== Version w/o RegExp ====
<langsyntaxhighlight lang="javascript">var soundex = function (s) {
var a = s.toLowerCase().split('')
f = a.shift(),
Line 2,185 ⟶ 2,587:
// Burroughs B622 B622 true
// Burrows B620 B620 true
// O'Hara O600 O600 true</langsyntaxhighlight>
 
 
Line 2,192 ⟶ 2,594:
Note: This version differs from the one above in the following way. According to U.S. National Archives Website, consecutive consonants which map to the same code are not condensed to a single occurrence of the code if they are separated by vowels, but separating W and H do not thus intervene. Therefore Ashcraft is coded A261 and Burroughs is coded B620 rather than A226 and B622
 
<langsyntaxhighlight lang="javascript">
function soundex(t) {
t = t.toUpperCase().replace(/[^A-Z]/g, '');
Line 2,234 ⟶ 2,636:
console.log('soundex("' + a + '") was ' + d + ' should be ' + t);
}
}); </langsyntaxhighlight>
 
===ES6===
Line 2,241 ⟶ 2,643:
(Reusing set of tests from second contribution)
 
<langsyntaxhighlight JavaScriptlang="javascript">(() => {
'use strict';
 
Line 2,369 ⟶ 2,771:
) : a;
}, '');
})();</langsyntaxhighlight>
 
{{Out}}
Line 2,379 ⟶ 2,781:
=={{header|Julia}}==
There is a Soundex package for Julia. If that is used:
<langsyntaxhighlight lang="julia">
using Soundex
@assert soundex("Ashcroft") == "A261" # true
 
# Too trivial? OK. Here is an example not using a package:
 
function soundex(s)
char2num = Dict('B'=>1,'F'=>1,'P'=>1,'V'=>1,'C'=>2,'G'=>2,'J'=>2,'K'=>2,
Line 2,404 ⟶ 2,805:
hadvowel = false
end
elseif c in ('A', 'E', 'I', 'O', 'U', 'Y')
hadvowel = true
end
if length(ret) >= 4
break
end
end
Line 2,414 ⟶ 2,812:
ret *= "0"
end
ret[1:4]
end
 
@assert soundex("Ascroft") == "A261"
@assert soundex("Euler") == "E460"
Line 2,435 ⟶ 2,832:
@assert soundex("Burrows") == "B620"
@assert soundex("O'Hara") == "O600"
</syntaxhighlight>
</lang>
 
=={{header|Kotlin}}==
{{trans|VBScript}}
<langsyntaxhighlight lang="scala">// version 1.1.2
 
fun getCode(c: Char) = when (c) {
Line 2,486 ⟶ 2,883:
println("${pair.first.padEnd(9)} -> ${pair.second} -> ${soundex(pair.first) == pair.second}")
}
}</langsyntaxhighlight>
 
{{out}}
Line 2,507 ⟶ 2,904:
Example -> E251 -> true
</pre>
 
 
=={{header|Lua}}==
Adapt from D Alternative
<langsyntaxhighlight Lualang="lua">local d, digits, alpha = '01230120022455012623010202', {}, ('A'):byte()
d:gsub(".",function(c)
digits[string.char(alpha)] = c
Line 2,552 ⟶ 2,948:
assert( soundex(itm[1])==itm[2] )
end
print"all tests ok"</langsyntaxhighlight>
{{out}}
<pre>all tests ok</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<langsyntaxhighlight Mathematicalang="mathematica">Soundex[ input_ ] := Module[{x = input, head, body},
{head, body} = {First@#, Rest@#}&@ToLowerCase@Characters@x;
body = (Select[body, FreeQ[Characters["aeiouyhw"],#]&] /. {("b"|"f"|"p"|"v")->1,
Line 2,565 ⟶ 2,961:
body = DeleteDuplicates[body]
];
StringJoin @@ ToString /@ PrependTo[ body[[1 ;; 3]], ToUpperCase@head]]</langsyntaxhighlight>
Example usage:
<pre>Map[Soundex,{"Soundex", "Sownteks", "Example", "Ekzampul"}]
Line 2,571 ⟶ 2,967:
 
=={{header|MUMPS}}==
<langsyntaxhighlight MUMPSlang="mumps">SOUNDEX(X,NARA=0)
;Converts a string to its Soundex value.
;Empty strings return "0000". Non-alphabetic ASCII characters are ignored.
Line 2,619 ⟶ 3,015:
KILL UP,LO,PREFIX,X1,X2,Y2,C,DX,XD
QUIT Y
</syntaxhighlight>
</lang>
<p>Examples:<pre>
USER>W $$SOUNDEX^SOUNDEX("")
Line 2,657 ⟶ 3,053:
USER>W $$SOUNDEX^SOUNDEX("ghoti")
G300</pre></p>
 
=={{header|NetRexx}}==
{{trans|Rexx}}
<syntaxhighlight lang="netrexx">
class Soundex
 
method get_soundex(in_) static
in = in_.upper()
old_alphabet= 'AEIOUYHWBFPVCGJKQSXZDTLMNR'
new_alphabet= '@@@@@@**111122222222334556'
word=''
loop i=1 for in.length()
tmp_=in.substr(i, 1) /*obtain a character from word*/
if tmp_.datatype('M') then word=word||tmp_
end
 
value=word.strip.left(1) /*1st character is left alone.*/
word=word.translate(new_alphabet, old_alphabet) /*define the current word. */
prev=value.translate(new_alphabet, old_alphabet) /* " " previous " */
 
loop j=2 to word.length() /*process remainder of word. */
q=word.substr(j, 1)
if q\==prev & q.datatype('W') then do
value=value || q; prev=q
end
else if q=='@' then prev=q
end /*j*/
 
return value.left(4,0) /*padded value with zeroes. */
 
method main(args=String[]) static
 
test=''; result_=''
test['1']= "12346" ; result_['1']= '0000'
test['4']= "4-H" ; result_['4']= 'H000'
test['11']= "Ashcraft" ; result_['11']= 'A261'
test['12']= "Ashcroft" ; result_['12']= 'A261'
test['18']= "auerbach" ; result_['18']= 'A612'
test['20']= "Baragwanath" ; result_['20']= 'B625'
test['22']= "bar" ; result_['22']= 'B600'
test['23']= "barre" ; result_['23']= 'B600'
test['20']= "Baragwanath" ; result_['20']= 'B625'
test['28']= "Burroughs" ; result_['28']= 'B620'
test['29']= "Burrows" ; result_['29']= 'B620'
test['30']= "C.I.A." ; result_['30']= 'C000'
test['37']= "coöp" ; result_['37']= 'C100'
test['43']= "D-day" ; result_['43']= 'D000'
test['44']= "d jay" ; result_['44']= 'D200'
test['45']= "de la Rosa" ; result_['45']= 'D462'
test['46']= "Donnell" ; result_['46']= 'D540'
test['47']= "Dracula" ; result_['47']= 'D624'
test['48']= "Drakula" ; result_['48']= 'D624'
test['49']= "Du Pont" ; result_['49']= 'D153'
test['50']= "Ekzampul" ; result_['50']= 'E251'
test['51']= "example" ; result_['51']= 'E251'
test['55']= "Ellery" ; result_['55']= 'E460'
test['59']= "Euler" ; result_['59']= 'E460'
test['60']= "F.B.I." ; result_['60']= 'F000'
test['70']= "Gauss" ; result_['70']= 'G200'
test['71']= "Ghosh" ; result_['71']= 'G200'
test['72']= "Gutierrez" ; result_['72']= 'G362'
test['80']= "he" ; result_['80']= 'H000'
test['81']= "Heilbronn" ; result_['81']= 'H416'
test['84']= "Hilbert" ; result_['84']= 'H416'
test['100']= "Jackson" ; result_['100']= 'J250'
test['104']= "Johnny" ; result_['104']= 'J500'
test['105']= "Jonny" ; result_['105']= 'J500'
test['110']= "Kant" ; result_['110']= 'K530'
test['116']= "Knuth" ; result_['116']= 'K530'
test['120']= "Ladd" ; result_['120']= 'L300'
test['124']= "Llyod" ; result_['124']= 'L300'
test['125']= "Lee" ; result_['125']= 'L000'
test['126']= "Lissajous" ; result_['126']= 'L222'
test['128']= "Lukasiewicz" ; result_['128']= 'L222'
test['130']= "naïve" ; result_['130']= 'N100'
test['141']= "Miller" ; result_['141']= 'M460'
test['143']= "Moses" ; result_['143']= 'M220'
test['146']= "Moskowitz" ; result_['146']= 'M232'
test['147']= "Moskovitz" ; result_['147']= 'M213'
test['150']= "O'Conner" ; result_['150']= 'O256'
test['151']= "O'Connor" ; result_['151']= 'O256'
test['152']= "O'Hara" ; result_['152']= 'O600'
test['153']= "O'Mally" ; result_['153']= 'O540'
test['161']= "Peters" ; result_['161']= 'P362'
test['162']= "Peterson" ; result_['162']= 'P362'
test['165']= "Pfister" ; result_['165']= 'P236'
test['180']= "R2-D2" ; result_['180']= 'R300'
test['182']= "rÄ≈sumÅ∙" ; result_['182']= 'R250'
test['184']= "Robert" ; result_['184']= 'R163'
test['185']= "Rupert" ; result_['185']= 'R163'
test['187']= "Rubin" ; result_['187']= 'R150'
test['191']= "Soundex" ; result_['191']= 'S532'
test['192']= "sownteks" ; result_['192']= 'S532'
test['199']= "Swhgler" ; result_['199']= 'S460'
test['202']= "'til" ; result_['202']= 'T400'
test['208']= "Tymczak" ; result_['208']= 'T522'
test['216']= "Uhrbach" ; result_['216']= 'U612'
test['221']= "Van de Graaff" ; result_['221']= 'V532'
test['222']= "VanDeusen" ; result_['222']= 'V532'
test['230']= "Washington" ; result_['230']= 'W252'
test['233']= "Wheaton" ; result_['233']= 'W350'
test['234']= "Williams" ; result_['234']= 'W452'
test['236']= "Woolcock" ; result_['236']= 'W422'
 
loop i over test
say test[i].left(10) get_soundex(test[i]) '=' result_[i]
end
</syntaxhighlight>
{{out}}
<pre>
barre B600 = B600
Wheaton W350 = W350
Knuth K530 = K530
auerbach A612 = A612
Ekzampul E251 = E251
D-day D000 = D000
example E251 = E251
4-H H000 = H000
Burroughs B620 = B620
d jay D200 = D200
F.B.I. F000 = F000
Lissajous L222 = L222
Burrows B620 = B620
coöp C100 = C100
de la Rosa D462 = D462
Gauss G200 = G200
Donnell D540 = D540
Ghosh G200 = G200
Dracula D624 = D624
Ellery E460 = E460
he H000 = H000
Gutierrez G362 = G362
Drakula D624 = D624
Williams W452 = W452
Heilbronn H416 = H416
Du Pont D153 = D153
Robert R163 = R163
Pfister P236 = P236
Moskowitz M232 = M232
Euler E460 = E460
Hilbert H416 = H416
Rupert R163 = R163
Uhrbach U612 = U612
Moskovitz M213 = M213
Lukasiewic L222 = L222
Woolcock W422 = W422
Tymczak T522 = T522
Rubin R150 = R150
Swhgler S460 = S460
Jackson J250 = J250
Kant K530 = K530
Ladd L300 = L300
naïve N100 = N100
O'Conner O256 = O256
Miller M460 = M460
O'Connor O256 = O256
Washington W252 = W252
R2-D2 R300 = R300
Peters P362 = P362
Van de Gra V532 = V532
Johnny J500 = J500
'til T400 = T400
O'Hara O600 = O600
Peterson P362 = P362
Moses M220 = M220
Llyod L300 = L300
Soundex S532 = S532
VanDeusen V532 = V532
Jonny J500 = J500
O'Mally O540 = O540
12346 000 = 0000
Ashcraft A261 = A261
rÄ≈sumÅ∙ R250 = R250
Ashcroft A261 = A261
Baragwanat B625 = B625
Lee L000 = L000
bar B600 = B600
C.I.A. C000 = C000
sownteks S532 = S532
</pre>
 
=={{header|Nim}}==
<syntaxhighlight lang="nim">import strutils
 
const
Wovel = 'W' # Character code used to specify a wovel.
Ignore = ' ' # Character code used to specify a character to ignore ('h', 'w' or non-letter).
 
 
proc code(ch: char): char =
## Return the soundex code for a character.
case ch.toLowerAscii()
of 'b', 'f', 'p', 'v': '1'
of 'c', 'g', 'j', 'k', 'q', 's', 'x', 'z': '2'
of 'd', 't': '3'
of 'l': '4'
of 'm', 'n': '5'
of 'r': '6'
of 'a', 'e', 'i', 'o', 'u', 'y': Wovel
else: Ignore
 
proc soundex(str: string): string =
## Return the soundex for the given string.
 
result.add str[0] # Store the first letter.
 
# Process characters.
var prev = code(str[0])
for i in 1..str.high:
let curr = code(str[i])
if curr != Ignore:
if curr != Wovel and curr != prev:
result.add curr
prev = curr
 
# Make sure the result has four characters.
if result.len > 4:
result.setLen(4)
else:
for _ in result.len..3:
result.add '0'
 
 
for name in ["Robert", "Rupert", "Rubin", "Ashcraft", "Ashcroft", "Tymczak",
"Pfister", "Honeyman", "Moses", "O'Mally", "O'Hara", "D day"]:
echo name.align(8), " ", soundex(name)</syntaxhighlight>
 
{{out}}
<pre> Robert R163
Rupert R163
Rubin R150
Ashcraft A261
Ashcroft A261
Tymczak T522
Pfister P236
Honeyman H555
Moses M220
O'Mally O540
O'Hara O600
D day D000</pre>
 
=={{header|Objeck}}==
{{trans|Java}}
 
<syntaxhighlight lang="objeck">class SoundEx {
function : Main(args : String[]) ~ Nil {
SoundEx("Soundex")->PrintLine();
SoundEx("Example")->PrintLine();
SoundEx("Sownteks")->PrintLine();
SoundEx("Ekzampul")->PrintLine();
}
 
function : SoundEx(s : String) ~ String {
input := s->ToUpper()->Get(0);
code := input->ToString();
previous := GetCode(input);
 
for(i := 1; i < s->Size(); i += 1;) {
current := GetCode(s->ToUpper()->Get(i));
if(current->Size() > 0 & <>current->Equals(previous)) {
code += current;
};
previous := current;
};
 
soundex := String->New(code);
soundex += "0000";
return soundex->SubString(4);
}
 
function : GetCode(c : Char) ~ String {
select(c) {
label 'B': label 'F':
label 'P': label 'V': {
return "1";
}
 
label 'C': label 'G':
label 'J': label 'K':
label 'Q': label 'S':
label 'X': label 'Z': {
return "2";
}
 
label 'D': label 'T': {
return "3";
}
 
label 'L': {
return "4";
}
 
label 'M': label 'N': {
return "5";
}
 
label 'R': {
return "6";
}
 
other: {
return "";
}
};
}
}
</syntaxhighlight>
 
{{out}}
<pre>
S532
E251
S532
E251
</pre>
 
=={{header|OCaml}}==
Line 2,662 ⟶ 3,373:
Here is an implementation:
 
<langsyntaxhighlight lang="ocaml">let c2d = function
| 'B' | 'F' | 'P' | 'V' -> "1"
| 'C' | 'G' | 'J' | 'K' | 'Q' | 'S' | 'X' | 'Z' -> "2"
Line 2,696 ⟶ 3,407:
match dbl [] (List.rev !cl) with
| c::rem -> (String.make 1 c) ^ (soundex_aux rem)
| [] -> invalid_arg "soundex"</langsyntaxhighlight>
 
Test our implementation:
 
<langsyntaxhighlight lang="ocaml">let tests = [
"Soundex", "S532";
"Example", "E251";
Line 2,730 ⟶ 3,441:
let status = if code1 = code2 then "OK " else "Arg" in
Printf.printf " \"%s\" \t %s %s %s\n" word code1 code2 status
) tests</langsyntaxhighlight>
 
{{out}}
Line 2,764 ⟶ 3,475:
{{works with|Free Pascal|2.6.2}}
 
<langsyntaxhighlight Pascallang="pascal">program Soundex;
 
{$mode objfpc}{$H+}
Line 2,871 ⟶ 3,582:
end;
ReadLn;
End.</langsyntaxhighlight>
 
{{out}}
Line 2,894 ⟶ 3,605:
=={{header|Perl}}==
The <tt>Text::Soundex</tt> core module supports various soundex algorithms.
<langsyntaxhighlight lang="perl">use Text::Soundex;
print soundex("Soundex"), "\n"; # S532
print soundex("Example"), "\n"; # E251
print soundex("Sownteks"), "\n"; # S532
print soundex("Ekzampul"), "\n"; # E251</langsyntaxhighlight>
 
=={{header|Perl 6Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
US census algorithm, so "Ashcraft" and "Burroughs" adjusted to match.
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
We fake up a first consonant in some cases to make up for the fact that we always trim the first numeric code (so that the 'l' of 'Lloyd' is properly deleted).
<span style="color: #008080;">constant</span> <span style="color: #000000;">soundex_alphabet</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"0123012#02245501262301#202"</span>
<lang perl6>sub soundex ($name --> Str) {
<span style="color: #000080;font-style:italic;">-- ABCDEFGHIJKLMNOPQRSTUVWXYZ</span>
my $first = substr($name,0,1).uc;
gather {
<span style="color: #008080;">function</span> <span style="color: #000000;">soundex</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">name</span><span style="color: #0000FF;">)</span>
take $first;
<span style="color: #004080;">string</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"0000"</span>
my $fakefirst = '';
<span style="color: #004080;">integer</span> <span style="color: #000000;">rdx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">curr</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">prev</span>
$fakefirst = "de " if $first ~~ /^ <[AEIOUWH]> /;
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">name</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
"$fakefirst$name".lc.trans('wh' => '') ~~ /
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">upper</span><span style="color: #0000FF;">(</span><span style="color: #000000;">name</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
^
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">>=</span><span style="color: #008000;">'A'</span> <span style="color: #008080;">and</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;"><=</span><span style="color: #008000;">'Z'</span> <span style="color: #008080;">then</span>
[
<span style="color: #000000;">curr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">soundex_alphabet</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">-</span><span style="color: #008000;">'A'</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
[
<span style="color: #008080;">if</span> <span style="color: #000000;">rdx</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
| <[ bfpv ]>+ { take 1 }
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ch</span>
| <[ cgjkqsxz ]>+ { take 2 }
<span style="color: #000000;">rdx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span>
| <[ dt ]>+ { take 3 }
<span style="color: #000000;">prev</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">curr</span>
| <[ l ]>+ { take 4 }
<span style="color: #008080;">elsif</span> <span style="color: #000000;">curr</span><span style="color: #0000FF;">!=</span><span style="color: #008000;">'#'</span> <span style="color: #008080;">then</span>
| <[ mn ]>+ { take 5 }
<span style="color: #008080;">if</span> <span style="color: #000000;">curr</span><span style="color: #0000FF;">!=</span><span style="color: #008000;">'0'</span> <span style="color: #008080;">and</span> <span style="color: #000000;">curr</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">prev</span> <span style="color: #008080;">then</span>
| <[ r ]>+ { take 6 }
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">rdx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">curr</span>
]
<span style="color: #008080;">if</span> <span style="color: #000000;">rdx</span><span style="color: #0000FF;">=</span><span style="color: #000000;">4</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|| .
<span style="color: #000000;">rdx</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
]+
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
$ { take 0,0,0 }
<span style="color: #000000;">prev</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">curr</span>
/;
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
}.flat.[0,2,3,4].join;
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
}
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
 
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
for < Soundex S532
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
Example E251
Sownteks S532
<span style="color: #008080;">constant</span> <span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span>
Ekzampul E251
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Ashcraft"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"A261"</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- not "A226"</span>
Euler E460
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Ashcroft"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"A261"</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- not "A226"</span>
Gauss G200
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Ashkrofd"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"A261"</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- not "A226"</span>
Hilbert H416
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Burroughs"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"B620"</span><span style="color: #0000FF;">},</span>
Knuth K530
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Burrows"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"B620"</span><span style="color: #0000FF;">},</span>
Lloyd L300
<span style="color: #0000FF;">{</span><span style="color: #008000;">"ciondecks"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"C532"</span><span style="color: #0000FF;">},</span>
Lukasiewicz L222
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Example"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"E251"</span><span style="color: #0000FF;">},</span>
Ellery E460
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Ekzampul"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"E251"</span><span style="color: #0000FF;">},</span>
Ghosh G200
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Ellery"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"E460"</span><span style="color: #0000FF;">},</span>
Heilbronn H416
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Euler"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"E460"</span><span style="color: #0000FF;">},</span>
Kant K530
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Gauss"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"G200"</span><span style="color: #0000FF;">},</span>
Ladd L300
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Ghosh"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"G200"</span><span style="color: #0000FF;">},</span>
Lissajous L222
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Gutierrez"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"G362"</span><span style="color: #0000FF;">},</span>
Wheaton W350
<span style="color: #0000FF;">{</span><span style="color: #008000;">"He"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"H000"</span><span style="color: #0000FF;">},</span>
Ashcraft A261
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Heilbronn"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"H416"</span><span style="color: #0000FF;">},</span>
Burroughs B620
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Hilbert"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"H416"</span><span style="color: #0000FF;">},</span>
Burrows B620
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Honeyman"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"H555"</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- not "H500"</span>
O'Hara O600 >
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Jackson"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"J250"</span><span style="color: #0000FF;">},</span>
-> $n, $s {
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Kant"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"K530"</span><span style="color: #0000FF;">},</span>
my $s2 = soundex($n);
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Knuth"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"K530"</span><span style="color: #0000FF;">},</span>
say $n.fmt("%16s "), $s, $s eq $s2 ?? " OK" !! " NOT OK $s2";
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Lee"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"L000"</span><span style="color: #0000FF;">},</span>
}</lang>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Ladd"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"L300"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Lloyd"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"L300"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Lissajous"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"L222"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Lukasiewicz"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"L222"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Moses"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"M220"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"O'Hara"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"O600"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Pfister"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"P236"</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- not "P123"</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Robert"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"R163"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Rupert"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"R163"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Rubin"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"R150"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"r~@sum~@"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"R250"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Soundex"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"S532"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Sownteks"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"S532"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Tymczak"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"T522"</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- not "T520"</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"VanDeusen"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"V532"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Washington"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"W252"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Wheaton"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"W350"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Weeton"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"W350"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">""</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"0000"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">" "</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"0000"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"12346"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"0000"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"aaa a"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"A000"</span><span style="color: #0000FF;">}</span>
<span style="color: #0000FF;">}</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">string</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">name</span><span style="color: #0000FF;">,</span><span style="color: #000000;">expected</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">soundex</span><span style="color: #0000FF;">(</span><span style="color: #000000;">name</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">ok</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">=</span><span style="color: #000000;">expected</span><span style="color: #0000FF;">?</span><span style="color: #008000;">""</span><span style="color: #0000FF;">:</span><span style="color: #008000;">"*** ERROR ***"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%-12s -&gt; %s %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">name</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ok</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
<pre> Soundex S532 OK
Ashcraft -> A261
Example E251 OK
Ashcroft -> A261
Sownteks S532 OK
Ashkrofd -> A261
Ekzampul E251 OK
Burroughs -> B620
Euler E460 OK
Burrows -> Gauss G200 OKB620
ciondecks -> C532
Hilbert H416 OK
Example -> Knuth K530 OKE251
Ekzampul -> E251
Lloyd L300 OK
Ellery -> E460
Lukasiewicz L222 OK
Euler Ellery-> E460 OK
Gauss Ghosh-> G200 OK
Ghosh Heilbronn H416-> OKG200
Gutierrez -> G362
Kant K530 OK
He -> Ladd L300 OKH000
Heilbronn -> H416
Lissajous L222 OK
Hilbert -> Wheaton W350 OKH416
Honeyman -> H555
Ashcraft A261 OK
Jackson -> Burroughs B620 OKJ250
Kant Burrows-> B620 OKK530
Knuth -> O'Hara O600 OK</pre>K530
Lee -> L000
Ladd -> L300
Lloyd -> L300
Lissajous -> L222
Lukasiewicz -> L222
Moses -> M220
O'Hara -> O600
Pfister -> P236
Robert -> R163
Rupert -> R163
Rubin -> R150
r~@sum~@ -> R250
Soundex -> S532
Sownteks -> S532
Tymczak -> T522
VanDeusen -> V532
Washington -> W252
Wheaton -> W350
Weeton -> W350
-> 0000
-> 0000
12346 -> 0000
aaa a -> A000
</pre>
 
=={{header|PHP}}==
PHP already has a built-in <tt>soundex()</tt> function:
<langsyntaxhighlight lang="php"><?php
echo soundex("Soundex"), "\n"; // S532
echo soundex("Example"), "\n"; // E251
echo soundex("Sownteks"), "\n"; // S532
echo soundex("Ekzampul"), "\n"; // E251
?></langsyntaxhighlight>
 
=={{header|Picat}}==
{{trans|C#}}
<syntaxhighlight lang="picat">go =>
Names = split("Lloyd Woolcock Donnell Baragwanath Williams Ashcroft Ashcraft Euler
Ellery Gauss Ghosh Hilbert Heilbronn Knuth Kant Ladd Lukasiewicz Lissajous O'Hara"),
SoundexNames = split("L300 W422 D540 B625 W452 A261 A261 E460
E460 G200 G200 H416 H416 K530 K530 L300 L222 L222 O600"),
 
foreach({Name,Correct} in zip(Names, SoundexNames))
S = soundex(Name),
printf("%s: %s ",Name,S),
if S == Correct then
println("ok")
else
printf("not correct! Should be: %s\n", Correct)
end
end,
nl.
 
soundex("", _) = "" => true.
soundex(Word) = Soundex =>
SoundexAlphabet = "0123012#02245501262301#202",
Soundex = "",
LastC = '?',
foreach(Ch in Word.to_uppercase,
C = ord(Ch), C >= 0'A', C <= 0'Z',
Soundex.len < 4)
ThisC := SoundexAlphabet[C-0'A'+1],
Skip = false, % to handle '#'
if Soundex.len == 0 then
Soundex := Soundex ++ [Ch]
elseif ThisC == '#' then
Skip := true
elseif ThisC != '0', ThisC != LastC then
Soundex := Soundex ++ [ThisC]
end,
if Skip == false then
LastC := ThisC
end
end,
Soundex := Soundex.padRight(4,'0').
 
padRight(S,Len,PadChar) = S ++ [PadChar : _ in 1..Len-S.len].</syntaxhighlight>
 
{{out}}
<pre>Lloyd: L300 ok
Woolcock: W422 ok
Donnell: D540 ok
Baragwanath: B625 ok
Williams: W452 ok
Ashcroft: A261 ok
Ashcraft: A261 ok
Euler: E460 ok
Ellery: E460 ok
Gauss: G200 ok
Ghosh: G200 ok
Hilbert: H416 ok
Heilbronn: H416 ok
Knuth: K530 ok
Kant: K530 ok
Ladd: L300 ok
Lukasiewicz: L222 ok
Lissajous: L222 ok
O'Hara: O600 ok</pre>
 
=={{header|PicoLisp}}==
Simple:
<langsyntaxhighlight PicoLisplang="picolisp">(de soundex (Str)
(pack
(pad -4
Line 3,006 ⟶ 3,837:
(<> Last C)
(setq Last C) ) )
(cdr (chop Str)) ) ) ) ) ) ) )</langsyntaxhighlight>
NARA:
<langsyntaxhighlight PicoLisplang="picolisp">(de soundex (Str)
(let (Str (chop Str) Last)
(pack
Line 3,034 ⟶ 3,865:
(<> Last C)
(setq Last C) ) )
Str ) ) ) ) ) ) ) ) )</langsyntaxhighlight>
 
=={{header|PL/I}}==
<langsyntaxhighlight PLlang="pl/Ii">Soundex: procedure (pword) returns (character(4));
declare pword character (*) varying, value character (length(pword)) varying;
declare word character (length(pword));
Line 3,075 ⟶ 3,906:
return ( left(value, 4, '0') ); /* Pad, if necessary. */
end Soundex;</langsyntaxhighlight>
 
=={{header|PowerShell}}==
{{works with|PowerShell 3.0}}
<syntaxhighlight lang="powershell">
<lang PowerShell>
function Get-Soundex
{
Line 3,161 ⟶ 3,992:
}
}
</syntaxhighlight>
</lang>
<syntaxhighlight lang="powershell">
<lang PowerShell>
"Ashcraft", "Ashcroft", "Gauss", "Ghosh", "Hilbert", "Heilbronn", "Lee", "Lloyd",
"Moses", "Pfister", "Robert", "Rupert", "Rubin", "Tymczak", "Soundex", "Example" | Get-Soundex
</syntaxhighlight>
</lang>
{{Out}}
<pre>
Line 3,186 ⟶ 4,017:
Soundex S532
Example E251
</pre>
===Alternative Version===
Here we're using as much PowerShell native functionaity as possible, without reaching deep into .NET libraries. The goal here is to have script that can be called from the prompt to be easily used in other scripts.
<syntaxhighlight lang="powershell">
# script Soundex.ps1
Param([string]$Phrase)
Process {
$src = $Phrase.ToUpper().Trim()
$coded = $src[0..($src.Length - 1)] | %{
if('BFPV'.Contains($_)) { '1' }
elseif('CGJKQSXZ'.Contains($_)) { '2' }
elseif('DT'.Contains($_)) { '3' }
elseif('L'.Contains($_)) { '4' }
elseif('MN'.Contains($_)) { '5' }
elseif('R'.Contains($_)) { '6' }
elseif('AEIOU'.Contains($_)) { 'v' }
else { '.' }
} | Where { $_ -ne '.'}
$coded2 = 0..($coded.Length - 1) | %{ if ($_ -eq 0 -or $coded[$_] -ne $coded[$_ - 1]) { $coded[$_] } else { '' } }
$coded2 = if ($coded[0] -eq 'v' -or $coded2[0] -ne $coded[0]) { $coded2 } else { $coded2[1..($coded2.Length - 1)] }
$src[0] + ((-join $($coded2 | Where { $_ -ne 'v'})) + "000").Substring(0,3)
}
</syntaxhighlight>
 
<syntaxhighlight lang="powershell">
Function t([string]$value, [string]$expect) {
$result = .\Soundex.ps1 -Phrase $value
New-Object –TypeName PSObject –Prop @{ "Value"=$value; "Expect"=$expect; "Result"=$result; "Pass"=$($expect -eq $result) }
}
@(
(t "Ashcraft" "A261"); (t "Ashcroft" "A261"); (t "Burroughs" "B620"); (t "Burrows" "B620");
(t "Ekzampul" "E251"); (t "Example" "E251"); (t "Ellery" "E460"); (t "Euler" "E460");
(t "Ghosh" "G200"); (t "Gauss" "G200"); (t "Gutierrez" "G362"); (t "Heilbronn" "H416");
(t "Hilbert" "H416"); (t "Jackson" "J250"); (t "Kant" "K530"); (t "Knuth" "K530");
(t "Lee" "L000"); (t "Lukasiewicz" "L222"); (t "Lissajous" "L222"); (t "Ladd" "L300");
(t "Lloyd" "L300"); (t "Moses" "M220"); (t "O'Hara" "O600"); (t "Pfister" "P236");
(t "Rubin" "R150"); (t "Robert" "R163"); (t "Rupert" "R163"); (t "Soundex" "S532");
(t "Sownteks" "S532"); (t "Tymczak" "T522"); (t "VanDeusen" "V532"); (t "Washington" "W252");
(t "Wheaton" "W350");
) | Format-Table -Property Value,Expect,Result,Pass
</syntaxhighlight>
{{Out}}
<pre>
Value Expect Result Pass
----- ------ ------ ----
Ashcraft A261 A261 True
Ashcroft A261 A261 True
Burroughs B620 B620 True
Burrows B620 B620 True
Ekzampul E251 E251 True
Example E251 E251 True
Ellery E460 E460 True
Euler E460 E460 True
Ghosh G200 G200 True
Gauss G200 G200 True
Gutierrez G362 G362 True
Heilbronn H416 H416 True
Hilbert H416 H416 True
Jackson J250 J250 True
Kant K530 K530 True
Knuth K530 K530 True
Lee L000 L000 True
Lukasiewicz L222 L222 True
Lissajous L222 L222 True
Ladd L300 L300 True
Lloyd L300 L300 True
Moses M220 M220 True
O'Hara O600 O600 True
Pfister P236 P236 True
Rubin R150 R150 True
Robert R163 R163 True
Rupert R163 R163 True
Soundex S532 S532 True
Sownteks S532 S532 True
Tymczak T522 T522 True
VanDeusen V532 V532 True
Washington W252 W252 True
Wheaton W350 W350 True
</pre>
 
=={{header|Prolog}}==
Note: Rather than produce a terse and incomprehensible example, this demonstrates how simply a set of logical rules can be translated into Prolog.
<langsyntaxhighlight Prologlang="prolog">%____________________________________________________________________
% Implements the American soundex algorithm
% as described at https://en.wikipedia.org/wiki/Soundex
Line 3,264 ⟶ 4,173:
test :- test('Tymczak', 't522'), !, fail.
test :- test('Pfister', 'p236'), !, fail.
test. % Succeeds only if all the tests succeed</langsyntaxhighlight>
 
=={{header|PureBasic}}==
<langsyntaxhighlight PureBasiclang="purebasic">Procedure.s getCode(c.s)
Protected getCode.s = ""
Line 3,286 ⟶ 4,195:
word = UCase(word)
code = Mid(word,1,1)
previous = ""getCode(Left(word, 1))
For i = 2 To (Len(word) + 1)
current = getCode(Mid(word, i, 1))
Line 3,307 ⟶ 4,216:
 
PrintN (soundex("Lukasiewicz"))
PrintN("Press any key to exit"): Repeat: Until Inkey() <> ""</langsyntaxhighlight>
 
=={{header|Python}}==
<langsyntaxhighlight lang="python">from itertools import groupby
 
def soundex(word):
Line 3,320 ⟶ 4,229:
sdx3 = sdx2[0:4].ljust(4,'0')
return sdx3
</syntaxhighlight>
</lang>
{{out}}
<langsyntaxhighlight Pythonlang="python">>>>print soundex("soundex")
S532
>>>print soundex("example")
Line 3,329 ⟶ 4,238:
C532
>>>print soundex("ekzampul")
E251</langsyntaxhighlight>
 
=={{header|Racket}}==
The [http://rosettacode.org/wiki/Soundex#Scheme Scheme solution] runs as is in Racket.
 
=={{header|Raku}}==
(formerly Perl 6)
US census algorithm, so "Ashcraft" and "Burroughs" adjusted to match.
We fake up a first consonant in some cases to make up for the fact that we always trim the first numeric code (so that the 'l' of 'Lloyd' is properly deleted).
<syntaxhighlight lang="raku" line>sub soundex ($name --> Str) {
my $first = substr($name,0,1).uc;
gather {
take $first;
my $fakefirst = '';
$fakefirst = "de " if $first ~~ /^ <[AEIOUWH]> /;
"$fakefirst$name".lc.trans('wh' => '') ~~ /
^
[
[
| <[ bfpv ]>+ { take 1 }
| <[ cgjkqsxz ]>+ { take 2 }
| <[ dt ]>+ { take 3 }
| <[ l ]>+ { take 4 }
| <[ mn ]>+ { take 5 }
| <[ r ]>+ { take 6 }
]
|| .
]+
$ { take 0,0,0 }
/;
}.flat.[0,2,3,4].join;
}
 
for < Soundex S532
Example E251
Sownteks S532
Ekzampul E251
Euler E460
Gauss G200
Hilbert H416
Knuth K530
Lloyd L300
Lukasiewicz L222
Ellery E460
Ghosh G200
Heilbronn H416
Kant K530
Ladd L300
Lissajous L222
Wheaton W350
Ashcraft A261
Burroughs B620
Burrows B620
O'Hara O600 >
-> $n, $s {
my $s2 = soundex($n);
say $n.fmt("%16s "), $s, $s eq $s2 ?? " OK" !! " NOT OK $s2";
}</syntaxhighlight>
{{out}}
<pre> Soundex S532 OK
Example E251 OK
Sownteks S532 OK
Ekzampul E251 OK
Euler E460 OK
Gauss G200 OK
Hilbert H416 OK
Knuth K530 OK
Lloyd L300 OK
Lukasiewicz L222 OK
Ellery E460 OK
Ghosh G200 OK
Heilbronn H416 OK
Kant K530 OK
Ladd L300 OK
Lissajous L222 OK
Wheaton W350 OK
Ashcraft A261 OK
Burroughs B620 OK
Burrows B620 OK
O'Hara O600 OK</pre>
 
=={{header|REXX}}==
Line 3,343 ⟶ 4,328:
:* &nbsp; letters of the ASCII-extended character set are ignored.
:* &nbsp; ASCII-extended characters (ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜíóúñÑ) could be added to the program easily.
<langsyntaxhighlight lang="rexx">/*REXX program demonstrates Soundex codes from some words or from the command line.*/
_=; @.= /*set a couple of vars to "null".*/
parse arg @.0 . /*allow input from command line. */
Line 3,441 ⟶ 4,426:
end /*j*/
 
return left(value,4,0) /*padded value with zeroes. */</langsyntaxhighlight>
'''output''' &nbsp; when using the default (internal) inputs:
<pre style="height:33ex">
Line 3,513 ⟶ 4,498:
[ok] W452 is the Soundex for Williams
[ok] W422 is the Soundex for Woolcock
</pre>
 
=={{header|Ring}}==
<syntaxhighlight lang="ring">
# Project: Soundex
 
name = ["Ashcraf", "Ashcroft", "Gauss", "Ghosh", "Hilbert", "Heilbronn", "Lee", "Lloyd",
"Moses", "Pfister", "Robert", "Rupert", "Rubin","Tymczak", "Soundex", "Example"]
for i = 1 to 16
sp = 10 - len(name[i])
see '"' + name[i] + '"' + copy(" ", sp) + " " + soundex(name[i]) + nl
next
func soundex(name2)
name2 = upper(name2)
n = "01230129022455012623019202"
s = left(name2,1)
p = number(substr(n, ascii(s) - 64, 1))
for i = 2 to len(name2)
n2 = number(substr(n, ascii(name2[i]) - 64, 1))
if n2 > 0 and n2 != 9 and n2 != p s = s + string(n2) ok
if n2 != 9 p = n2 ok
next
return left(s + "000", 4)
</syntaxhighlight>
Output:
<pre>
"Ashcraf" A261
"Ashcroft" A261
"Gauss" G200
"Ghosh" G200
"Hilbert" H416
"Heilbronn" H416
"Lee" L000
"Lloyd" L300
"Moses" M220
"Pfister" P236
"Robert" R163
"Rupert" R163
"Rubin" R150
"Tymczak" T522
"Soundex" S532
"Example" E251
</pre>
 
=={{header|RPL}}==
≪ "a123e12Xi22455o12623u1X2X2" "123456" → name table codes
≪ name 1 1 SUB ""
1 name SIZE '''FOR''' j
name j DUP SUB NUM
R→B #DFh AND B→R
'''IF''' 65 OVER ≤ OVER 90 ≤ AND '''THEN'''
table SWAP 64 - DUP SUB
'''IF''' DUP "X" ≠ '''THEN''' + '''ELSE''' DROP '''END'''
'''ELSE''' DROP '''END'''
'''NEXT'''
'name' STO
2 name SIZE '''FOR''' j
name j DUP SUB
'''IF''' codes OVER POS OVER name j 1 - DUP SUB ≠ AND '''THEN''' + '''ELSE''' DROP '''END'''
'''NEXT'''
"000" + 1 4 SUB
≫ ≫ '<span style="color:blue">SOUNDX</span>' STO
 
French Soundex code can be generated by modifying the table to "a123e97Xi72455o12683u9X8y8" and the codes to "123456789"
≪ { "Ashcraft" "Ashcroft" "Gauss" "Ghosh" "Ghosn" "Hilbert" "Heilbronn" "Lee" "Lloyd" "Moses" "Pfister" "Robert" "Rupert" "Rubin" "Tymczak" "Soundex" "Example" } { }
1 3 PICK SIZE '''FOR''' j
OVER j GET <span style="color:blue">SOUNDX</span> + '''NEXT'''
SWAP DROP
≫ '<span style="color:blue">TESTS</span>' STO
{{out}}
<pre>
1: { { "A261" "A261" "G200" "G200" "G250" "H416" "H416" "L000" "L300" "M220" "P236" "R163" "R163" "R150" "T522" "S532" "E251" } }
</pre>
 
=={{header|Ruby}}==
Courtesy http://snippets.dzone.com/posts/show/4530
<langsyntaxhighlight lang="ruby">class String
 
SoundexChars = 'BFPVCGJKQSXZDTLMNR'
Line 3,544 ⟶ 4,602:
print word1.sounds_like(word2) ? "sounds" : "does not sound"
print " like '#{word2}'\n"
end</langsyntaxhighlight>
 
<pre>Soundex -> S532
Line 3,558 ⟶ 4,616:
=={{header|Run BASIC}}==
Courtesy http://dkokenge.com/rbp
<langsyntaxhighlight lang="runbasic">global val$
val$(1) = "BPFV"
val$(2) = "CSGJKQXZ"
Line 3,599 ⟶ 4,657:
next i
soundex$ = left$(a$,1) + left$(sdx$;"000",3)
end function</langsyntaxhighlight>
 
<pre>Robert soundex:R163
Line 3,607 ⟶ 4,665:
O'Mally soundex:O054
d jay soundex:D200</pre>
 
 
=={{header|Rust}}==
<syntaxhighlight lang="rust">use std::ops::Deref;
use regex::Regex;
use once_cell::sync::Lazy;
 
pub trait Soundex {
fn soundex(&self) -> String;
}
 
fn soundex_match(c: char) -> char {
return match c.to_ascii_lowercase() {
'b' | 'f' | 'p' | 'v' => Some('1'),
'c' | 'g' | 'j' | 'k' | 'q' | 's' | 'x' | 'z' => Some('2'),
'd' | 't' => Some('3'),
'l' => Some('4'),
'm' | 'n' => Some('5'),
'r' => Some('6'),
_ => Some('0'),
}.unwrap();
}
 
static RE: Lazy<Regex> = Lazy::new(|| {Regex::new("[^a-zA-Z]").unwrap()});
 
impl<T: Deref<Target = str>> Soundex for T {
fn soundex(&self) -> String {
let s = RE.replace(self, "").chars().collect::<Vec<char>>();
if s.len() == 0 {
return String::new();
}
let mut a = vec![s[0].to_ascii_uppercase(); 1].to_vec();
let mut last_sdex = soundex_match(a[0]);
let mut hadvowel = false;
for ch in &s[1..s.len()] {
let lc_ch = ch.to_ascii_lowercase();
let sdex = soundex_match(lc_ch);
if sdex != '0' {
if sdex != last_sdex || hadvowel {
a.push(sdex);
last_sdex = sdex;
hadvowel = false;
}
}
else if "aeiouy".contains(lc_ch) {
hadvowel = true;
}
}
if a.len() < 4 {
for _ in 0..(4 - a.len()) {
a.push('0');
}
}
return a[0..4].into_iter().collect();
}
}
 
fn main() {
assert_eq!("Ascroft".soundex(), "A261".to_string());
assert_eq!("Euler".soundex(), "E460".to_string());
assert_eq!("Gausss".soundex(), "G200".to_string());
assert_eq!("Hilbert".soundex(), "H416".to_string());
assert_eq!("Knuth".soundex(), "K530".to_string());
assert_eq!("Lloyd".soundex(), "L300".to_string());
assert_eq!("Lukasiewicz".soundex(), "L222".to_string());
assert_eq!("Ellery".soundex(), "E460".to_string());
assert_eq!("Ghosh".soundex(), "G200".to_string());
assert_eq!("Heilbronn".soundex(), "H416".to_string());
assert_eq!("Kant".soundex(), "K530".to_string());
assert_eq!("Ladd".soundex(), "L300".to_string());
assert_eq!("Lissajous".soundex(), "L222".to_string());
assert_eq!("Wheaton".soundex(), "W350".to_string());
assert_eq!("Ashcraft".soundex(), "A261".to_string());
assert_eq!("Burroughs".soundex(), "B620".to_string());
assert_eq!("Burrows".soundex(), "B620".to_string());
assert_eq!("O'Hara".soundex(), "O600".to_string());
}
</syntaxhighlight>
 
=={{header|Scala}}==
<langsyntaxhighlight lang="scala">def soundex(s:String)={
var code=s.head.toUpper.toString
var previous=getCode(code.head)
Line 3,633 ⟶ 4,769:
case _ => ""
}
}</langsyntaxhighlight>
 
<langsyntaxhighlight lang="scala">def main(args: Array[String]): Unit = {
val tests=Map(
"Soundex" -> "S532",
Line 3,661 ⟶ 4,797:
printf("Name: %-20s Code: %s Found: %s - %s\n", v._1, v._2, code, status)
}
}</langsyntaxhighlight>
 
=={{header|Scheme}}==
Line 3,669 ⟶ 4,805:
{{works with|any R6RS Scheme}}
 
<langsyntaxhighlight lang="scheme">;; The American Soundex System
;;
;; The soundex code consist of the first letter of the name followed
Line 3,738 ⟶ 4,874:
(soundex "Uhrbach")
(soundex "Moskowitz")
(soundex "Moskovitz")</langsyntaxhighlight>
 
{{out}}
Line 3,748 ⟶ 4,884:
> "M232"
> "M213"
</pre>
 
=={{header|SenseTalk}}==
<syntaxhighlight lang="sensetalk">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
</syntaxhighlight>
{{out}}
<pre>
Aschraft --> A261
Ashcroft --> A261
DiBenedetto --> ["D153","B533"]
Euler --> E460
Gauss --> G200
Ghosh --> G200
Gutierrez --> G362
Heilbronn --> H416
Hilbert --> H416
Honeyman --> H555
Jackson --> J250
Lee --> L000
LeGrand --> ["L265","G653"]
Lissajous --> L222
Lloyd --> L300
Moses --> M220
Pfister --> P236
Robert --> R163
Rupert --> R163
Rubin --> R150
Tymczak --> T522
VanDeusen --> ["V532","D250"]
Van de Graaff --> V532
Wheaton --> W350
</pre>
 
=={{header|Sidef}}==
<langsyntaxhighlight lang="ruby">func soundex(word, length=3) {
 
# Uppercase the argument passed in to normalize it
Line 3,771 ⟶ 4,977:
 
# Discard the first letter
word.ftlast!(-1)
 
# Remove A, E, H, I, O, U, W, and Y
Line 3,805 ⟶ 5,011:
}
 
testSoundex()</langsyntaxhighlight>
 
=={{header|Smalltalk}}==
 
{{works with|Smalltalk/X}}
using a builtin utility:
<syntaxhighlight lang="smalltalk">PhoneticStringUtilities soundexCodeOf: 'Soundex' "-> S532"</syntaxhighlight>
 
=={{header|SNOBOL4}}==
Line 3,815 ⟶ 5,027:
US National Archives (NARA) Soundex. Includes the "HW" rule omitted by Knuth and many other implementations.
 
<langsyntaxhighlight SNOBOL4lang="snobol4">* # Soundex coding
* # ABCDEFGHIJKLMNOPQRSTUVWXYZ
* # 01230127022455012623017202
Line 3,840 ⟶ 5,052:
loop test span(' ') break(' ') . name = :f(end)
output = soundex(name) ' ' name :(loop)
end</langsyntaxhighlight>
 
{{out}}
Line 3,852 ⟶ 5,064:
S460 Swhgler
O256 O'Connor</pre>
 
=={{header|Smalltalk}}==
 
{{works with|Smalltalk/X}}
using a builtin utility:
<lang smalltalk>PhoneticStringUtilities soundexCodeOf: 'Soundex' "-> S532"</lang>
 
=={{header|Standard ML}}==
This implementation uses datatypes to encode the different rules for handling duplicate digits
when different characters appear in the input:
<langsyntaxhighlight lang="sml">(* There are 3 kinds of letters:
* h and w are ignored completely (letters separated by h or w are considered
* adjacent, or merged together)
Line 3,927 ⟶ 5,133:
val () = test "Rubin" "R150"
val () = test "Tymczak" "T522"
val () = test "Pfister" "P236"</langsyntaxhighlight>
 
=={{header|Stata}}==
The soundex function is built-in. See [http://www.stata.com/help.cgi?soundex Stata help].
<langsyntaxhighlight lang="stata">. display soundex_nara("Ashcraft")
A261
 
. display soundex_nara("Tymczak")
T522</langsyntaxhighlight>
 
There is also a variant:
 
<syntaxhighlight lang="stata">. di soundex("Ashcraft")
A226</syntaxhighlight>
 
=={{header|Tcl}}==
{{tcllib|soundex}} contains an implementation of Knuth's soundex algorithm.
<langsyntaxhighlight lang="tcl">package require soundex
 
foreach string {"Soundex" "Example" "Sownteks" "Ekzampul"} {
set soundexCode [soundex::knuth $string]
puts "\"$string\" has code $soundexCode"
}</langsyntaxhighlight>
{{out}}
<pre>"Soundex" has code S532
Line 3,949 ⟶ 5,161:
"Sownteks" has code S532
"Ekzampul" has code E251</pre>
 
=={{header|TMG}}==
Unix TMG:
<syntaxhighlight lang="unixtmg">prog: ignore(spaces)
let: peek/done
[ch = ch>140 ? ch-40 : ch ]
( [ch<110?] ( [ch==101?] vow
| [ch==102?] r1
| [ch==103?] r2
| [ch==104?] r3
| [ch==105?] vow
| [ch==106?] r1
| [ch==107?] r2 )
| [ch<120?] ( [ch==110?] hw
| [ch==111?] vow
| [ch==112?] r2
| [ch==113?] r2
| [ch==114?] r4
| [ch==115?] r5
| [ch==116?] r5
| [ch==117?] vow )
| [ch<130?] ( [ch==120?] r1
| [ch==121?] r2
| [ch==122?] r6
| [ch==123?] r2
| [ch==124?] r3
| [ch==125?] vow
| [ch==126?] r1
| [ch==127?] hw )
| [ch<140?] ( [ch==130?] r2
| [ch==131?] vow
| [ch==132?] r2 ))
[n>0?]\let done;
 
vow: [ch=0] out;
r1: [ch=1] out;
r2: [ch=2] out;
r3: [ch=3] out;
r4: [ch=4] out;
r5: [ch=5] out;
r6: [ch=6] out;
hw: [ch=7] out;
out: [n==4?] [--n] parse(( scopy ))
| ( [(l1!=10) & ((ch==l1) | (ch==7) | (!ch)) ?]
| [(l1==7) & (ch==l2) ?]
| [--n] parse(num) );
num: octal(ch);
done: [l1=10] [ch=0]
loop: [n>0?] out loop | parse((={*}));
 
peek: adv ord/read;
ord: char(ch) fail;
read: smark any(!<<>>);
adv: [l2=l1] [l1=ch];
 
spaces: <<
>>;
 
n: 4;
ch: 0;
l1: 0;
l2: 0;</syntaxhighlight>
 
=={{header|TSE SAL}}==
<syntaxhighlight lang="tse sal">
<lang TSE SAL>
 
// library: string: get: soundex <description></description> <version>1.0.0.0.35</version> <version control></version control> (filenamemacro=getstgso.s) [kn, ri, sa, 15-10-2011 18:23:04]
Line 4,035 ⟶ 5,309:
END
 
</syntaxhighlight>
</lang>
 
 
=={{header|TUSCRIPT}}==
<langsyntaxhighlight lang="tuscript">
$$ MODE DATA
 
Line 4,070 ⟶ 5,343:
PRINT first,soundex,"=",n
ENDLOOP
</syntaxhighlight>
</lang>
{{out}}
<pre style='height:30ex;overflow:scroll'>
Line 4,104 ⟶ 5,377:
This implements the full Soundex described in [[http://www.archives.gov/research/census/soundex.html U.S. National Archives Website]]. Doubled letters are condensed before separating the first letter, so that for instance "Lloyd" is not treated as L followed by the coding of LOYD but as L followed by the coding of OYD. Consecutive consonants which map to the same code are not condensed to a single occurrence of the code if they are separated by vowels, but separating W and H do not thus intervene. Names with common prefixes are encoded in two ways.
 
<langsyntaxhighlight lang="txr">@(next :args)
@###
@# soundex-related filters
Line 4,177 ⟶ 5,450:
"@first_arg" and "@second_arg" match under soundex
@ (end)
@(end)</langsyntaxhighlight>
 
Run:
Line 4,197 ⟶ 5,470:
This solution is similar to some of the solutions in other languages. Its treatment of the algorithm is not as complete as the above solution.
 
<langsyntaxhighlight lang="txr">@(do (defun get-code (c)
(caseq c
((#\B #\F #\P #\V) #\1)
Line 4,223 ⟶ 5,496:
@arg -> @(soundex arg)
@ (end)
@(end)</langsyntaxhighlight>
 
Run:
Line 4,236 ⟶ 5,509:
The following functions require this associative array to be declared:
 
<langsyntaxhighlight lang="bash">declare -A value=(
[B]=1 [F]=1 [P]=1 [V]=1
[C]=2 [G]=2 [J]=2 [K]=2 [Q]=2 [S]=2 [X]=2 [Z]=2
Line 4,243 ⟶ 5,516:
[M]=5 [N]=5
[R]=6
)</langsyntaxhighlight>
 
The first algorithm described at https://en.wikipedia.org/wiki/Soundex#American_Soundex can be implemented like this:
 
<langsyntaxhighlight lang="bash">soundex() {
local -u word=${1//[^[:alpha:]]/.}
local letter=${word:0:1}
Line 4,282 ⟶ 5,555:
soundex+="000"
echo "${soundex:0:4}"
}</langsyntaxhighlight>
 
The "simplified" algorithm can be implemented like this:
 
<langsyntaxhighlight lang="bash">soundex2() {
local -u word=${1//[^[:alpha:]]/}
 
Line 4,329 ⟶ 5,602:
word+="000"
echo "${word:0:4}"
}</langsyntaxhighlight>
 
If we cheat a bit and allow calling out to `tr`, we can do:
 
<langsyntaxhighlight lang="bash">soundex3() {
local -u word=${1//[^[:alpha:]]/}
 
Line 4,353 ⟶ 5,626:
word+="000"
echo "${word:0:4}"
}</langsyntaxhighlight>
 
And some testing code:
 
<langsyntaxhighlight lang="bash">declare -A tests=(
[Soundex]=S532 [Example]=E251 [Sownteks]=S532 [Ekzampul]=E251
[Euler]=E460 [Gauss]=G200 [Hilbert]=H416 [Knuth]=K530
Line 4,384 ⟶ 5,657:
run_tests soundex
run_tests soundex2
run_tests soundex3</langsyntaxhighlight>
 
{{out}}
Line 4,396 ⟶ 5,669:
 
=={{header|VBScript}}==
<langsyntaxhighlight lang="vb">' Soundex
tt=array( _
"Ashcraft","Ashcroft","Gauss","Ghosh","Hilbert","Heilbronn","Lee","Lloyd", _
Line 4,439 ⟶ 5,712:
soundex = Mid(code & "000", 1, 4)
End Function 'soundex
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 4,458 ⟶ 5,731:
14 Soundex S532
15 Example E251
</pre>
 
=={{header|Wren}}==
{{trans|Kotlin}}
{{libheader|Wren-str}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="wren">import "./str" for Char
import "./fmt" for Fmt
 
var getCode = Fn.new { |c|
return "BFPV".contains(c) ? "1" :
"CGJKQSXZ".contains(c) ? "2" :
c == "D" || c == "T" ? "3" :
c == "L" ? "4" :
c == "M" || c == "N" ? "5" :
c == "R" ? "6" :
c == "H" || c == "W" ? "-" : ""
}
 
var soundex = Fn.new { |s|
if (s == "") return ""
var sb = Char.upper(s[0])
var prev = getCode.call(sb[0])
for (c in s.skip(1)) {
var curr = getCode.call(Char.upper(c))
if (curr != "" && curr != "-" && curr != prev) sb = sb + curr
if (curr != "-") prev = curr
}
return Fmt.ljust(4, sb, "0")[0..3]
}
 
var pairs = [
["Ashcraft", "A261"],
["Ashcroft", "A261"],
["Gauss", "G200"],
["Ghosh", "G200"],
["Hilbert", "H416"],
["Heilbronn", "H416"],
["Lee", "L000"],
["Lloyd", "L300"],
["Moses", "M220"],
["Pfister", "P236"],
["Robert", "R163"],
["Rupert", "R163"],
["Rubin", "R150"],
["Tymczak", "T522"],
["Soundex", "S532"],
["Example", "E251"]
]
 
for (pair in pairs) {
Fmt.print("$-9s -> $s -> $s", pair[0], pair[1], soundex.call(pair[0]) == pair[1])
}</syntaxhighlight>
 
{{out}}
<pre>
Ashcraft -> A261 -> true
Ashcroft -> A261 -> true
Gauss -> G200 -> true
Ghosh -> G200 -> true
Hilbert -> H416 -> true
Heilbronn -> H416 -> true
Lee -> L000 -> true
Lloyd -> L300 -> true
Moses -> M220 -> true
Pfister -> P236 -> true
Robert -> R163 -> true
Rupert -> R163 -> true
Rubin -> R150 -> true
Tymczak -> T522 -> true
Soundex -> S532 -> true
Example -> E251 -> true
</pre>
 
=={{header|XPL0}}==
<langsyntaxhighlight XPL0lang="xpl0">code CrLf=9, Text=12;
string 0; \use zero-terminated strings
 
Line 4,495 ⟶ 5,840:
Text(0, Name(I)); CrLf(0);
];
]</langsyntaxhighlight>
 
{{out}}
9,476

edits