2010-11-25 3 views
5

Я хочу найти все последовательные числа в упорядоченном int [8] случайных чисел от 0 до 31. Последовательные числа должны быть от минимальной длины 3 и макс. 5 номеров.Найти все последовательные числа в int []

В приведенном выше примере дайте мне очень настоящую проблему.

например:

int[] = new int[] { 3,7,14,16,23, 28, 29 ,30 } // no result (28,29 is length of 2 numbers) 

int[] = new int[] { 4,5,6,7,18, 19, 20 ,21 } // 4,5,6,7 (yes! length of 4!!) 

int[] = new int[] { 2.3.4.5.6.7.8.9 } // two results : 2,3,4 and 5,6,7,8,9 

Я не хочу Решение а просто пример того, как подойти к этому вопросу, потому что я пытаюсь с помощью генералов, и я действительно застрял!

Действительно спасибо за помощь!

Christian

-это есть код, где я начал (не суп из моей кухни)

public partial class Test2 : Form 
{ 
    public Test2() 
    { 
     InitializeComponent(); 
    } 

    private void Test2_Load(object sender, EventArgs e) 
    {   

     int[] numbers = new[] { 21, 4, 5, 22, 17, 6, 20, 23 }; 

     // int[] numbers = new[] { 1, 2, 3, 4, 5, 6, 7, 8 }; 

     foreach (Campo r in FindRanges(numbers, 3)) 
     { 
      listBox1.Items.Add(string.Join(", ", r.Select(x => x.ToString()).ToArray())); 
     } 



    } 


    struct Campo : IEnumerable<int> 
    { 
     readonly int _start; 
     readonly int _count; 

     public Campo(int start, int count) 
     { 
      _start = start; 
      _count = count; 
     } 

     public int Start 
     { 
      get { return _start; } 
     } 

     public int Count 
     { 
      get { return _count; } 
     } 

     public int End 
     { 
      get { return _start + _count - 1; } 

     } 

     public IEnumerator<int> GetEnumerator() 
     { 
      for (int i = 0; i < _count; ++i) 
      { 
       yield return _start + i; 
      } 
     } 

     IEnumerator IEnumerable.GetEnumerator() 
     { 

      return this.GetEnumerator(); 

     } 


     public static Campo operator +(Campo x, int y) 
     { 
      return new Campo(x.Start, x.Count + y); 
     } 

     public Campo removefirst() 
     { 
      return new Campo(this.Start + 3, this.Count); 
     } 

     public Campo removelast() 
     { 
      return new Campo(this.Start, this.Count - 1); 
     } 
    } 

    static IEnumerable<Campo> FindRanges(IEnumerable<int> source, int minCount) 
    { 


     var ordered = source.OrderBy(x => x); 

     Campo r = default(Campo); 

     foreach (int value in ordered) 
     { 

      if (r.Count == 0) 
      { 
       r = new Campo(value, 1); 
       continue; 
      } 


      if (r.Count == 5) 
      { 
       r = r.removefirst(); 

       continue; 
      } 

      if (value == r.End) 
      { 
       continue; 
      } 


      if ((value == 0 || value == 8 || value == 16 || value == 24) && (r.Count > minCount)) 
      { 
       continue; 
      } 

      if ((value == 7 || value == 15 || value == 23 || value == 31) && (r.Count == 1)) 
      { 
       continue; 
      } 

      else if (value == r.End + 1) 
      { 
       r += 1; 
      } 
      else 
      { 

       if (r.Count >= minCount) 
       { 
        yield return r; 
       } 


       r = new Campo(value, 1); 
      } 
     } 


     if (r.Count >= minCount) 
     { 
      yield return r; 
     } 
    } 

}

+1

Где код, который вы использовали для решения этой проблемы? – birryree 2010-11-25 20:21:45

+0

if (r.Count == 5) // better (r.count> 5) { r = r.removefirst(); продолжить; } – 2010-11-25 21:04:45

+0

Начните с листа бумаги, как предлагает Джон. Легче начать чистую пластину. – Lucero 2010-11-25 21:05:32

ответ

1

извините за поздний обновление, но время очень угнетающее ....

Это мое окончательное решение со всеми необходимыми пределами (для моих нужд) для serier. Thank you all

static IEnumerable<IEnumerable<int>> Sequences(IEnumerable<int> input, bool ascen = false, int min = 3) 
    { 
     int ord = ascen == false ? -1 : 1; 

     input = ord == -1 ? input.OrderByDescending(x => x) : input.OrderBy(x => x); 

     var seq = new List<List<int>>(); 
     foreach (var i in input) 
     { 
      var existing = seq.FirstOrDefault(lst => lst.Last() + ord == i); 
      if ((existing == null) || (seq.Last().Count == 5) || i == 7 || i == 15 || i == 23) 

       seq.Add(new List<int> { i }); 
      else 
       existing.Add(i); 
     } 
     return min <= 1 ? seq : seq.Where(lst => lst.Count >= min); 
    } 
6

Я предлагаю вам несколько примеров и записать их на бумаге. Тщательно выработайте то, что вы интуитивно делаете, когда пытаетесь решить их вручную - и конвертируйте это в код.

Вы, вероятно, захотите сохранить счетчик, сколько значений вы уже нашли в последовательности, и то, что предыдущее значение было ...

1

псевдокод:

1-сортировать массив в порядке возрастания 2-

int count = 0 
for i = 0 to array.length - 2 
    if {array[i + 1] - array[i] = 1 then 
     count+=1 
    else count=0} 
    if { count >= 3 and count <= 5 then found} 
1

конечно, это зависит, если ваша проблема всегда ограничивается тем, что ограничения, я имею в виду ИНТ [8] массив, 0-31 и 3-5, но если он ISN» t, я думаю, ваша проблема не может быть решена с помощью наивного алгоритма.

Я имею в виду, скажем, у нас есть этот массив:

int[] = new int[] { 2,3,4,5,6,7,8,9,10,11,12 }; 

и ваше подмножество ограничения, т.е. «последовательные номера наборы должны быть от минимальной длины 3 и не более 5 номеров».

Наивный алгоритм, который начинается с первого элемента до последнего и заполняет максимально возможное последовательное подмножество, приведет к получению эти два подмножества:

[2,3,4,5,6] [7,8,9,10,11]

В этом растворе 12 находится в каких-либо перегородок, но, очевидно, есть другое допустимое решение (на самом деле больше, чем один), который включает в себя все цифры, то есть, например:

[2,3,4,5] [6,7,8,9] [10,11,12]

Таким образом, вы можете есть несколько возможностей:

  1. 1-решение в порядке, вам не нужно, чтобы покрыть как можно больше найденного последовательный набор
  2. 2-е решения в порядке, вам нужно, чтобы покрыть как можно больше найденной последовательный набор
  3. 2-е решения в порядке, вы должны охватывать как можно больше найденный последовательный набор, и, возможно, с наималейшим возможным числом подмножества

в первом случае, вы можете сделать, как другие отвечающую указал (эй человек, Джон Скит ответил вам! :П).
И наоборот, во 2-м и 3-м корпусах это намного сложнее, потому что это Knapsack type problem, т. Е. NP полная проблема, (третий случай, в частности, звучит для меня как Change-making problem).

Это мои два цента, очевидно, повторяю, проблема doen't существовать, если у вас есть всегда одни и те же размер массива, диапазон и подмножество ограничений ...

0

1) Разделить данный массив в список последовательных номеров (вы сказали, массив уже порядок)

2) При добавлении в список, если список уже 5 элементов добавить в новый список

3) Списки графа> 2 ваши результаты

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