2009-09-04 52 views
6

這個問題很複雜,但我會詳細解釋它。如何進行字符串的下一步。 C#

目標是創建一個函數,它將返回給定字符串的下一個「步驟」。

例如

String.Step("a"); // = "b" 
String.Step("b"); // = "c" 
String.Step("g"); // = "h" 
String.Step("z"); // = "A" 
String.Step("A"); // = "B" 
String.Step("B"); // = "C" 
String.Step("G"); // = "H" 

直到這裏它很容易,但同時記住,輸入字符串,它可以包含超過100個字符和功能必須這樣的表現。

String.Step("Z"); // = "aa"; 
String.Step("aa"); // = "ab"; 
String.Step("ag"); // = "ah"; 
String.Step("az"); // = "aA"; 
String.Step("aA"); // = "aB"; 
String.Step("aZ"); // = "ba"; 
String.Step("ZZ"); // = "aaa"; 

等等...

這不正是需要擴展基String類。

我試圖通過每個字符的ASCII值來解決問題,但卡住了包含2個字符的字符串。

我真的很感激,如果有人可以提供完整的功能代碼。

在此先感謝。

編輯 *對不起,我忘了前面提到的功能「重新分析」自我生成的字符串時,其長度達到ñ

continuation of this function will be smth like this. for example n = 3 
String.Step("aaa"); // = "aab"; 
String.Step("aaZ"); // = "aba"; 
String.Step("aba"); // = "abb"; 
String.Step("abb"); // = "abc"; 
String.Step("abZ"); // = "aca"; 
..... 
String.Step("zzZ"); // = "zAa"; 
String.Step("zAa"); // = "zAb"; 
........ 

對不起,我之前沒有提到它,在閱讀了一些答案之後,我意識到問題是有問題的。

沒有此功能將在步驟結束後始終生成字符「a」n次。

+4

爲什麼不發佈你試過的東西? – 2009-09-04 12:49:19

+0

輸入始終是a-zA-Z – George 2009-09-04 13:17:46

+0

對不起,我忘了添加主要問題:S。 已編輯的問題。 – George 2009-09-04 13:18:51

回答

11

注:這個答案是不正確,爲 「AA」, 「Z」 後,應遵循...(見下文評論)

這是可能的工作的算法:

「字符串」表示給定基數的數字(這裏:字母表中字母數的兩倍)。

因此,下一步可以通過將「數字」字符串解析爲一個int,然後加1然後將其格式化回基數來計算。

實施例:

"a" == 1 -> step("a") == step(1) == 1 + 1 == 2 == "b" 

現在您的問題歸結爲解析字符串作爲數字的給定鹼和重新格式化。一個谷歌搜索暗示了這個頁面:http://everything2.com/title/convert+any+number+to+decimal

如何實現這個?

  • 查詢表中的字母對應的數字:a = 1,b = 2,c = 3,... Y =?,Z = 0
  • 解析字符串到數字,讀取以相反的順序中的字符,查找的數量和增加起來:
    • 「AB」 - > 2 * BASE^0 + 1 * BASE^1
    • 與基座上的 「數字」 的數量(2計數的字母,是48?)

編輯:這個鏈接看起來更有前途:http://www.citidel.org/bitstream/10117/20/12/convexp.html

+0

你能否簡單地解釋一下,比如發佈一個僞代碼,或者如果可能的話填滿一個。謝謝 – George 2009-09-04 12:54:08

+1

它其實並不那麼簡單,哪個字母代表0,a? 「a」的整數值是多少?「aa」的整數值是多少? – AnthonyWJones 2009-09-04 12:55:28

+0

@Anthony:從這個問題的例子中,我認爲它只是顛倒了Base52。 'a = 0,A = 26,aa = 52' – dtb 2009-09-04 13:07:40

0

將輸入字符串拆分爲多列,並按從右到左的順序進行處理,就像是基本算術一樣。將所有可用於單列的代碼應用於每列。當你得到一個Z時,你使用相同的算法「增加」下一個左列。如果沒有左下角的列,請粘貼「a」。

