2012-11-27 23 views
12

के साथ टेलीफोन शब्द को अधिक सुन्दर तरीके से हल करने का प्रयास कर मैंने स्टैक ओवरफ़्लो को देखा है लेकिन काम करने के लिए कुछ भी नहीं मिला है। अगर मैं एक स्पष्ट रूप से स्पष्ट पोस्ट चूक गया तो मैं क्षमा चाहता हूं।रिकर्सन

मुझे एक स्कूल समस्या थी जिसमें फ़ोन नंबर लेने, सभी संभावित शब्द संयोजन प्राप्त करने और फिर इसे एक टेक्स्ट फ़ाइल में लिखना शामिल था। मैंने ऐसा किया और मेरे असाइनमेंट के लिए पूर्ण क्रेडिट मिला। मैं इसे सात नेस्टेड लूप के साथ करने में सक्षम था लेकिन यह बहुत ही सुरुचिपूर्ण नहीं है और बहुत कठोर है। मुझे दूर उड़ा दिया गया और पाठ्यपुस्तक समाधान खोजने के लिए पूरी तरह निराश सात नेस्टेड लूप था। मेरे प्रशिक्षक के पास कोई जवाब नहीं था।

मैंने कई अलग-अलग दृष्टिकोणों की कोशिश की है लेकिन मैं इसे डायल करने में सक्षम नहीं हूं। मैंने एक रिकर्सन और हत्या बिंदु की पहचान की लेकिन कभी भी इसे काम करने में सक्षम नहीं था। मैं पत्र अनुक्रमों का उत्पादन कर सकता हूं लेकिन कहीं भी नहीं होना चाहिए। मैंने अपने प्रयासों पर टिप्पणी की ताकि आप मेरी असफल विचार प्रक्रियाओं को देख सकें :) कृपया एक नज़र डालें और अगर आपके पास कोई विचार है तो मुझे बताएं।

public partial class TelephoneWorderizer : Form 
{ 
    protected Dictionary<int, IEnumerable<string>> KeyMappings = new Dictionary<int, IEnumerable<string>>(); 
    protected string[][] ActiveLettersGroups = null; 
    protected List<string> Words = new List<string>(); 
    protected List<string> RecursiveWords = new List<string>(); 
    protected int Iteration = 0; 

    public TelephoneWorderizer() 
    { 
     InitializeComponent(); 

     this.KeyMappings = this.GetKeyMappings(); 
    } 

    private void btnGetWords_Click(object sender, EventArgs e) 
    { 
     string textBoxContent = textBoxNumber.Text; 

     int[] digits = this.GetPhoneNumbers(textBoxContent); 

     List<string> words = this.GetWords(digits); 

     using (StreamWriter writer = new StreamWriter(@"E:\words.txt")) 
     { 
      foreach (var word in words) 
      { 
       writer.WriteLine(word); 
      } 
     } 

     textBoxNumber.Clear(); 
    } 

    private List<string> GetWords(int[] digits) 
    { 
     List<string[]> letterGroupings = new List<string[]>(); 

     //digits array of numbers 
     for (int i = 0, j = digits.Length; i < j; i++) 
     { 
      int digit = digits[i]; 

      //if the number has a letter group mapped to it 
      if (this.KeyMappings.ContainsKey(digit)) 
      { 
       // letters mapped to a given number 
       letterGroupings.Add(this.KeyMappings[digit].ToArray()); 
      } 
     } 

     this.WordMakerLoop(letterGroupings); 
     //this.WordMaker(letterGroupings); 

     return this.Words; 
     //return this.RecursiveWords; 
    } 

    //private void RecursionTest(string word, List<string[]> groups, int letterCtr, int groupCtr) 
    //{ 
    // string[] Group = groups[groupCtr]; 

    // word += Group[letterCtr]; 

    // letterCtr += 1; 

    // if (letterCtr < Group.Length - 1) 
    // { 
    //  letterCtr = 0; 
    //  groupCtr += 1; 

    //  // Hit bottom 
    //  if (groupCtr == groups.Count - 1) 
    //  { 
    //   groupCtr -= 1; 
    //  } 

    //  RecursionTest(word, groups, letterCtr, groupCtr); 
    // } 
    //} 

