Task: NYSIIS

C: #include <iostream>   
#include <iomanip>    
#include <string>

std::string NYSIIS( std::string const& str )
{
    std::string s, out;
    s.reserve( str.length() );
    for( auto const c : str )
    {
        if( c >= 'a' && c <= 'z' )
            s += c - ('a' - 'A');
        else if( c >= 'A' && c <= 'Z' )
            s += c;
    }

    auto replace = []( char const * const from, char const* to, char* const dst ) -> bool
    {
        auto const n = strlen( from );
        if( strncmp( from, dst, n ) == 0 )
        {
            strncpy( dst, to, n );
            return true;
        }
        return false;
    };

    auto multiReplace = []( char const* const* from, char const* to, char* const dst ) -> bool
    {
        auto const n = strlen( *from );
        for( ; *from; ++from )
            if( strncmp( *from, dst, n ) == 0 )
            {
                memcpy( dst, to, n );
                return true;
            }
        return false;
    };

    auto isVowel = []( char const c ) -> bool
    {
        return c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U';
    };

    size_t n = s.length();
    replace( "MAC", "MCC", &s[0] );
    replace( "KN", "NN", &s[0] );
    replace( "K", "C", &s[0] );
    char const* const prefix[] = { "PH", "PF", 0 };
    multiReplace( prefix, "FF", &s[0] );
    replace( "SCH", "SSS", &s[0] );

    char const* const suffix1[] = { "EE", "IE", 0 };
    char const* const suffix2[] = { "DT", "RT", "RD", "NT", "ND", 0 };
    if( multiReplace( suffix1, "Y", &s[n - 2] ) || multiReplace( suffix2, "D", &s[n - 2] ))
    {
        s.pop_back();
        --n;
    }

    out += s[0];

    char* vowels[] = { "A", "E", "I", "O", "U", 0 };
    for( unsigned i = 1; i < n; ++i )
    {
        char* const c = &s[i];
        if( !replace( "EV", "AV", c ) )
            multiReplace( vowels, "A", c );
        replace( "Q", "G", c );
        replace( "Z", "S", c );
        replace( "M", "N", c );
        if( !replace( "KN", "NN", c ))
            replace( "K", "C", c );
        replace( "SCH", "SSS", c );
        replace( "PH", "FF", c );
        if( *c == 'H' && (!isVowel( s[i - 1] ) || i + 1 >= n || !isVowel( s[i + 1] )))
            *c = s[i - 1];
        if( *c == 'W' && isVowel( s[i - 1] ))
            *c = 'A';
        if( out.back() != *c )
            out += *c;
    }

    if( out.back() == 'S' || out.back() == 'A' )
        out.pop_back();
    n = out.length() - 2;
    if( out[n] == 'A' && out[n + 1] == 'Y' )
        out = out.substr( 0, n ) + "Y";

    return out;
}

int main()
{
    static char const * const names[][2] = {
    { "Bishop", "BASAP" },
    { "Carlson", "CARLSAN" },
    { "Carr", "CAR" },
    { "Chapman", "CAPNAN" },
    { "Franklin", "FRANCLAN" },
    { "Greene", "GRAN" },
    { "Harper", "HARPAR" },
    { "Jacobs", "JACAB" },
    { "Larson", "LARSAN" },
    { "Lawrence", "LARANC" },
    { "Lawson", "LASAN" },
    { "Louis, XVI", "LASXV" },
    { "Lynch", "LYNC" },
    { "Mackenzie", "MCANSY" },
    { "Matthews", "MATA" },
    { "McCormack", "MCARNAC" },
    { "McDaniel", "MCDANAL" },
    { "McDonald", "MCDANALD" },
    { "Mclaughlin", "MCLAGLAN" },
    { "Morrison", "MARASAN" },
    { "O'Banion", "OBANAN" },
    { "O'Brien", "OBRAN" },
    { "Richards", "RACARD" },
    { "Silva", "SALV" },
    { "Watkins", "WATCAN" },
    { "Wheeler", "WALAR" },
    { "Willis", "WALA" },
    { "brown, sr", "BRANSR" },
    { "browne, III", "BRAN" },
    { "browne, IV", "BRANAV" },
    { "knight", "NAGT" },
    { "mitchell", "MATCAL" },
    { "o'daniel", "ODANAL" } };

    for( auto const& name : names )
    {
        auto const code = NYSIIS( name[0] );
        std::cout << std::left << std::setw( 16 ) << name[0] << std::setw( 8 ) << code;
        if( code == std::string( name[1] ))
            std::cout << " ok";
        else
            std::cout << " ERROR: " << name[1] << " expected";
        std::cout << std::endl;
    }

    return 0;
}