-1

LetterToNum應該是一個函數,它將「a」映射爲0,「Z」映射爲51. NumToLetter的逆。

long x = "aazeiZa".Aggregate((x,y) => (x*52) + LetterToNum(y)) + 1; 
string s = ""; 

do { // assertion: x > 0 
    var c = x % 52; 
    s = NumToLetter() + s; 
    x = (x - c)/52; 
} while (x > 0) 

// s now should contain the result 
+0

)再次使用基於Base52的方法,這不起作用。第一行將返回1作爲「a」或「aa」或「aaa」。 – AnthonyWJones 2009-09-04 13:40:42

+0

確實,錯過了52. – 2009-09-04 13:43:01

3
public static class StringStep 
{ 
    public static string Next(string str) 
    { 
     string result = String.Empty; 
     int index = str.Length - 1; 
     bool carry; 
     do 
     { 
      result = Increment(str[index--], out carry) + result;    
     } 
     while (carry && index >= 0); 
     if (index >= 0) result = str.Substring(0, index+1) + result; 
     if (carry) result = "a" + result; 
     return result; 
    } 

    private static char Increment(char value, out bool carry) 
    { 
     carry = false; 
     if (value >= 'a' && value < 'z' || value >= 'A' && value < 'Z') 
     { 
      return (char)((int)value + 1); 
     } 
     if (value == 'z') return 'A'; 
     if (value == 'Z') 
     { 
      carry = true; 
      return 'a'; 
     } 
     throw new Exception(String.Format("Invalid character value: {0}", value)); 
    } 
} 
+0

+1。像這個最好的(甚至比我的更好),a)它的工作原理(無論如何都通過我的測試),b)操作更清晰,c)本質上包含一些防禦性代碼。好一個。 ;) – AnthonyWJones 2009-09-04 13:47:51

+0

謝謝,首先我想讓它易讀易懂。 – empi 2009-09-04 13:51:24

0

你需要考慮A)的事實,大寫字母在ASCII表低於那些情況下,較低的十進制值。 B)表格不是連續的A-Z-a-z - 在Z和a之間有字符。

public static string stepChar(string str) 
{ 
    return stepChar(str, str.Length - 1); 
} 

public static string stepChar(string str, int charPos) 
{ 
    return stepChar(Encoding.ASCII.GetBytes(str), charPos); 
} 

public static string stepChar(byte[] strBytes, int charPos) 
{ 
    //Escape case 
    if (charPos < 0) 
    { 
    //just prepend with a and return 
    return "a" + Encoding.ASCII.GetString(strBytes); 
    } 
    else 
    { 

    strBytes[charPos]++; 

    if (strBytes[charPos] == 91) 
    { 
     //Z -> a plus increment previous char 
     strBytes[charPos] = 97; 
     return stepChar(strBytes, charPos - 1);    } 
    else 
    { 
     if (strBytes[charPos] == 123) 
     { 
     //z -> A 
     strBytes[charPos] = 65; 
     } 

     return Encoding.ASCII.GetString(strBytes); 
    } 
    } 
} 

您可能希望在一些地方檢查,以確保輸入字符串只包含字符A-雜誌-Z


編輯整理了代碼,增加了新的重載以刪除冗餘字節[] - >串 - >字節[]轉換

Proof http://geekcubed.org/random/strIncr.png

5

相當approa的集合CHES,這裏是我的: -

的功能:

private static string IncrementString(string s) 
{ 
    byte[] vals = System.Text.Encoding.ASCII.GetBytes(s); 
    for (var i = vals.Length - 1; i >= 0; i--) 
    { 
    if (vals[i] < 90) 
    { 
     vals[i] += 1; 
     break; 
    } 
    if (vals[i] == 90) 
    { 
     if (i != 0) 
     { 
     vals[i] = 97; 
     continue; 
     } 
     else 
     { 
     return new String('a', vals.Length + 1); 
     } 
    } 

    if (vals[i] < 122) 
    { 
     vals[i] += 1; 
     break; 
    } 

    vals[i] = 65; 
    break; 
    } 

    return System.Text.Encoding.ASCII.GetString(vals); 
} 