    private void WordMaker(List<string[]> letterCollections) 
    { 
     string newword = ""; 
     int numberLength = letterCollections.Count; 

     this.ActiveLettersGroups = letterCollections.ToArray(); 

     string[] letterGroup = this.ActiveLettersGroups[0]; 

     this.RecursiveGetWords(newword, 0, 0); 
    } 

    /// <summary> 
    /// 
    /// </summary> 
    /// <param name="word"></param> 
    /// <param name="groupIndex"></param> 
    /// <param name="letterIndex"></param> 
    private void RecursiveGetWords(string word, int groupIndex, int letterIndex) 
    { 

     /* 
     * 
     * 
     * 
     */ 


     var numActiveLetterGroups = this.ActiveLettersGroups.Length; 

     if (this.ActiveLettersGroups.Length > 0 && this.Iteration < numActiveLetterGroups) 
     { 
      if (groupIndex < numActiveLetterGroups) 
      { 
       var letters = this.ActiveLettersGroups[groupIndex]; // Picks the a letter group ex: A, B, C 

       if (letterIndex < letters.Length) 
       { 
        //var letter1 = letters.Select(x => 
        string letter = letters[letterIndex]; // Picks a letter from the group ex: A 

        word += letter; 

        this.RecursiveGetWords(word, groupIndex + 1, this.Iteration); 
       } 
       else 
       { 
        //this.RecursiveWords.Add(word); 
        //word = ""; 

        //this.RecursiveGetWords(word, 0, 1); 
       } 
      } 
      else 
      { 
       this.RecursiveWords.Add(word); 
       word = ""; 
       this.Iteration++; 

       this.RecursiveGetWords(word, 0, this.Iteration); 
      } 
     } 
    } 

    #region 
    private void WordMakerLoop(List<string[]> letterGroups) 
    { 
     string word = ""; 

     // array of string[] 
     var newGroup = letterGroups.ToArray(); 

     //grabs a letter group 
     for (int i = 0; i < newGroup.Length; i++) 
     { 
      var letterGroup1 = newGroup[i]; 

      //grabs a letter from group 1 
      for (int j = 0; j < letterGroup1.Length; j++) 
      { 
       string letter1 = letterGroup1[j]; 

       if (i + 1 < newGroup.Length) 
       { 
        var letterGroup2 = newGroup[i + 1]; 

        //grabs a letter from group 2 
        for (int k = 0; k < letterGroup2.Length; k++) 
        { 
         string letter2 = letterGroup2[k]; 

         if (i + 2 < newGroup.Length) 
         { 
          var letterGroup3 = newGroup[i + 2]; 

          //grabs a letter from group 3 
          for (int l = 0; l < letterGroup3.Length; l++) 
          { 
           string letter3 = letterGroup3[l]; 

           if (i + 3 < newGroup.Length) 
           { 
            var letterGroup4 = newGroup[i + 3]; 

            //grabs a letter from group 4 
            for (int m = 0; m < letterGroup4.Length; m++) 
            { 
             string letter4 = letterGroup4[m]; 

             if (i + 4 < newGroup.Length) 
             { 
              var letterGroup5 = newGroup[i + 4]; 

              //grabs a letter from group 5 
              for (int n = 0; n < letterGroup5.Length; n++) 
              { 
               string letter5 = letterGroup5[n]; 

               if (i + 5 < newGroup.Length) 
               { 
                var letterGroup6 = newGroup[i + 5]; 

                //grabs a letter from group 6 
                for (int o = 0; o < letterGroup6.Length; o++) 
                { 
                 string letter6 = letterGroup6[o]; 

                 if (i + 6 < newGroup.Length) 
                 { 
                  var letterGroup7 = newGroup[i + 6]; 

                  //grabs a letter from group 6 
                  for (int p = 0; p < letterGroup7.Length; p++) 
                  { 
                   string letter7 = letterGroup7[p]; 

                   word = letter1 + letter2 + letter3 + letter4 + letter5 + letter6 + letter7; 
                   this.Words.Add(word); 
                   word = ""; 
                  } 
                 } 
                } 
               } 
              } 
             } 
            } 
           } 
          } 
         } 
        } 
       } 
      } 
     } 
    } 

