2010-01-24 56 views
12

Làm thế nào tôi chuyển đổi mã này để có n lồng cho vòng:C#: N Vòng lặp For

  int num = 4; 

      for (int i = 0; i <= num; i++) 
      { 
       for (int j = 0; j + i <= num; j++) 
       { 
        for (int k = 0; i + j + k <= num; k++) 
        { 
         for (int l = 0; i + j + k + l <= num; l++) 
         { 
          Console.WriteLine(i + " " + j + " " + k + " " + l); 
         } 
        } 
       } 
      } 

Vì vậy, nếu num là 2 sau đó sẽ chỉ là 2 vòng; i và j.

Đây KHÔNG phải là bài tập về nhà và tôi đã hy vọng làm điều đó lặp đi lặp lại. Mỗi Console.WriteLine() cần phải được lưu trữ giống như một phần tử tất cả cùng nhau.

Đầu ra của chương trình này tạo số mũ hyperspase n chiều.

+5

Bạn cần làm cho hàm của bạn đệ quy. Có một đối số xác định có bao nhiêu vòng lặp lồng nhau vẫn còn để chạy. Khi nó bằng không, làm "thang" của nó. :-P Tôi rất sẵn lòng trợ giúp thêm nữa khi tôi thấy nỗ lực đầu tiên của bạn về vấn đề này. :-) –

+4

Nếu đây là bài tập về nhà, hãy gắn nhãn cho nó, nếu không, bạn sẽ tự giúp mình bằng cách nêu rõ trường hợp kinh doanh của bạn. –

+1

Đây có phải là bài tập về nhà không? Những gì bạn đã đưa ra cho đến nay? – womp

Trả lời

14

OK, bạn muốn có một giải pháp không đệ quy đó là tham số trong numcó một hằng số của các vòng lồng nhau, đúng không?

Đây là bản phác thảo phương pháp thực hiện điều đó. Điền vào các chi tiết còn lại như một bài tập.

Trước tiên, tôi giả định rằng bạn có loại "Vector" bất biến có thể là 0-tuple, 1-tuple, 2-tuple, 3-tuple, ... n-tuple.

Phương pháp lấy kích thước của vectơ và trả về một chuỗi các vectơ có kích thước đó.

IEnumerable<Vector> MakeVectors(int num) 
{ 
    Vector current = new Vector(num); // make an all-zero vector with num items. 
    while(true) 
    { 
     yield return current; 
     Vector next; 
     bool gotAnother = GetNextVector(current, out next); 
     if (!gotAnother) break; 
     current = next; 
    } 
} 

Ở đó. Vấn đề bây giờ đã được giảm xuống hai vấn đề nhỏ hơn:

1) Cho một vectơ có kích thước num, đó có phải là vectơ cuối cùng trong chuỗi không?

2) Nếu không, vector tiếp theo là gì?

Sẽ khá đơn giản để tìm hiểu xem vector tiếp theo được đưa ra cái hiện tại: tăng giá trị của vị trí cuối cùng. Nếu điều đó quá lớn, hãy đặt thành 0 và tăng giá trị của vị trí trước đó. Lặp lại cho đến khi bạn tìm thấy thứ được tăng lên.

Có ý nghĩa?

+1

'Lợi tức lợi nhuận' là những gì tôi đang tìm kiếm. Tôi chỉ không thể nhớ nó được gọi là gì và tôi không thể tìm ra cách để mô tả nó cho google. – Ames

+0

@Ames: Để tham khảo trong tương lai, khái niệm này là của các trình vòng lặp. cf. http://msdn.microsoft.com/en-us/library/dscyy5s0.aspx. – jason

1

Lấy bạn vào văn bản của bạn rằng đây không phải là bài tập về nhà, xem dưới đây:

public void LoopRecursively(Stack<int> valuesSoFar, int dimensions) 
    { 
     for (var i = 0; SumOf(valuesSoFar) + i <= dimensions; i++) 
     { 
      valuesSoFar.Push(i); 
      if (valuesSoFar.Count == dimensions) 
      { 
       Console.WriteLine(StringOf(valuesSoFar)); 
      } 
      else 
      { 
       LoopRecursively(valuesSoFar, dimensions); 
      } 
      valuesSoFar.Pop(); 
     } 
    } 

    private int SumOf(IEnumerable<int> values) 
    { 
     return values.Sum(x => x); 
    } 

    private string StringOf(IEnumerable<int> values) 
    { 
     return string.Join(" ", values.Reverse().Select(x => x.ToString()).ToArray()); 
    } 
