2016-11-18 6 views
2

Я пытаюсь написать функцию, которая генерирует lucky numbers,Почему это не приводит к удачным номерам?

static IEnumerable<int> LuckyNumbers() 
{ 
    IEnumerable<int> luckyNumbers = Enumerable.Range(1, int.MaxValue); 
    int counter = 1; 
    while (true) 
    { 
    int number = luckyNumbers.ElementAt(counter++); 
    yield return number; 
    luckyNumbers = luckyNumbers.Where((_, index) => (index + 1) % number != 0); 
    } 
} 

, но это порождает:

2,5,7,11,13,17,21,... 

, которые не являются счастливыми числами.

Почему мой код не работает? Я пытаюсь:

  1. начала со всеми натуральными числами:

    IEnumerable<int> luckyNumbers = Enumerable.Range(1, int.MaxValue); 
    int counter = 1; 
    
  2. итерацию через них и вернуться на следующий счастливый номер:

    while (true) 
    { 
        int number = luckyNumbers.ElementAt(counter++); 
        yield return number; 
    
  3. демонтировать все n го числа из следующей последовательности:

    luckyNumbers = luckyNumbers.Where((_, index) => (index + 1) % number != 0); 
    

Я не понимаю, почему это не работает, как я предполагаю.

+2

Помните, что каждый раз, когда вы выполняете шаг 3, вы получаете новую последовательность. Теперь вы уверены, что хотите, чтобы элемент 'counter' из этой новой последовательности? Попробуйте просмотреть все это на листе бумаги ... –

+0

@JonSkeet Я уверен, я думал, что я должен каждый раз брать следующий элемент из предыдущего поколения. Но я могу попробовать это на бумаге. – theonlygusti

+2

Учитывая, что wikipedia имеет обработанный пример, я предлагаю вам следовать этому при отладке. Первая проблема. Я отмечаю, что вы начинаете со второго элемента, потому что у вас есть 'counter = 1', а не' counter = 0'. Это означает, что вы никогда не вернетесь 1, что означает счастливое число. –

ответ

0

Есть несколько причин, почему ваш код не работает:

  1. Коллекции в программировании равны нулю индексированные. Вот почему первое число, которое вы создаете, равно 2, потому что его номер с индексом 1. Вы должны скорее инициализировать counter до 0.
  2. Я думаю, что вы инициализировали счетчик 1, чтобы избежать отмены 1-го номера из последовательности (который эффективно уничтожит все числа и, следовательно, элемент в заданной позиции обречен на провал). Проблема заключается в определении счастливых чисел здесь: в то время как первое счастливое число - 1, первая итерация - нанести каждый второй номер. Поэтому вы должны принять Math.Min(number, 2).

Наконец, вы прибудете на следующее:

static IEnumerable<int> LuckyNumbers() 
    { 
     IEnumerable<int> luckyNumbers = Enumerable.Range(1, int.MaxValue); 
     int counter = 0; 
     while (true) 
     { 
      int number = luckyNumbers.ElementAt(counter++); 
      yield return number; 
      int moduloCheck = Math.Max(number, 2); 
      luckyNumbers = luckyNumbers.Where((_, index) => (index + 1) % moduloCheck != 0); 
     } 
    } 

С точки зрения производительности, хотя, я думаю, что решение ужасна для больших чисел, как вы будете повторно проверить первые цифры навсегда в ElementAt. Поскольку выражение where не является индексируемым, это всегда будет проверять каждое число для нескольких условий. Самое приятное, что вы можете просто использовать его как LuckyNumbers().Take(n), чтобы получить первые n счастливых чисел.

+0

«Я думаю, что вы инициализировали счетчик 1, чтобы избежать отмены 1-го номера из последовательности» - это правда. – theonlygusti