2010-11-25 25 views
5

Sırayla numaralar 0 ile 31 arasında sıralı sayıların düzenli bir sayı [8] içinde bulmak istiyorum. Ardışık sayılar en az 3 ve en fazla 3 olmalıdır. 5 sayı.Bir arka planda tüm ardışık sayıları bulun Bir int []

Örnekte, sonuncusu bana çok gerçek bir problem veriyor.

örn:

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 

Ben çözüm ama generalleri kullanarak çalışıyorum çünkü soruyu yaklaşım nasıl sadece bir örnektir istemiyorum ve ben gerçekten sıkıştım!

Yardımlarınız için teşekkürler!

Hıristiyan

-bu sana bazı örnekler alıp kağıda yazmak önermek (benim mutfaktan değil çorbası) başladığım yerden kod

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

Bunu çözmek için kullandığınız kod nerede? – birryree

+0

(r.Count == 5) // daha iyisi (r.count> 5) { r = r.removefirst(); devamı; } –

+0

Jon'un önerdiği gibi bir kağıt parçasıyla başlayın. Temiz bir plaka ile başlamak genellikle daha kolaydır. – Lucero

cevap

1

üzgün eklemek varsa listeye eklerken güncelleme ama zaman çok zalim ....

Bu benim son çözüm için serier için tüm gerekli sınırlarla (ihtiyaçlarım). Teşekkür ederiz tüm

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

olduğunu. El ile çözmeyi denediğinizde dikkatle yaptığınız şeyi dikkatli bir şekilde çalışın ve bunu koda dönüştürün.

Muhtemelen zaten sırayla buldum ve önceki değeri ne ...

+0

+1 - Cevabı vermeden, işte bu yoldur. – TheCloudlessSky

+1

"Çözüm" in güzel bir açıklaması ... belki de aynı zamanda Hıristiyanın sıradaki her bir sayının sadece bir kez bakılması gerektiğini bilmesine yardımcı olur; hiçbir geri izleme ya da buna gerek yok. – Lucero

+0

Cevabımın zamanında önerdiğin gibi yaptım ve sitenden C# üzerinde birçok şey öğrendim! Çok teşekkürler! Gerçekten mi! –

1

sahte kod kaç değer sayımını tutmak istersiniz:

1-sıralamak Sorununuz her zaman sınırlı olup olmadığını küçükten büyüğe dizi tabii 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

o bağlı olduğu kısıtlamalar, ben int demek [8] dizisi, 0-31 ve 3-5, ama 'o değil mi eğer t, senin problemin bir naif algoritma ile çözülemez sanırım. Yani

, Şimdi bu dizi var diyelim: yani

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

ve alt kısıtlama, "ardışık sayılar setleri minimum 3 uzunluğuna ve 5 numaralarının maksimum olmalıdır".

son ilk elemana başlar ve mümkün olan en büyük ardışık alt kümesini dolduran Saf bir algoritma verecektir bu iki alt kümeleri:

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

12 hayır bölümleri bulunan bu çözümde

, ama belli tüm numaraları içeren başka uygun bir çözüm (aslında birden fazla) olduğu, yani örneğin geçerli:

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

bu nedenle, can düzenleme imkanı bulunuyor:

  1. 1 çözüm Tamam, sen 2 çözüm Tamam
  2. , bir tespit mümkün olduğunca karşılamak için gereken olası bir Bulunan ardışık kümesi kadar kapak gerek yok ardışık seti
  3. 2 çözüm Tamam, mümkün bir bulundu ardışık kümesi kadar ve muhtemelen ilk durumda alt kümesi

arasında mümkün olan en düşük sayı ile karşılamak için gereken, diğer yanıtlayanın olarak yapabilirsiniz dikkat çekti (hey adam, Jon Skeet size cevap verdi! : P). Tersine, ikinci ve üçüncü durumda çok daha karmaşıktır, çünkü bir Knapsack type problem yani bir NP tam problemi, (özellikle üçüncü durumda bana Change-making problem gibi sesler gelir).

açıkçası, tekrar ediyorum, benim iki sent

, sorun ... hep aynı dizi boyut, aralık ve alt küme kısıtlamaları varsa mevcut doent

+0

her zaman aynı dizi boyutu, aralık ve alt küme kısıtlamalarına sahiptir ... ve diğer sınır: 0 (obviusly), 8,16,24 aralığı kapatamaz ve 7,15,23,31 aralığı başlatamaz. .. –

+0

Yani her şeyi kodlayabiliyorsunuz, aslında en fazla 28 ardışık 3 eleman, 27 ardışık 4 eleman ve 26 ardışık 5 elemandan oluşan bir sete sahip olabilirsiniz: -P (ve son sınırlarınızı dahil etmeden) – digEmAll

+0

evet biliyorum .. ama genellemek istiyorum .... ve biliyorum ki yeteneğim bitti (umduğum an; -P) –

0
ardışık sayılar Listesi'nde

1) Bölünmüş verilen dizi (Eğer dizi sipariş zaten söz)

2) liste zaten 5 element geç için yeni listeye Count

3) Listeleri> 2 için sonuçlar

İlgili konular