RosettaCodeData/Task/Soundex/D/soundex-2.d

62 lines
2.1 KiB
D
Raw Permalink Normal View History

2013-10-27 22:24:23 +00:00
import std.array, std.string, std.ascii, std.algorithm, std.range;
2013-04-11 01:07:29 -07:00
2013-10-27 22:24:23 +00:00
/**
2013-04-11 01:07:29 -07:00
Soundex is a phonetic algorithm for indexing names by
sound, as pronounced in English. See:
http://en.wikipedia.org/wiki/Soundex
*/
2013-10-27 22:24:23 +00:00
string soundex(in string name) pure /*nothrow*/
out(result) {
2013-04-11 01:07:29 -07:00
assert(result.length == 4);
2013-10-27 22:24:23 +00:00
assert(result[0] == '0' || result[0].isUpper);
2013-04-11 01:07:29 -07:00
2013-10-27 22:24:23 +00:00
if (name.empty)
2013-04-11 01:07:29 -07:00
assert(result == "0000");
2013-10-27 22:24:23 +00:00
immutable charCount = name.filter!isAlpha.walkLength;
2013-04-11 01:07:29 -07:00
assert((charCount == 0) == (result == "0000"));
} body {
2013-10-27 22:24:23 +00:00
// Adapted from public domain Python code by Gregory Jorgensen:
// http://code.activestate.com/recipes/52213/
// digits holds the soundex values for the alphabet.
2013-04-11 01:07:29 -07:00
static immutable digits = "01230120022455012623010202";
string firstChar, result;
2013-10-27 22:24:23 +00:00
// Translate alpha chars in name to soundex digits.
foreach (immutable dchar c; name.toUpper) { // Not nothrow.
if (c.isUpper) {
if (firstChar.empty)
firstChar ~= c; // Remember first letter.
2013-04-11 01:07:29 -07:00
immutable char d = digits[c - 'A'];
2013-10-27 22:24:23 +00:00
// Duplicate consecutive soundex digits are skipped.
if (!result.length || d != result.back)
2013-04-11 01:07:29 -07:00
result ~= d;
}
}
2013-10-27 22:24:23 +00:00
// Return 0000 if the name is empty.
2013-04-11 01:07:29 -07:00
if (!firstChar.length)
return "0000";
2013-10-27 22:24:23 +00:00
// Replace first digit with first alpha character.
assert(!result.empty);
2013-04-11 01:07:29 -07:00
result = firstChar ~ result[1 .. $];
2013-10-27 22:24:23 +00:00
// Remove all 0s from the soundex code.
result = result.replace("0", "");
2013-04-11 01:07:29 -07:00
2013-10-27 22:24:23 +00:00
// Return soundex code padded to 4 zeros.
2013-04-11 01:07:29 -07:00
return (result ~ "0000")[0 .. 4];
2013-10-27 22:24:23 +00:00
} unittest { // Tests of soundex().
2013-04-11 01:07:29 -07:00
auto tests = [["", "0000"], ["12346", "0000"],
["he", "H000"], ["soundex", "S532"],
["example", "E251"], ["ciondecks", "C532"],
["ekzampul", "E251"], ["résumé", "R250"],
["Robert", "R163"], ["Rupert", "R163"],
["Rubin", "R150"], ["Ashcraft", "A226"],
["Ashcroft", "A226"]];
2013-10-27 22:24:23 +00:00
foreach (const pair; tests)
assert(pair[0].soundex == pair[1]);
2013-04-11 01:07:29 -07:00
}
void main() {}