2016-11-22 5 views
-1

Я пытаюсь сделать функцию перестановок IEnumerable (с повторением) на C#. У меня уже есть функция, которая использует Массивы;Перестановки с повторением с IEnumerable на основе целых чисел

public IEnumerable<IEnumerable<T>> GetPermsWithReps<T>(IEnumerable<T> items, int count) 
{   
    foreach (var item in items) 
    { 
     if (count == 1) 
     { 
      yield return new T[] { item }; 
     } 
     else 
     { 
      foreach (var result in GetPermsWithReps(items, count - 1)) 
      { 
       yield return new T[] { item }.Concat(result); 
      } 
     } 
    } 
} 

И он работает довольно хорошо ... но Теперь мне нужно сделать IEnumerable функцию, которая будет работать прямо на целых числах, а не массив. Так, например, если я это называю;

GetPermsInts(max_val = 1, digits_num = 2) 

Я должен получить выход;

00 
01 
10 
11 

Я пытался изменить эту функцию на многих способов добиться этого, но не везло до сих пор ... Пожалуйста может кто-нибудь мне помочь?

+1

Итак, вам нужно выяснить, как с учетом значения создать последовательность всех возможных значений между нулем и этим числом. Вы можете просмотреть существующие методы LINQ, чтобы увидеть, есть ли метод, который делает это (подсказка: есть метод, который делает именно это), или вы можете написать свой собственный; это не ужасно сложная функция для записи. – Servy

+0

@Servy На самом деле, я могу написать функцию, которая сбрасывает все возможные значения - НО проблема в том, что я не хочу их всех, я просто хочу, чтобы каждая запись была отдельно и остановлена, когда 3 из этих записей соответствуют некоторому условию - поэтому я использую IEnumerable (потому что я могу проверять запись после каждого цикла) и больше не хочу использовать массив в качестве базового параметра (потому что тогда мне придется сначала сбрасывать все возможные цифры в массив, что потеря времени и памяти). У Вас есть какие-либо идеи ? – LOLOLOLO

+0

Создание последовательности с '0' и' 1' в ней, когда вы собираетесь создать последовательность, содержащую все перестановки этой последовательности с самим собой, не дорого. Вы выполняете операцию с 'n!' Сложностью; создание входной последовательности размера 'n' никогда не будет значительным в сравнении. – Servy

ответ

0

Ну, вы можете сделать что-то подобное (предполагая, что вы хотите вернуть строки):

IEnumerable<string> EnumeratePermutations(int digits, int length) 
{ 
    var data = new char[length]; 
    for (int i = 0; i < data.Length; ++i) 
    { 
     data[i] = '0'; 
    } 

    while (true) 
    { 
     yield return new string(data); 

     char maxChar = (char)('0' + digits); 

     for (int index = length - 1; index >= 0; --index) 
     { 
      if (++data[index] == maxChar) 
      { 
       for (int i = index; i < data.Length; ++i) 
       { 
        data[i] = '0'; 
       } 

       if (index == 0) 
       { 
        yield break; 
       } 
      } 
      else 
      { 
       break; 
      } 
     } 
    } 
} 

Таким образом, вы можете получить любую перестановку данной length с использованием digits различных символов. Если вы хотите, чтобы база была больше 9, вы, вероятно, должны добавить некоторое сопоставление, чтобы использовать нужные символы.

Этот код будет генерировать только используемую перестановку в лексическом порядке.

+0

Кстати, с этим кодом я могу сделать 'EnumeratePermutations (222, 5) .Skip (35000000) .Выберите (5)' примерно через 1 секунду на моем компьютере. Таким образом, я повторяю около 35 миллионов значений в секунду, если я ничего не делаю с теми параметрами, которые были указаны в комментарии ниже вопроса. – Phil1970