11

Thông thường, bạn muốn sử dụng đệ quy cho các kịch bản mà bạn đã lồng vòng nơi số vòng lặp lồng nhau không biết tại thời gian biên dịch . Một cái gì đó với ý tưởng:

void func(const vector<int> &times, int depth) { 
    if (depth == times.size()) return; 
    for (int i = 0; i < times[depth]; ++i) { 
     cout << depth; 
     func(times, depth + 1); 
    } 
} 
+0

@mehrdad. anh ấy không sử dụng std. và câu hỏi được gắn thẻ C#. +1 cho mã nhỏ. – Behrooz

+0

Cần một số sửa đổi ngữ nghĩa nhỏ để thực hiện giống như mã trong câu hỏi, nhưng +1. – dtb

+0

Tôi cho rằng đó là câu hỏi về bài tập về nhà. Tôi không có ý viết toàn bộ điều mà là ý tưởng làm những việc như thế. –

0

Để thay thế thao tác các chữ số riêng biệt, như được thực hiện trong các giải pháp đệ quy và các giải pháp sử dụng Vector <>, bạn có thể dựa vào biểu diễn máy và số học. Điều này không nhanh hơn nếu bạn cần kiểm tra từng chữ số mỗi lần qua vòng lặp, nhưng nếu bạn đang triển khai một trình lặp thì nó sẽ giảm dung lượng lưu trữ của bạn trong vòng lặp và nếu bạn không sử dụng mọi giá trị thì nó cũng có thể cải thiện hiệu quả của bạn. Trong mọi trường hợp, đó là một cách tiếp cận tương đương thú vị. Đây là ...

Đầu tiên hãy suy nghĩ về trường hợp chung chung hơn một chút, nơi bạn có n vòng lặp lồng nhau, mỗi vòng được đếm từ 0 đến num. Trong trường hợp đó, về cơ bản bạn chỉ cần đếm từ 0 đến num^n - 1 trong số cơ sở.Vì vậy, bạn có thể làm một cái gì đó như thế này:

for(int x=0; x<(num^n); x++) 
{ 
    int digit_0 = x % num; 
    int digit_1 = (x/num) % num; 
    int digit_2 = (x/num^2) % num; 
    // etc. 
} 

Lưu ý rằng:

  • Nếu không có loại nguyên tự nhiên là đủ lớn cho ứng dụng của bạn, sau đó bạn sẽ phải sử dụng một số loại lớp số nguyên lớn. Điều này sẽ làm giảm hiệu quả của các bộ phận lưu trữ và gia tăng, mặc dù có thể không nhiều bằng cách sử dụng một vectơ có chiều dài num.
  • Nếu bạn thực sự nhìn vào mỗi chữ số mỗi lần, sau đó bạn cần một vectơ chữ số, và bạn chưa đạt được gì cả. Điều này thực sự hữu ích nhất khi bạn không nhìn vào tất cả các chữ số mỗi lần.
  • Tất cả các ước số phải được precomputed, vì vậy bạn cần phải giữ xung quanh một vector cho điều đó!

Dù sao, đối với câu hỏi cụ thể của bạn, bạn không muốn đếm đến num mỗi lần, bạn muốn đếm đến num - (the sum of the already decided digits). Cách đơn giản nhất để giải thích điều này đơn giản bằng cách đặt một điều kiện thích hợp continue vào vòng lặp của bạn. Dưới đây là là với một số giá trị thay thế trong khi n=2num=10:

for(x=0; x<100; x++) // i.e. x < num*num 
{ 
    int ones = x%10; // i.e. x % num 
    int tens = (x/10) % 10; // i.e. (x/num) % num 

    if(ones + tens < 10) 
    { 
    // actually do work 
    } 
} 

(Trong trường hợp đó là không rõ ràng, tôi không có nghĩa là bạn thực sự cần sử dụng 100 và 10 trong các mã, đây chỉ là một ví dụ minh họa .)

Bạn có thể làm điều này hiệu quả hơn bằng cách tính toán số tiền tăng x, hoặc bằng cách giảm phạm vi x và sau đó ánh xạ trực tiếp đến không gian con thay vì toàn bộ không gian. (Nhưng trong 2-d và 3-d bạn đang sử dụng chính xác một nửa các giá trị có thể, do đó công việc bổ sung sẽ chỉ giúp bạn tăng tốc độ 2. Tôi nghĩ nó giống nhau khi n> 3, nhưng tôi quá lười biếng để tìm ra nó ngay bây giờ, xin lỗi!)