2010-11-25 30 views
5

Quiero encontrar todos los números consecutivos en un int ordenado [8] de números casuales de 0 a 31. Los números consecutivos deben ser de una longitud mínima de 3 y un máximo de 5 números.Encontrar todos los números consecutivos en un int []

En el ejemplo, el último me da un problema muy real.

ejemplo:

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 

no quiero la solución pero sólo un ejemplo de cómo abordar la cuestión porque estoy tratando de usar generales y estoy realmente atascado!

Realmente gracias por la ayuda!

Cristiano

-Este es el código desde donde empecé (no la sopa de mi cocina)

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

¿Dónde está el código que solía resolver? – birryree

+0

if (r.Count == 5) // better (r.count> 5) { r = r.removefirst(); continuar; } –

+0

Comience con una hoja de papel, como sugiere Jon. A menudo es más fácil comenzar con un plato limpio. – Lucero

Respuesta

1

lo siento por la tarde actualización pero el tiempo es muy opresor ....

Esta es mi solución final con todos los límites necesarios (para mis necesidades) para serier. Gracias a todos

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

le sugiero que tome algunos ejemplos y escribirlas en un papel. Analice cuidadosamente lo que está haciendo intuitivamente cuando intente resolverlos a mano y conviértalo en código.

Usted probablemente querrá mantener un recuento de la cantidad de valores que ya ha encontrado en la secuencia, y lo que el valor anterior era ...

+0

+1 - Sin dar la respuesta, este es el camino a seguir. – TheCloudlessSky

+1

Buena descripción de la "solución" ... tal vez también le ayuda a Christian saber que cada número en la secuencia solo necesita ser visto una vez; no es necesario retroceder o eso es necesario. – Lucero

+0

En el momento de mi respuesta, he hecho lo que sugiere y desde su sitio aprendí muchas cosas sobre C#. ¡Muchas gracias! ¡De Verdad! –

1

pseudo código:

1-ordenar la matriz en orden ascendente 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

por supuesto, depende si su problema es siempre limitado a las restricciones que, quiero decir int [8] matriz, 0-31 y 3-5, pero si iSN' Creo que tu problema no pudo ser resuelto por un ingenuo algoritmo.

quiero decir, supongamos que tenemos esta matriz:

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

y su restricción de subconjunto, es decir "números consecutivos conjuntos deben ser de longitud mínima de 3 y un máximo de 5 números".

un algoritmo ingenuo que se inicia desde el primer elemento hasta el último y llena el mayor subconjunto consecutiva posible, producirán estos dos subconjuntos:

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

En esta solución 12 está en ninguna partición, pero, obviamente, hay otra solución factible (en realidad más de uno) que incluye todos los números, es decir, por ejemplo:

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

por lo tanto, se puede tienen varias posibilidades:

  1. La primera solución está bien, no es necesario para cubrir lo más posible una serie consecutiva encontrado
  2. La segunda solución está bien, tiene que cubrir lo más posible una encontrado conjunto consecutivo
  3. la segunda solución está bien, tiene que cubrir lo más posible una serie consecutiva encontrado, y posiblemente con el número más bajo posible de subconjunto

En el primer caso, se puede hacer como otros contestador señaló (¡oye, Jon Skeet te respondió! :PAG).
Por el contrario, en el segundo y tercer caso es mucho más complicado porque es un Knapsack type problem es decir, un problema completo de NP, (el tercer caso en particular me suena como Change-making problem).

de que es mi granito de arena, obviamente, repito, el problema Doe no existiría si usted tiene siempre el mismo tamaño de la matriz, el alcance y las limitaciones de subconjuntos ...

+0

tienen siempre las mismas restricciones de tamaño de matriz, rango y subconjunto ... y otro límite: 0 (obvio), 8,16,24 no puede finalizar el rango y 7,15,23,31 no puede iniciar el rango. .. –

+0

Así que incluso puedes codificar todo, de hecho puedes tener como máximo 28 conjuntos de 3 elementos consecutivos, 27 de 4 elementos consecutivos y 26 de 5 elementos consecutivos :-P (y esto sin incluir tus últimos límites) – digEmAll

+0

sí, lo sé ... .pero me gustaría generalizar .... y sé que está por encima de mi capacidad (@ en el momento en que espero ;-P) –

0

1) Dividir matriz dada en la lista de números consecutivos (que dicho conjunto ya está pedido)

2) Cuando se añade a la lista si la lista ya tiene 5 elementos se suman a la nueva lista

3) Listas de Conde> 2 son los resultados

Cuestiones relacionadas