Task: NYSIIS





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;
    }
}



Python: import re

_vowels = 'AEIOU'

def replace_at(text, position, fromlist, tolist):
    for f, t in zip(fromlist, tolist):
        if text[position:].startswith(f):
            return ''.join([text[:position],
                            t,
                            text[position+len(f):]])
    return text

def replace_end(text, fromlist, tolist):
    for f, t in zip(fromlist, tolist):
        if text.endswith(f):
            return text[:-len(f)] + t
    return text

def nysiis(name):
    name = re.sub(r'\W', '', name).upper()
    name = replace_at(name, 0, ['MAC', 'KN', 'K', 'PH', 'PF', 'SCH'],
                               ['MCC', 'N',  'C', 'FF', 'FF', 'SSS'])
    name = replace_end(name, ['EE', 'IE', 'DT', 'RT', 'RD', 'NT', 'ND'],
                             ['Y',  'Y',  'D',  'D',  'D',  'D',  'D'])
    key, key1 = name[0], ''
    i = 1
    while i < len(name):
        
        n_1, n = name[i-1], name[i]
        n1_ = name[i+1] if i+1 < len(name) else ''
        name = replace_at(name, i, ['EV'] + list(_vowels), ['AF'] + ['A']*5)
        name = replace_at(name, i, 'QZM', 'GSN')
        name = replace_at(name, i, ['KN', 'K'], ['N', 'C'])
        name = replace_at(name, i, ['SCH', 'PH'], ['SSS', 'FF'])
        if n == 'H' and (n_1 not in _vowels or n1_ not in _vowels):
            name = ''.join([name[:i], n_1, name[i+1:]])
        if n == 'W' and n_1 in _vowels:
            name = ''.join([name[:i], 'A', name[i+1:]])
        if key and key[-1] != name[i]:
            key += name[i]
        i += 1
    key = replace_end(key, ['S', 'AY', 'A'], ['', 'Y', ''])
    return key1 + key

if __name__ == '__main__':
    names = ['Bishop', 'Carlson', 'Carr', 'Chapman', 'Franklin',
             'Greene', 'Harper', 'Jacobs', 'Larson', 'Lawrence',
             'Lawson', 'Louis, XVI', 'Lynch', 'Mackenzie', 'Matthews',
             'McCormack', 'McDaniel', 'McDonald', 'Mclaughlin', 'Morrison',
             "O'Banion", "O'Brien", 'Richards', 'Silva', 'Watkins',
             'Wheeler', 'Willis', 'brown, sr', 'browne, III', 'browne, IV',
             'knight', 'mitchell', "o'daniel"]
    for name in names:
        print('%15s: %s' % (name, nysiis(name)))