2009-09-04 10 views
6

सवाल जटिल है लेकिन मैं इसे विवरण में समझाऊंगा।स्ट्रिंग का अगला चरण कैसे बनाएं। सी #

लक्ष्य एक ऐसा फ़ंक्शन बनाना है जो दिए गए स्ट्रिंग के अगले "चरण" को वापस कर देगा।

उदाहरण

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" 

यहाँ अपने काफी आसान तक के लिए

, लेकिन ध्यान ले जा रहा है कि इनपुट स्ट्रिंग है यह 1 से अधिक वर्ण हो सकते हैं और समारोह इस तरह व्यवहार करना चाहिए।

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"; 

और इतने पर ...

यही आधार स्ट्रिंग वर्ग का विस्तार करने की जरूरत नहीं है।

मैंने प्रत्येक अक्षर ASCII मानों से इसे काम करने की कोशिश की लेकिन स्ट्रिंग्स के साथ 2 अक्षर युक्त अटक गए।

यदि कोई व्यक्ति फ़ंक्शन का पूरा कोड प्रदान कर सकता है तो मैं वास्तव में सराहना करता हूं।

अग्रिम धन्यवाद।

संपादित * मैं माफी चाहता कि मैंने पहले कि समारोह "रीपार्स" आत्म उत्पन्न स्ट्रिंग जब इसकी लंबाई n तक पहुँच जाता है उल्लेख करना भूल गया हूँ।

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"; 
........ 

मुझे खेद है कि मैंने पहले इसका उल्लेख नहीं किया था, कुछ उत्तरों पढ़ने के बाद मुझे एहसास हुआ कि समस्या प्रश्न में थी।

इसके बिना यह कार्य हमेशा चरण के अंत के बाद चरित्र "ए" एन बार उत्पन्न करेगा।

+4

आपने जो भी प्रयास किया है उसे पोस्ट न करें? –

+0

इनपुट हमेशा एक-जेए-जेड – George

+0

मुझे खेद है कि मैं मुख्य प्रश्न जोड़ना भूल गया: एस। प्रश्न संपादित किया गया। – George

उत्तर

11

नोट: इस उत्तर गलत है, "आ" "Z" के बाद का पालन करना चाहिए के रूप में ... (नीचे टिप्पणी देखें)

यहाँ एक एल्गोरिथ्म है कि काम हो सकता है है:

प्रत्येक "स्ट्रिंग" किसी दिए गए आधार पर एक संख्या का प्रतिनिधित्व करता है (यहां: वर्णमाला में अक्षरों की संख्या दोगुना)।

इस प्रकार अगले चरण को "संख्या" को पीछे छोड़कर एक int में वापस खींचकर गणना की जा सकती है, 1 जोड़कर और फिर इसे आधार पर वापस स्वरूपित किया जा सकता है।

उदाहरण:

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

अब आपकी समस्या किसी दिए गए आधार पर किसी संख्या के रूप में स्ट्रिंग को पार्स करने और उसे पुन: प्रारूपित करने के लिए कम है। एक त्वरित googling इस पृष्ठ का सुझाव देता है: http://everything2.com/title/convert+any+number+to+decimal

इसे कैसे कार्यान्वित करें?

  • उनके संबंधित नंबर पर अक्षरों के लिए एक लुकअप टेबल: ए = 1, बी = 2, सी = 3, ... वाई =?, जेड = 0
  • एक स्ट्रिंग पार्स करने के लिए संख्या, उलटे क्रम में वर्ण, संख्या को देख और उन्हें जोड़ने पढ़ें:
    • "ab" -> 2 * आधार^0 + 1 * आधार^1
    • आधार "अंक" की संख्या होने के साथ
    • (वर्णमाला के अक्षरों की 2 गिनती, कि 48 है?)

संपादित करें: इस कड़ी और भी अधिक आशाजनक दिखता है: http://www.citidel.org/bitstream/10117/20/12/convexp.html

+0

क्या आप इसे छद्म कोड पोस्ट करने या यदि संभव हो तो इसे संक्षिप्त रूप से समझा सकते हैं। धन्यवाद – George

+1

यह वास्तव में इतना आसान नहीं है, कौन सा पत्र 0 का प्रतिनिधित्व करता है, एक? "ए" का int मान क्या है और "aa" का int मान क्या है? – AnthonyWJones

