j'ai des difficultés à trouver un algorithme pour le puzzle suivant Une chaîne est appelée laid si elle a 3 voyelles d'affilée ou 5 consonnes dans une rangée ou les deux. Une chaîne s'appelle bien si ce n'est pas laid. Vous recevez une chaîne S, composée de lettres majuscules ('A' - 'Z') et de points d'interrogation ('?'). Pouvez-vous trouver un algorithme qui indique si la chaîne peut être rendue agréable en substituant les points d'interrogation avec des alphabets? p>
Exemple - P>
"EE? FFFF" - ne peut pas être fait bien. L'insertion d'une consonne ou d'une voyelle le ferait laid. P> Li>
"h ?? lowor ??" - Peut être fait bien. p> li> ol>
P.S - Pas de devoirs, mais une partie d'un puzzle de programmation sur Internet. p>
8 Réponses :
Avez-vous essayé d'itération à travers tout l'alphabet et essayez chaque combinaison de voir si c'est «laid» ou non? P>
Essayez de remplacer chaque point d'interrogation avec une lettre, vérifiez la validité, c'est la manière la plus simple, la moins optimale. Par exemple: p>
EEF? D ?? P>
Je commencerais à remplir dans le? Avec ces combinaisons: p>
aaa Aab Aac AAD P>
etc. p>
Edit: Non, vous n'avez pas à itérer sur tout l'alphabet, juste A et B suffisent. Ou vraiment, n'importe quelle voyelle et toute consonne. P>
Ouais, ça marcherait. Mais y a-t-il quelque chose de mieux que la force brute?
Vous n'avez pas besoin de faire cela, tout ce que vous avez à faire est de choisir un de chacun, à tout le moins. Mais je pense que certains modèles de base peuvent facilement détecter les problèmes de toute façon, sans avoir besoin de force brute / boucle.
Itération de l'alphabet semble un peu inutile. Il n'y a que deux types de lettres impliquées ici: voyelle et consonne. La technique de la force brute serait de représenter la chaîne de sa forme la plus simple (choisir un symbole pour la voyelle et une pour la consonne), puis itérer les combinaisons de voyelles et de la consonne pour chaque point d'interrogation et testez chaque résultat.
Itération à travers l'alphabet entier est extrêmement inutile, mais hélas, je ne faisais que donner un indice.
Itération à travers tout l'alphabet semble inutile puisque vous ne vous inquiétez que des consonnes et des voyelles. Ce problème simplifie si on peut créer une chaîne binaire qui n'a pas plus de deux 1s consécutifs ou 4 consécutifs 0s. (c.-à-d.: prenez «consonne» pour égaler '0' et «voyelle» à égaler '1')
Voici la clé: la transformabilité de laid à Nice est fondée sur une certaine longueur de consonnes ou de voyelles. Donc, si transformer un bloc à Nice serait nécessairement prédire la laideur d'un autre bloc, on ne peut pas être fait. P>
La mise en œuvre est laissée comme un exercice pour la personne trop paresseuse pour faire leurs propres devoirs. : -) p>
Ce que vous pouvez faire est de se déplacer sur chaque point d'interrogation et testez toute combinaison possible de l'insertion d'une voyelle ou d'un point d'interrogation. P>
Par exemple (v => voyelle, c => consonne) p>
Essentiellement, décomposer la chaîne d'origine dans un motif, puis assortir le modèle avec des caractères génériques pour remplir le résultat. Bien sûr, si plus d'un personnage peut prendre la place, vous devez faire correspondre le motif à distance de levenstein, en ignorant les suppressions.
Il y a un modèle de regex qui correspondra à la laide: maintenant, si un dans chacun de ces cas, il n'y a pas de solution. Maintenant, s'il y a deux marques d'interrogation, l'une après l'autre, le problème se produit si les séquences sont les suivantes: P> ? code> se produit à l'intérieur d'une séquence de voyelles, vous pouvez le transformer en un consonne. Si cela se produit à l'intérieur d'une séquence de consonnes, vous pouvez la transformer en voyelle. Le problème se produit si le point d'interrogation apparaît sur une limite: p>
[aeiouAEIOU]{2}\?\?[aeiouAEIOU]{2}
[a-zA-Z&&[^aeiouAEIOU]]{4}\?\?[a-zA-Z&&[^aeiouAEIOU]]{4}
Je n'ai pas pensé que PCRES vous permet de nier des cours de personnage ... Je vais vérifier cela.
Java accepte et Perl a quelque chose d'équivalent, bien que je ne me souvienne pas si c'est la même syntaxe.
Une solution dans HASKELLL:
import System (getArgs) nicePart :: Int -> Int -> String -> Bool nicePart 3 _ _ = False nicePart _ 5 _ = False nicePart _ _ "" = True nicePart v c ('?':as) = nicePart (v+1) 0 as || nicePart 0 (c+1) as nicePart v c (a:as) | a `elem` "AEIOU" = nicePart (v+1) 0 as | otherwise = nicePart 0 (c+1) as nice :: String -> Bool nice as = nicePart 0 0 as main = getArgs >>= print . nice . unwords
Notez que les seules chaînes qui pourraient potentiellement être laides sont celles qui sont déjà laides en vertu des lettres données ou celles qui ne contiennent que des marques d'interrogation singleton. Voici le croquis de la preuve: p>
Alors, nous sommes partis avec deux cas simples. p>
Comme il a été souligné, il y a une approche brutale de force brute qui fonctionnera très inefficace. Le plaisir consiste à ajouter des gains d'efficacité qui éliminent la liste 2 ** n des possibilités. P>
Premièrement, faites une correspondance rapide "laid de regex" contre la chaîne d'origine, avant tout? substitution. Si vous obtenez un match, la chaîne ne peut évidemment pas être rendue belle. P> li>
Suivant look pour célibataire? opportunités, celles? qui sont flanqués des deux côtés par aucun autre? pour quatre positions. Voir si l'une d'entre elles doit être corrigée comme V ou C, ou si elles disqualifient entièrement la chaîne entièrement (comme dans l'exemple de OP). S'ils doivent être réparés V ou C, faites-le et continuez. P> li>
Les stratégies ultérieures sont plus impliquées: double? Les segments impliquent la vérification de gauche et non? Pour une exigence v / c basée sur leurs caractères flanques gauche / droite respectifs, etc. p> li> ol>
Mais ?? peut être trivialement transformé en VC ou en CV pour faire une ficelle agréable.
Voici une solution en C # qui semble fonctionner d'une poignée de cas de test que j'ai jeté dessus. [Certaines parties de l'expression de regex ont été empruntées à un répondeur précédent.]
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; }
Est-ce que chacun '?' doivent être substitués par la même lettre ou peuvent-ils être différents?
@Victor il ne peut pas être gentil à moins que tout le '?' ont été remplacés.