Вот решение в C #, которое, кажется, работает из нескольких тестовых случаев, которые я бросил на него. [Части выражения регулярного выражения были заимствованы у предыдущего автора.]
public static bool IsWordNiceable(string word, int maxVowels, int maxConsonants)
{
if (IsUgly(word, maxVowels, maxConsonants)) return false;
int i = 0;
while ((i = word.IndexOf('?', i)) != -1)
{
string newWord = word.Substring(0, i) + "a" + word.Substring(i+1);
bool vowelMakesNice = IsWordNiceable(newWord, maxVowels, maxConsonants);
newWord = word.Substring(0, i) + "b" + word.Substring(i + 1);
bool consonantMakesNice = IsWordNiceable(newWord, maxVowels, maxConsonants);
if (!(vowelMakesNice || consonantMakesNice)) return false;
i++;
}
return true;
}
private static bool IsUgly(string word, int maxVowels, int maxConsonants)
{
string consonants = "bcdfghjklmnpqrstvwxyz";
string vowels = "aeiou";
string uglyRegex = string.Format("([{0}]{{{1},{1}}})|([{2}]{{{3},{3}}})", vowels, maxVowels, consonants, maxConsonants);
Match match = Regex.Match(word.ToLower(), uglyRegex);
return match.Success;
}
Это сначала проверяет данное слово как есть, чтобы увидеть, уродливо ли оно (включая вопросительные знаки, если таковые имеются). Затем он перебирает слово, заменяя первое «?» с гласной и согласной, и называет себя, используя новое слово. Если замена гласного и согласного не удалась, то эта ветвь возвращает ложь (безобразно).