Task: Soundex

C: #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>


static char code[128] = { 0 };
void add_code(const char *s, int c)
{
	while (*s) {
		code[(int)*s] = code[0x20 ^ (int)*s] = c;
		s++;
	}
}

void init()
{
	static const char *cls[] =
		{ "AEIOU", "", "BFPV", "CGJKQSXZ", "DT", "L", "MN", "R", 0};
	int i;
	for (i = 0; cls[i]; i++)
		add_code(cls[i], i - 1);
}


const char* soundex(const char *s)
{
	static char out[5];
	int c, prev, i;

	out[0] = out[4] = 0;
	if (!s || !*s) return out;

	out[0] = *s++;

	
	prev = code[(int)out[0]];
	for (i = 1; *s && i < 4; s++) {
		if ((c = code[(int)*s]) == prev) continue;

		if (c == -1) prev = 0;	
		else if (c > 0) {
			out[i++] = c + '0';
			prev = c;
		}
	}
	while (i < 4) out[i++] = '0';
	return out;
}

int main()
{
	int i;
	const char *sdx, *names[][2] = {
		{"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"},
		{"Burroughs",	"B620"},
		{"Burrows",	"B620"},
		{"O'Hara",	"O600"},
		{"Washington",	"W252"},
		{"Lee",		"L000"},
		{"Gutierrez",	"G362"},
		{"Pfister",	"P236"},
		{"Jackson",	"J250"},
		{"Tymczak",	"T522"},
		{"VanDeusen",	"V532"},
		{"Ashcraft",	"A261"},
		{0, 0}
	};

	init();

	puts("  Test name  Code  Got\n----------------------");
	for (i = 0; names[i][0]; i++) {
		sdx = soundex(names[i][0]);
		printf("%11s  %s  %s ", names[i][0], names[i][1], sdx);
		printf("%s\n", strcmp(sdx, names[i][1]) ? "not ok" : "ok");
	}

	return 0;
}











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;
procedure Soundex is
   type UStrings is array(Natural range <>) of Unbounded_String;
   function "+"(S:String) return Unbounded_String renames To_Unbounded_String;
   
   function toSoundex (instr : String) return String is
      str  : String := To_Upper(instr);
      output : String := "0000";
      spos : Integer := str'First+1;  opos : Positive := 2;
      map  : array(0..255) of Character := (others => ' ');
      last : Integer := str'First;
   begin
      map(65..90) := " 123 12- 22455 12623 1-2 2";
      for i in str'Range loop str(i) := map(Character'Pos(str(i))); end loop;
      output(1) := str(str'First);
      while (opos <= 4 and spos <= str'Last) loop
         if str(spos) /= '-' and str(spos) /= ' ' then
            if (str(spos-1) = '-' and last = spos-2) and then
              (str(spos) = str(spos-2)) then null;
            elsif (str(spos) = output(opos-1) and last = spos-1) then last := spos;
            else output(opos) := str(spos);  opos := opos + 1; last := spos;
            end if;
         end if;
         spos := spos + 1;
      end loop;
      output(1) := To_Upper(instr(instr'First));
      return output;
   end toSoundex;
   
   cases : constant UStrings := (+"Soundex", +"Example", +"Sownteks",
      +"Ekzampul", +"Euler", +"Gauss", +"Hilbert", +"Knuth", +"Lloyd",
      +"Lukasiewicz", +"Ellery", +"Ghosh", +"Heilbronn", +"Kant",
      +"Ladd", +"Lissajous", +"Wheaton", +"Burroughs", +"Burrows",
      +"O'Hara", +"Washington", +"Lee", +"Gutierrez", +"Pfister",
      +"Jackson", +"Tymczak", +"VanDeusen", +"Ashcraft");
begin
   for i in cases'Range loop
      Put_Line(To_String(cases(i))&" = "&toSoundex(To_String(cases(i))));
   end loop;
end Soundex;