測試

Console.WriteLine(IncrementString("a") == "b"); 
Console.WriteLine(IncrementString("z") == "A"); 
Console.WriteLine(IncrementString("Z") == "aa"); 
Console.WriteLine(IncrementString("aa") == "ab"); 
Console.WriteLine(IncrementString("az") == "aA"); 
Console.WriteLine(IncrementString("aZ") == "ba"); 
Console.WriteLine(IncrementString("zZ") == "Aa"); 
Console.WriteLine(IncrementString("Za") == "Zb"); 
Console.WriteLine(IncrementString("ZZ") == "aaa"); 
+0

+1花式循環 - 我更喜歡遞歸函數;) – Ian 2009-09-04 13:56:09

0

對不起問題是部分說明。 我編輯的問題,以便它符合要求,沒有編輯該功能將逐步逐步增加每個單詞從小寫字母a到大寫z沒有「重新解析」它最終將與n次。

請考慮重新閱讀問題,包括編輯部分

0

這就是我想出的。我不是依靠ASCII int轉換,而是使用一組字符。這應該做你正在尋找的東西。

public static string Step(this string s) 
    { 
     char[] stepChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray(); 

     char[] str = s.ToCharArray(); 
     int idx = s.Length - 1; 

     char lastChar = str[idx]; 


     for (int i=0; i<stepChars.Length; i++) 
     { 
      if (stepChars[i] == lastChar) 
      { 
       if (i == stepChars.Length - 1) 
       { 
        str[idx] = stepChars[0]; 
        if (str.Length > 1) 
        { 
         string tmp = Step(new string(str.Take(str.Length - 1).ToArray())); 
         str = (tmp + str[idx]).ToCharArray(); 
        } 
        else 
         str = new char[] { stepChars[0], str[idx] }; 
       } 
       else 
        str[idx] = stepChars[i + 1]; 

       break; 
      } 
     } 

     return new string(str); 
    } 
0

這是一個數字系統的特例。它有52的基數。如果你寫了一些解析器和輸出邏輯,你可以做任何類型的算術,這裏顯然是+1(++)。 數字是「a」 - 「z」和「A」到「Z」,其中「a」爲零且「Z」爲51

因此,您必須編寫一個解析器來接收字符串並構建一個int或者離它很遠。這個函數被稱爲StringToInt()並且被直接實現(將字符轉換爲數字(0..51)與52相乘並取下一個字符)

而且您需要反向函數IntToString,它也實現爲直接向前用52對int進行取模並將結果轉換爲數字,將int除以52並重復此操作,直到int爲null)

使用此功能,您可以執行下列操作: IntToString(StringToInt(「ZZ」)+1) //將會是「aaa」

+1

不是那麼簡單。自!= aa!= aaa以來沒有「零位」。由於aZ!= ZaZ,無法使用Z. – jnylen 2009-09-04 17:36:33

0

這很像Excel表格如果無界限時可以工作。您可以將52更改爲引用字符。長度更容易修改。

static class AlphaInt { 
    private static string chars = 
     "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 

    public static string StepNext(string input) { 
     return IntToAlpha(AlphaToInt(input) + 1); 
    } 

    public static string IntToAlpha(int num) { 
     if(num-- <= 0) return "a"; 
     if(num % 52 == num) return chars.Substring(num, 1); 
     return IntToAlpha(num/52) + IntToAlpha(num % 52 + 1); 
    } 

    public static int AlphaToInt(string str) { 
     int num = 0; 
     for(int i = 0; i < str.Length; i++) { 
      num += (chars.IndexOf(str.Substring(i, 1)) + 1) 
        * (int)Math.Pow(52, str.Length - i - 1); 
     } 
     return num; 
    } 
} 
相關問題