    // Sanitizes input text and converts the string into and arra of int 
    private int[] GetPhoneNumbers(string content) 
    { 
     int[] phoneNumbers = null; 

     string cleanString = this.SanitizeString(content); 

     int numbers; 

     if (Int32.TryParse(cleanString, out numbers)) 
     { 
      //phoneNumbers = this.GetIntArray(numbers).OfType<int>().ToList(); 
      phoneNumbers = this.GetIntArray(numbers); 
     } 

     return phoneNumbers; 
    } 

    // Removes potential unwanted characters from the phone number 
    private string SanitizeString(string content) 
    { 
     content = content.Replace("-", ""); 
     content = content.Replace("(", ""); 
     content = content.Replace(")", ""); 

     return content; 
    } 

    //breaks a number into an array of its individual digits 
    private int[] GetIntArray(int num) 
    { 
     List<int> listOfInts = new List<int>(); 

     while (num > 0) 
     { 
      listOfInts.Add(num % 10); 
      num = num/10; 
     } 

     listOfInts.Reverse(); 

     return listOfInts.ToArray(); 
    } 

    //gets the mappings for the numerical values 
    private Dictionary<int, IEnumerable<string>> GetKeyMappings() 
    { 
     List<string> alphabet = new List<string>() { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" }; 
     Dictionary<int, IEnumerable<string>> mappings = new Dictionary<int, IEnumerable<string>>(); 

     for (int i = 0; i < 10; i++) 
     { 
      string[] letters = null; 
      switch (i) 
      { 
       case 0: 
       case 1: 
        break; 
       case 2: 
       case 3: 
       case 4: 
       case 5: 
       case 6: 
       case 8: 
        letters = alphabet.Take(3).ToArray(); 
        mappings.Add(i, letters); 
        alphabet.RemoveRange(0, 3); 
        break; 
       case 7: 
       case 9: 
        letters = alphabet.Take(4).ToArray(); 
        mappings.Add(i, letters); 
        alphabet.RemoveRange(0, 4); 
        break; 
       default: 
        break; 
      } 
     } 

     return mappings; 
    } 
    #endregion 
} 

मुझे इस बात पर जोर देना चाहिए कि स्कूल के असाइनमेंट उन लोगों के लिए संदेह में है। मैं यह बेहतर और अधिक कुशल करना चाहता हूं। अगर मैं मदद करता हूं तो मैं अपनी परियोजना को गिटहब पर पोस्ट कर सकता हूं।

+0

ऐसा कुछ लगता है जो [codegolf.se] – ThiefMaster

+0

के लिए एक बहुत अच्छा फिट होगा, समस्या को देखने के लिए बहुत बढ़िया सवाल, और आपके तर्क स्पष्ट रूप से बताए गए हैं, साथ ही साथ कोड फ़ॉर्म में इसे हल करने के आपके प्रयास भी हैं। अक्सर अधिक जानकारी के लिए पूछने वाली टिप्पणियां होती हैं या व्यक्ति को प्रश्न पूछने के लिए पूछने के लिए कहा जाता है, यह आपके पास बहुत ही बढ़िया है। इसके लिए +1। – Crippledsmurf

उत्तर

3

मैं इस समय किसी भी कोड को लिखने के लिए बहुत आलसी हूं, लेकिन आपको निश्चित रूप से सात नेस्टेड लूपों के बजाय रिकर्सन के माध्यम से ऐसा करने में सक्षम होना चाहिए, और वास्तव में आप किसी विधि को डिजाइन करने में सक्षम होना चाहिए जो किसी पर काम करना चाहिए मनमानी लंबाई टेलीफोन नंबर।

मूल विचार यह है कि आप इस तरह एक पुनरावर्ती विधि कुछ डिजाइन होता है:

void recurse(String phone, int index, StringBuilder sb) 
{ 
    // Get the number at position phone[index] 
    // Loop through the possible letters for that particular number (eg. A, B, C): 
     // Add the letter to the StringBuilder 
     // Call recurse(phone, index + 1, sb) 
     // Subtract last letter from the StringBuilder 
} 

हर बार जब आप recurse आप अगले संख्या/अक्षर स्थिति पर काम कर रहे हैं।

बेशक यदि आप टर्मिनिंग हालत (एसबी लंबाई == फोन लम्बाई) में भाग लेते हैं, तो आपको रिकर्सिंग करने के बजाय स्ट्रिंगबिल्डर के वर्तमान मूल्य को फ़ाइल और लौटने के लिए लिखें।

उम्मीद है कि इससे मदद मिलती है।

संपादित करें: वास्तव में कुछ कोड लिखने के लिए आसपास हो रही है। यह वास्तव में इस सरल है, कोई LINQ आवश्यक:

class Program 
    { 
     static Dictionary<Char, String> DigitMap = new Dictionary<Char, String>() 
     { 
     {'0', "0"}, 
     {'1', "1"}, 
     {'2', "ABC"}, 
     {'3', "DEF"}, 
     {'4', "GHI"}, 
     {'5', "JKL"}, 
     {'6', "MNO"}, 
     {'7', "PQRS"}, 
     {'8', "TUV"}, 
     {'9', "WXYZ"} 
     }; 

