2008-10-23 4 views
3

Я хочу написать одометр-подобный метод на языке C#, но не только с использованием 0-9 для символов, но и для любого набора символов. Он будет действовать как приложение грубой силы, более или менее.Алгоритм: Одометр/сила брата

Если я прохожу в полукокса-массив символов из к J, и установите длину 5, я хочу результатов, как 00000, 00001, 00002 ... HJJJJ, IJJJJJ, JJJJJ.

Вот основа, пожалуйста, помогите мне расширить:

protected void Main() 
{ 
    char[] chars = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J' }; 

    BruteForce(chars, 5); 
} 

private void BruteForce(char[] chars, int length) 
{ 
    // for-loop (?) console-writing all possible combinations from 00000 to JJJJJ 
    // (when passed in length is 5) 
    // TODO: Implement code... 
} 
+1

пароль взломан, мы? – KristoferA 2008-10-23 07:14:35

+0

Ха-ха, я не думаю, что мой ноутбук является реалистичной машиной для передовых паролей :) Это больше для мозгового экскремента и веселья. – 2008-10-23 07:33:49

ответ

1

Это одно из решений, которое я нашел. Мне нравится компактность и разделение его:

private static char[] characters = 
    new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J' }; 

// length: The length of the string created by bruteforce 
public static void PerformBruteForce(int length) { 
    int charactersLength = characters.Length; 
    int[] odometer = new int[length]; 
    long size = (long)Math.Pow(charactersLength, length); 

    for (int i = 0; i < size; i++) { 
     WriteBruteForce(odometer, characters); 
     int position = 0; 
     do { 
      odometer[position] += 1; 
      odometer[position] %= charactersLength; 
     } while (odometer[position++] == 0 && position < length); 
    } 
} 

private static void WriteBruteForce(int[] odometer, char[] characters) { 
    // Print backwards 
    for (int i = odometer.Length - 1; i >= 0; i--) { 
     Console.Write(characters[odometer[i]]); 
    } 
    Console.WriteLine(); 
} 
0

Google для перестановок.

Если же вы просто имеем дело с этим диапазоном «шестигранной», просто сделайте следующее:

for (int i = 0; i < (1 << 24); i++) 
    string s = i.ToString("X6"); 
7

Это не вполне дубликат "recursion instead of multi-loops", но это довольно близко. Я напишу решение, если это вам не поможет.

EDIT: Это нерекурсивное решение. Рекурсивный один немного сложнее вернуть IEnumerable<string> с, но возвращение итератора дает хороший интерфейс IMO :)

private static IEnumerable<string> GetAllMatches(char[] chars, int length) 
{ 
    int[] indexes = new int[length]; 
    char[] current = new char[length]; 
    for (int i=0; i < length; i++) 
    { 
     current[i] = chars[0]; 
    } 
    do 
     { 
      yield return new string(current); 
     } 
     while (Increment(indexes, current, chars)); 
} 

private static bool Increment(int[] indexes, char[] current, char[] chars) 
{ 
    int position = indexes.Length-1; 

    while (position >= 0) 
    { 
     indexes[position]++; 
     if (indexes[position] < chars.Length) 
     { 
      current[position] = chars[indexes[position]]; 
      return true; 
     } 
     indexes[position] = 0; 
     current[position] = chars[0]; 
     position--; 
    } 
    return false; 
} 
0

Ниже класс я использовал ранее для этой точной цели ... как подсказывает название , он имеет важное значение в разных Базах, основанных на количестве символов в предоставленном наборе символов. Надеюсь, это полезно ...

public class BaseNCounter 
{ 
    public char[] CharSet { get; set; } 
    public int Power { get; set; } 

    public BaseNCounter() { } 

    public IEnumerable<string> Count() { 
     long max = (long)Math.Pow((double)this.CharSet.Length, (double)this.Power); 
     long[] counts = new long[this.Power]; 
     for(long i = 0; i < max; i++) 
      yield return IncrementArray(ref counts, i); 
    } 

    public string IncrementArray(ref long[] counts, long count) { 
     long temp = count; 
     for (int i = this.Power - 1; i >= 0 ; i--) { 
      long pow = (long)Math.Pow(this.CharSet.Length, i); 
      counts[i] = temp/pow; 
      temp = temp % pow; 
     } 

     StringBuilder sb = new StringBuilder(); 
     foreach (int c in counts) sb.Insert(0, this.CharSet[c]); 
     return sb.ToString(); 
    } 
} 

Вот несколько сценариев использования в консольном приложении.

class Program 
{ 
    static void Main(string[] args) 
    { 
     BaseNCounter c = new BaseNCounter() { 
      CharSet = new char [] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }, 
      Power = 2}; 

     foreach(string cc in c.Count()) 
      Console.Write("{0} ,", cc); 
     Console.WriteLine(""); 

     BaseNCounter c2 = new BaseNCounter() 
     { 
      CharSet = new char[] { 'x', 'q', 'r', '9'}, 
      Power = 3 
     }; 
     foreach (string cc in c2.Count()) 
      Console.Write("{0} ,", cc); 
     Console.Read(); 
    } 
} 
0

Я только что опубликовал переписывают я сделал на старом (но большой) перебором рутина я сделал еще в 90-е годы, он доступен из моего Gist и будет делать именно то, что вы просите:

https://gist.github.com/johanssonrobotics/11249060

Успехов!

Смежные вопросы