2010-06-15 15 views
10

tôi cần phải mã hóa một phương pháp mà tăng một giá trị chuỗi từ AAA đến zzz với xoay vòng (giá trị tiếp theo sau khi ZZZ là AAA)Tăng một giá trị từ AAA đến zzz với xoay vòng

Đây là mã của tôi:

public static string IncrementValue(string value) { 
     if (string.IsNullOrEmpty(value) || value.Length != 3) { 
      string msg = string.Format("Incorrect value ('{0}' is not between AAA and ZZZ)", value); 
      throw new ApplicationException(msg); 
     } 
     if (value == "ZZZ") { 
      return "AAA"; 
     } 
     char pos1 = value[0]; 
     char pos2 = value[1]; 
     char pos3 = value[2]; 

     bool incrementPos2 = false; 
     bool incrementPos1 = false; 

     if (pos3 == 'Z') { 
      pos3 = 'A'; 
      incrementPos2 = true; 
     } else { 
      pos3++; 
     } 

     if (incrementPos2 && pos2 == 'Z') { 
      pos2 = 'A'; 
      incrementPos1 = true; 
     } else { 
      if (incrementPos2) { 
       if (pos2 == 'Z') { 
        pos2 = 'A'; 
        incrementPos1 = true; 
       } 
       pos2++; 
      } 
     } 

     if (incrementPos1) { 
      pos1++; 
     } 

     return pos1.ToString() + pos2.ToString() + pos3.ToString(); 
    } 

tôi biết đoạn mã này là khá bẩn và không phải là rất hiệu quả nhưng tôi không biết làm thế nào để làm điều đó đúng.

Làm thế nào được đảm bảo đoạn này? (điều này sẽ chỉ chạy trên cửa sổ plaform)

Làm cách nào để tối ưu hóa và làm cho nó dễ đọc hơn?

Cảm ơn ý kiến ​​của bạn

+4

Tại sao không sử dụng số cơ sở 26? – kennytm

+0

Bạn có thực sự cần phương pháp tăng hay không, ví dụ: một iterator lặp đi lặp lại vô hạn làm việc? –

+0

@Matthew Bạn có gợi ý anh ta tạo một danh sách vòng tròn chứa các giá trị AAA..ZZZ không? Đó sẽ là một danh sách khá lớn. – meagar

Trả lời

17

Hãy suy nghĩ về nó về mặt toán học: chuỗi của bạn (AAA, AAB, ...) cư xử giống như các số tự nhiên (000, 001, ...), với ngoại lệ của là cơ sở 26 thay vì cơ sở 10

Vì vậy, bạn có thể sử dụng cùng một nguyên tắc. Dưới đây là một số mã:

// iterate cyclicly from 0 to 26^3 - 1 
int incrementValue(int i) { 
    // a verbose way of writing "return (i + 1) % 26^3" 
    i++; 
    if (i == 26*26*26) i = 0; 
    return i; 
} 

// convert 0 to AAA, 1 to AAB, ... 
string formatValue(int i) { 
    var result = new StringBuilder(); 

    result.Insert(0, (char)('A' + (i % 26))); 
    i /= 26; 
    result.Insert(0, (char)('A' + (i % 26))); 
    i /= 26; 
    result.Insert(0, (char)('A' + (i % 26))); 

    return result.ToString(); 
} 
+0

Tôi thích nó, thực hiện tăng trên một số nguyên đơn giản và chuyển đổi thành ký hiệu cơ sở-26 nhu cầu. Một màn trình diễn nhẹ mặc dù với tất cả sự chia rẽ thêm đó. – meagar

+0

@meagar: Việc chia nhỏ là một hướng dẫn máy đơn giản. Tạo cá thể StringBuilder ví dụ chi phí * cách * nhiều hơn các phân chia. – Guffa

+0

@Guffa Theo ấn tượng rằng sự phân chia vốn đã đắt hơn so với bổ sung, nhưng kiến ​​thức của tôi được thừa nhận là ngày tháng; Tôi không dành bất kỳ thời gian nào trong các ngôn ngữ cấp thấp hơn trong những ngày này. – meagar

1

Tôi nghĩ rằng đó là dễ dàng hơn để phân tích nó thành một số nguyên, làm thặng dư, sau đó định dạng kết quả như là một chuỗi. Lưu ý rằng nếu bạn chỉ cần lặp qua các số để tạo ra phạm vi kết hợp, thì bạn không thực sự cần tăng/phân tích cú pháp. Bạn có thể chỉ cần có một vòng lặp for trên phạm vi số nguyên và sử dụng phương thức định dạng để chuyển đổi số nguyên thành chuỗi.