+0

@ एंथनी: प्रश्न के उदाहरणों से, मुझे लगता है कि यह बस बेस 52 को उलट देता है। 'ए = 0, ए = 26, एए = 52' – dtb

0

कॉलम में इनपुट स्ट्रिंग को विभाजित करें और प्रत्येक, दाएं से बाएं को संसाधित करें, जैसे कि यह मूल अंकगणित होगा। जो भी कोड मिला है उसे लागू करें जो प्रत्येक कॉलम में एक कॉलम के साथ काम करता है। जब आप ज़ेड प्राप्त करते हैं, तो आप उसी एल्गोरिदम का उपयोग करके अगले बाएं कॉलम को 'increment' करते हैं। यदि कोई अगला बाएं कॉलम नहीं है, तो 'ए' में चिपकाएं।

-1

LetterToNum एक ऐसा फ़ंक्शन होना चाहिए जो "ए" से 0 और "Z" को 51 तक 0.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

फिर से बेस 52 आधारित दृष्टिकोण, यह काम नहीं करता है। पहली पंक्ति "ए" या "एए" या "aaa" के लिए 1 लौटाएगी। – AnthonyWJones

+0

वास्तव में, 52. –

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 से चूक गया। इस तरह की सबसे अच्छी (मेरे से भी बेहतर), ए) क्योंकि यह काम करता है (वैसे भी मेरे परीक्षणों का सेट पास करता है), बी) ऑपरेशन स्पष्ट है और सी) आंतरिक रूप से कुछ रक्षात्मक कोड शामिल है। अच्छा है। ;) – AnthonyWJones

+0

धन्यवाद, सबसे पहले मैं इसे पठनीय और समझने में आसान होना चाहता था। फैंसी लूप के लिए – empi

0

आप) एक के लिए खाते में तथ्य यह है बड़े अक्षरों छोटे अक्षर की तुलना में Ascii तालिका में एक कम दशमलव मान है की जरूरत है। बी) तालिका निरंतर ए-जेड-ए-जेड नहीं है - ज़ेड और ए के बीच वर्ण हैं।

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); 
    } 
    } 
} 

आप यह सुनिश्चित करें कि इनपुट स्ट्रिंग केवल शामिल वर्ण ए-Za-z


संपादित कोड को tidied और अनावश्यक दूर करने के लिए नई अधिभार जोड़ा जगह में कुछ जाँच शायद चाहता हूँ बाइट [] -> स्ट्रिंग -> बाइट [] रूपांतरण

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

5

काफी approa का संग्रह टांके, यहाँ मेरा है: -

फंक्शन:

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

0

मैं माफी सवाल आंशिक रूप से कहा गया है हूँ। मैंने इस सवाल को संपादित किया है कि यह संपादन के बिना, 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 (++) कर सकते हैं। अंक "ए" - "जेड" और "ए" से "ज़ेड" हैं जहां "ए" शून्य है और "ज़ेड" 51

तो आपको एक पार्सर लिखना है जो स्ट्रिंग लेता है और int बनाता है या उससे लंबा। इस फ़ंक्शन को स्ट्रिंगटॉइन्ट() कहा जाता है और इसे सीधे आगे बढ़ाया जाता है (चार से गुणा (0..51) को 52 के साथ गुणा करें और अगले चार ले जाएं)

और आपको रिवर्स फ़ंक्शन इंटॉस्ट्रिंग की आवश्यकता है जो सीधे आगे भी कार्यान्वित है (52 के साथ int को संशोधित करें और अंक को बदल दें, int को 52 तक विभाजित करें और int को शून्य तक दोहराएं)

इस फ़ंक्शन के साथ आप इस तरह की चीज़ें कर सकते हैं: IntToString (StringToInt ("ZZ") +1) // "aaa"

+1

इतना आसान नहीं है। एक के बाद से कोई "शून्य अंक" नहीं है! = Aa! = Aaa। जेड का उपयोग नहीं कर सकते क्योंकि एजेड! = ज़ाज़ – jnylen

0

यह बहुत कुछ है जैसे एक्सेल कॉलम काम नहीं करेंगे अगर वे असंबद्ध थे। आप 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; 
    } 
} 
संबंधित मुद्दे