2010-01-04 2 views
1

J'essaie de résoudre le problème suivant, mais je ne trouve pas de solution élégante. Des idées? Merci. Entrée: chaîne de nombres de longueur variable, par exemple, chaîne str = "5557476374202110373551116201";Neat solution à un comptage dans une chaîne

Tâche - Vérifiez (de gauche à droite) que chaque numéro (en ignorant les répétitions) n'apparaît pas dans les 2 index suivants. En utilisant par exemple. Au-dessus, Premier nombre = 5. En ignorant les représentants, nous voyons que le dernier indice de 5 dans le groupe est 2. Donc nous vérifions les 2 index suivants, c'est-à-dire 3 et 4 ne devraient pas avoir 5. Si c'est le cas. Le but est de compter de telles erreurs dans la chaîne.

Dans les erreurs de chaîne ci-dessus sont à des index, 3,10 et 16.

+0

Attendez, vous venez de dire que les répétitions doivent être ignorées, alors comment est-il une erreur à l'index 3? – Amber

+3

hein? Est-ce que c'est une question d'un devoir? –

+0

De plus, si la position 3 comportait un 5, ne ferait-il pas partie du groupe? Cela n'a aucun sens. – danben

Répondre

5

en plus des autres solutions excellentes, vous pouvez utiliser une expression rationnelle simple:

foreach (Match m in Regexp.Matches(str, @"(\d)(?!\1)(?=\d\1)")) 
    Console.WriteLine("Error: " + m.Index); 

retours 3,10,16. cela correspondrait aux erreurs adjacentes en utilisant lookahead avec une référence arrière. gère les répétitions. .net devrait soutenir cela. sinon, vous pouvez utiliser une version non backreference:

(?<=0[^0])0|(?<=1[^1])1|(?<=2[^2])2|(?<=3[^3])3|(?<=4[^4])4|(?<=5[^5])5|(?<=6[^6])6|(?<=7[^7])7|(?<=8[^8])8|(?<=9[^9])9

+0

+1 Man-point pour la version non-backreference. Yikes. – ProfK

3

Un simple indexé pour la boucle avec un couple de regarder vers l'avenir si les contrôles travailleraient. Vous pouvez traiter une chaîne comme un char [] ou comme un IEnumerable - de toute façon, vous pouvez l'utiliser pour faire une boucle sur tous les caractères et effectuer une vérification anticipée pour voir si le ou les deux caractères suivants sont des doublons.

2

Désolé, pas un homme C#, mais voici une solution simple Ruby:

a="5557476374202110373551116201" 
0.upto(a.length) do |i| 
    puts "error at #{i}" if a[i]!=a[i+1] && a[i]==a[i+2] 
end 

Sortie:

error at 3 
error at 10 
error at 16 
1

Voici quelque chose que j'ai jeté ensemble en C# qui a travaillé avec l'exemple de la question. Je ne l'ai pas vérifié que bien, mais ...

public static IEnumerable<int> GetErrorIndices(string text) { 
    if (string.IsNullOrEmpty(text)) 
     yield break; 

    int i = 0; 
    while (i < text.Length) { 
     char c = text[i]; 

     // get the index of the next character that isn't a repetition 
     int nextIndex = i + 1; 
     while (nextIndex < text.Length && text[nextIndex] == c) 
      nextIndex++; 

     // if we've reached the end of the string, there's no error 
     if (nextIndex + 1 >= text.Length) 
      break; 

     // we actually only care about text[nextIndex + 1], 
     // NOT text[nextIndex] ... why? because text[nextIndex] 
     // CAN'T be a repetition (we already skipped to the first 
     // non-repetition) 
     if (text[nextIndex + 1] == c) 
      yield return i; 

     i = nextIndex; 
    } 

    yield break; 
} 
Questions connexes