Java: import static java.util.Arrays.*;
import static java.lang.System.out;

public class NYSIIS {

    final static String[][] first = {{"MAC", "MCC"}, {"KN", "N"}, {"K", "C"},
    {"PH", "FF"}, {"PF", "FF"}, {"SCH", "SSS"}};

    final static String[][] last = {{"EE", "Y"}, {"IE", "Y"}, {"DT", "D"},
    {"RT", "D"}, {"RD", "D"}, {"NT", "D"}, {"ND", "D"}};

    final static String Vowels = "AEIOU";

    public static void main(String[] args) {
        stream(args).parallel().map(n -> transcode(n)).forEach(out::println);
    }

    static String transcode(String s) {
        int len = s.length();
        StringBuilder sb = new StringBuilder(len);

        for (int i = 0; i < len; i++) {
            char c = s.charAt(i);
            if (c >= 'a' && c <= 'z')
                sb.append((char) (c - 32));
            else if (c >= 'A' && c <= 'Z')
                sb.append(c);
        }

        replace(sb, 0, first);
        replace(sb, sb.length() - 2, last);

        len = sb.length();
        sb.append(" ");
        for (int i = 1; i < len; i++) {
            char prev = sb.charAt(i - 1);
            char curr = sb.charAt(i);
            char next = sb.charAt(i + 1);

            if (curr == 'E' && next == 'V')
                sb.replace(i, i + 2, "AF");

            else if (isVowel(curr))
                sb.setCharAt(i, 'A');

            else if (curr == 'Q')
                sb.setCharAt(i, 'G');

            else if (curr == 'Z')
                sb.setCharAt(i, 'S');

            else if (curr == 'M')
                sb.setCharAt(i, 'N');

            else if (curr == 'K' && next == 'N')
                sb.setCharAt(i, 'N');

            else if (curr == 'K')
                sb.setCharAt(i, 'C');

            else if (sb.indexOf("SCH", i) == i)
                sb.replace(i, i + 3, "SSS");

            else if (curr == 'P' && next == 'H')
                sb.replace(i, i + 2, "FF");

            else if (curr == 'H' && (!isVowel(prev) || !isVowel(next)))
                sb.setCharAt(i, prev);

            else if (curr == 'W' && isVowel(prev))
                sb.setCharAt(i, prev);

            if (sb.charAt(i) == prev) {
                sb.deleteCharAt(i--);
                len--;
            }
        }
        sb.setLength(sb.length() - 1); 

        int lastPos = sb.length() - 1;
        if (lastPos > 1) {

            if (sb.lastIndexOf("AY") == lastPos - 1)
                sb.delete(lastPos - 1, lastPos + 1).append("Y");

            else if (sb.charAt(lastPos) == 'S')
                sb.setLength(lastPos);

            else if (sb.charAt(lastPos) == 'A')
                sb.setLength(lastPos);
        }

        if (sb.length() > 6)
            sb.insert(6, '[').append(']');

        return String.format("%s -> %s", s, sb);
    }

    private static void replace(StringBuilder sb, int start, String[][] maps) {
        if (start >= 0)
            for (String[] map : maps) {
                if (sb.indexOf(map[0]) == start) {
                    sb.replace(start, start + map[0].length(), map[1]);
                    break;
                }
            }
    }

    private static boolean isVowel(char c) {
        return Vowels.indexOf(c) != -1;
    }
}