public static string IncrementValue(string value) { 
    if (string.IsNullOrEmpty(value) || value.Length != 3) { 
     string msg = string.Format("Incorrect value ('{0}' is not between AAA and ZZZ)", value); 
     throw new ApplicationException(msg); 
    } 
    if (value == "ZZZ") { 
     return "AAA"; 
    } 
    int thisValue = Parse(value); 
    thisValue = (thisValue + 1) % 17576; // 26 * 26 * 26 
    return Format(thisValue); 
} 

private static int Parse(string value) 
{ 
    int result = 0; 
    foreach (var c in value) 
    { 
     result += ('Z' - c); // might need to cast to int? 
    } 
    return result; 
} 

private static string[] Alphabet = new string[] { 'A', 'B', ... }; 
private static string Format(int value) 
{ 
    int digit0 = value % 26; 
    int digit1 = (value/26) % 26; 
    int digit2 = value/676; 
    return Alphabet[digit2] + Alphabet[digit1] + Alphabet[digit0]; 
} 
11

Có lẽ tôi đang thiếu điều gì đó, nhưng tôi cho rằng giải pháp không đáng kể này hoạt động và không chỉ cho ba chữ số; bất kỳ số cơ sở chiều dài cơ sở 26 có thể được tăng lên. Nó sẽ quấn từ ZZZZ đến AAAA theo câu hỏi, thay vì tăng "đúng" từ ZZZZ đến AAAAA.

// Increment a base 26 number (composed of "digits" A..Z), wrapping around 
// from ZZZ... to AAA... 
string increment(string str) {   
    char[] digits = str.ToCharArray(); 

    for (int i = str.length - 1; i >= 0; --i) { 
    if (digits[i] == 'Z') { 
     digits[i] = 'A'; 
    } else { 
     digits[i] += 1; 
     break; 
    } 
    } 
    return new string(digits); 
} 
+2

+1, một thuật toán tổng quát thuật toán tốt đẹp và nhỏ gọn của thuật toán "thêm" mà chúng tôi đã học ở trường mẫu giáo. BTW: Việc sửa i thành 3 sẽ cho phép bạn thả 'if' vào đầu phương thức và sẽ dẫn đến kết quả" tự nhiên "xung quanh. – Heinzi

+0

@Heinzi Có, đã xóa nó. Thuật toán cho loại tăng chuyên biệt này tiếp tục đơn giản hơn, tôi càng nghĩ về nó. Nó đơn giản như nó sẽ có ngay bây giờ ... – meagar

+0

Cảm ơn Meagar vì đoạn mã của bạn. Nó nhỏ gọn, đơn giản và rõ ràng. Cách này để giải quyết vấn đề của tôi thực sự là "thanh lịch"! – fxkim

-1

Trong 'C' tôi đã viết như sau sẽ làm chính xác như được yêu cầu, tức là AA sẽ tăng lên AB. Cho ZZZ sẽ tăng lên AAA (chu kỳ).

main(int argc, char **argv) 
{ 

    int i; 
    char *s = argv[1]; 

    for(i=strlen(s)-1; i >= 0; i--) { 
      if(++s[i] > 'Z') 
       s[i] = 'A'; 
      else 
       break; 
    } 

    printf("%s\n",s); 
} 
+0

C# không C. Bên cạnh một số điểm tương đồng về cú pháp, chúng hầu như không có gì. – meagar

-1
import java.util.*; 

import java.io.*; 

public class abc{ 

public static void main (String arg[])throws Exception{ 

int i; 

String s; 

BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); 

System.out.println("...");\\just for get length of vector example 3 for aaa to zzz 
i= Integer.parseInt(br.readLine()); 
char[] guess = new char[i]; 

Arrays.fill(guess, 'a'); 


do { 
System.out.println("Current guess: " + new String(guess)); 


int n = guess.length - 1; 

while (n >= 0) { 

guess[n]++; 

if (guess[n] > 'z') { 

       if (n > 0) { 

        guess[n] = 'a'; 

       } 

       n--; 

      } 

    else { 

       break; 

      } 

     } 


    } 
while (guess[0] <= 'z'); 

} 
+0

Đây là câu hỏi C#, không phải là câu hỏi Java. – meagar

Các vấn đề liên quan