     static void Main(string[] args) 
     { 
     String phone = Regex.Replace("867-5309", "[^0-9]", ""); 
     recurse(phone, 0, new StringBuilder()); 
     } 

     static void recurse(String phone, int index, StringBuilder sb) 
     { 
     // Terminating condition 
     if (index == phone.Length) 
     { 
      Console.WriteLine(sb.ToString()); 
      return; 
     } 

     // Get digit and letters string 
     Char digit = phone[index]; 
     String letters = DigitMap[digit]; 

     // Loop through all letter combinations for digit 
     foreach (Char c in letters) 
     { 
      sb.Append(c); 
      recurse(phone, index + 1, sb); 
      sb.Length -= 1; 
     } 
     } 
    } 
} 

इस कोड में (जहां मैं एक साधारण सांत्वना एप्लिकेशन बनाया) मैं सिर्फ कंसोल के लिए शब्द लिख रहा हूँ, लेकिन आप किसी सरणी या लेखन के लिए तार जोड़ने जा सकता है उन्हें बदले में डिस्क पर।

0

यहाँ Javaish छद्म codeish पुनरावर्ती क्रिया है:

void recWords(String number, int ind, String buf, Collection<String> result){ 
    if(ind==number.length()) { 
    result.add(buf); 
    } else { 
    for(char letter : lettersForNumber(number.charAt(ind)) { 
     recWords(number, ind+1, buf+letter, result); 
    } 
    } 
} 

इसके अलावा पेट के रूप में सी # से ऊपर लिख और अपने कोड के लिए यह अनुकूल के बाद: एक के लिए String से

  1. बदलें bufStringBuilder साझा की है।
  2. फिर इसे कक्षा में लपेटें और केवल रिकर्सन में इंडियन पास करें, दूसरों को कक्षा सदस्य चर के रूप में रखें।
  3. फिर अंत में लूप में रिकर्सन चालू करें (संकेत: 3 नेस्टेड लूप, आंतरिक लूपों में से एक में पुनरावृत्तियों की संख्या बढ़ जाएगी)।

गैर पुनरावर्ती संस्करण के बारे में नोट मैं सोच रहा हूँ: यह प्रत्यावर्तन की तुलना में कम कुशल होगा, लेकिन क्या यह दिलचस्प और कोडिंग एक व्यायाम है के रूप में के योग्य बनाता है, यह breadth-first हो जाएगा, यह पुनरावर्ती संस्करण depth-first है, जबकि ।

2

मैंने यह धारणा बनाई है कि आप शायद प्रत्येक अंक को स्वयं के साथ-साथ सभी सामान्य पत्र मैपिंग्स का अनुवाद करना चाहते हैं, साथ ही 0 मैपिंग + पर मैपिंग करना चाहते हैं।

var map = new Dictionary<char, string>() 
{ 
    { '0', "+0"}, 
    { '1', "1" }, 
    { '2', "2ABC"}, 
    { '3', "3DEF"}, 
    { '4', "4GHI"}, 
    { '5', "5JKL"}, 
    { '6', "6MNO"}, 
    { '7', "7PQRS"}, 
    { '8', "8TUV"}, 
    { '9', "9WXYZ"}, 
}; 

मेरे permutate समारोह तो इस तरह दिखता है:

Func<IEnumerable<char>, IEnumerable<IEnumerable<char>>> permutate = null; 
permutate = cs => 
{ 
    var result = Enumerable.Empty<IEnumerable<char>>(); 
    if (cs.Any()) 
    { 
     result = map[cs.First()].Select(c => new [] { c }); 
     if (cs.Skip(1).Any()) 
     { 
      result = 
       from xs in result 
       from ys in permutate(cs.Skip(1)) 
       select xs.Concat(ys); 
     } 
    } 
    return result; 
}; 

यह है कि इसलिए मैं मैपिंग को संभालने के लिए इस शब्दकोश बनाया है।

आप इस तरह इसका इस्तेमाल कर सकते हैं:

var digits = "(08) 8234-5678" 
    .Where(x => char.IsDigit(x)); 

var results = 
    permutate(digits) 
     .Select(x => new string(x.ToArray())); 

परिणाम तार जहां प्रत्येक स्ट्रिंग इनपुट संख्या का क्रमपरिवर्तन है की एक सूची है।

यदि आप अंकों को अंक मैप करना नहीं चाहते हैं, तो उन्हें मूल शब्दकोश परिभाषा से बाहर ले जाएं, लेकिन आपको इसे काम करने के लिए 1 अंकों के लिए एक ही वर्ण रखना होगा।

मुझे बताएं कि यह आपके लिए काम करता है या नहीं।

0

यहाँ एक गैर पुनरावर्ती समाधान है, कि

  • एक संख्या को देखते हुए, के लिए यह
  • एक शब्द को देखते हुए पहला शब्द की गणना करता है, "वेतन वृद्धि" यह अगले शब्द को खोजने के लिए
public static class TelephoneFinder 
{ 
    static char[] firstDigits = new char[] 
        { '0', '1', 'A', 'D', 'G', 'J', 'M', 'P', 'T', 'W' }; 
    public static string First(string number) 
    { 
     char[] firstWord = new char[number.Length]; 
     for (int i = 0; i < number.Length; i++) 
     { 
      var c = number.Substring(i, 1); 
      firstWord[i] = firstDigits[int.Parse(c)]; 
     } 
     return new String(firstWord); 
    } 

    static Dictionary<char, char> rollovers = new Dictionary<char, char> { 
     { '1', '0' }, { '2', '1' }, { 'D', 'A' }, { 'G', 'D' }, { 'J', 'G' }, 
     { 'M', 'J' }, { 'P', 'M' }, { 'T', 'P' }, { 'W', 'T' }, { '[', 'W' } }; 
    public static string Next(string current) 
    { 
     char[] chars = current.ToCharArray(); 
     for (int i = chars.Length - 1; i >= 0; i--) 
     { 
      // Increment current character 
      chars[i] = (char)((int)chars[i] + 1); 

      if (rollovers.ContainsKey(chars[i])) 
       // Roll current character over 
       // Will then continue on to next character 
       chars[i] = rollovers[chars[i]]; 
      else 
       // Finish loop with current string 
       return new String(chars); 
     } 
     // Rolled everything over - end of list of words 
     return null; 
    } 
} 

उदाहरण के रूप में बुलाया गया

string word = TelephoneFinder.First("867"); 
while (!String.IsNullOrEmpty(word)) 
{ 
    Console.WriteLine(word); 
    word = TelephoneFinder.Next(word); 
} 

यह शायद कुछ साफ़ कर रही इस्तेमाल कर सकते हैं, लेकिन यह एक सामान्य गैर पुनरावर्ती समाधान है कि इसी तरह "पार उत्पाद" परिस्थितियों के लिए काम करने के लिए संशोधित किया जा सकता है।

0

मुझे खेद है हर कोई। यह मेरा पहला स्टैक ओवरफ़्लो पोस्ट था और मुझे एक ईमेल की उम्मीद थी जब मेरे प्रश्न पर एक उत्तर पोस्ट किया गया था लेकिन कभी नहीं मिला। मैंने अभी सोचा कि मेरा प्रश्न ढेर अतिप्रवाह के अस्थियों में निगल गया था।

डेवलपर्स का एक समूह जिसके साथ मैं काम करता हूं, यह लगभग 5 लाइनों में पाया गया। मुझे इस समय समाधान नहीं मिल रहा है, लेकिन मुझे लगता है कि यह इनिग्मैटीविटी पोस्ट करने के बहुत करीब था। मैं सकारात्मक हूं कि हमने क्रमपरिवर्तन का उपयोग किया। मैं उस समाधान की तलाश करूंगा जिसका हमने उपयोग किया था। सबको धन्यवाद।

संबंधित मुद्दे