Click here to Skip to main content
15,886,362 members
Articles / Programming Languages / C#

Solving Jumble Puzzles Using a Recursive Algorithm

Rate me:
Please Sign up or sign in to vote.
4.29/5 (3 votes)
8 Jul 2009CPOL6 min read 56.9K   1.3K   21  
Find all words that can be derived from a character string using recursion, LINQ, and COM
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

[assembly: CLSCompliant(true)]
namespace Unscramble
{
    class Permutations
    {
        private int itemLevel = -1;
        private int numOfItems;
        private int permCount;
        private int[] permutation = new int[0];
        private char[] inputCharSet;
        private List<string> permList = new List<string>();
        object missing = System.Reflection.Missing.Value;

        // Called directly w/o using directive to prevent ambiguity
        // with System.Windows.Forms.Application object
        Microsoft.Office.Interop.Word.Application wordApp =
            new Microsoft.Office.Interop.Word.Application();

        ProgressBar pgProgress = (ProgressBar)Form1
            .ActiveForm.Controls["pbProgress"];

        /// <summary>
        /// Convert input string to character array
        /// </summary>
        /// <param name="inputString">User input string</param>
        public void MakeCharArray(string inputString)
        {
            inputCharSet = inputString.ToCharArray();
            numOfItems = inputCharSet.Length;
            Array.Resize(ref permutation, numOfItems);
        }

        /// <summary>
        /// Recursive Algorithm Source:
        /// A. Bogomolny, Counting And Listing All Permutations 
        /// from Interactive Mathematics Miscellany and Puzzles
        /// http://www.cut-the-knot.org/do_you_know/AllPerm.shtml,
        /// Accessed 11 June 2009
        /// </summary>
        /// <param name="position"></param>
        public void Recursion(int position)
        {
            itemLevel++;
            permutation.SetValue(itemLevel, position);
            if(itemLevel == numOfItems)
            {
                AddPermutation(permutation);
            }
            else
            {
                for(int currentPosition = 0; currentPosition < numOfItems;
                    currentPosition++)
                {
                    if(permutation[currentPosition] == 0)
                    {
                        Recursion(currentPosition);
                    }
                }
            }
            itemLevel--;
            permutation.SetValue(0, position);
        }

        /// <summary>
        /// Code Source (AddItem()):
        /// A. Bogomolny, Counting And Listing All Permutations
        /// from Interactive Mathematics Miscellany and Puzzles
        /// http://www.cut-the-knot.org/do_you_know/AllPerm.shtml,
        /// Accessed 11 June 2009
        /// </summary>
        /// <param name="currentPermutation">A permutation</param>
        private void AddPermutation(int[] currentPermutation)
        {
            string tempPermString = "";
            foreach(int item in currentPermutation)
            {
                tempPermString += inputCharSet.GetValue(item - 1);
                // Build string permutation from position permutation
            }
            permList.Add(tempPermString);
            permCount++;
        }

        /// <summary>
        /// Call Microsoft Word 11.0 Object Library 
        /// to check spelling of each permutation 
        /// </summary>
        /// <param name="theWord">Permutation to check</param>
        /// <returns>Is it a word?</returns>
        private bool CheckTheSpelling(string theWord)
        {
            pgProgress.Increment(1);
            bool result = false;
            try
            {
                if(wordApp.CheckSpelling(theWord, ref missing,
                    ref missing, ref missing, ref missing,
                    ref missing, ref missing, ref missing,
                    ref missing, ref missing, ref missing,
                    ref missing, ref missing) == true)
                {
                    result = true;
                }
                else
                {
                    result = false;
                }
            }
            catch(Exception)
            {
                wordApp.Quit(ref missing, ref missing, ref missing);
            }
            return result;
        }

        /// <summary>
        /// Format list of permutation as string for output to UI
        /// </summary>
        /// <returns>Results to UI</returns>
        public string OutputPermutations()
        {
            //Count all
            int allPermCount = permList.Count();
            var permListTrue = permList.Distinct();
            //Count distinct
            int uniquePermCount = permListTrue.Count();
            pgProgress.Maximum = uniquePermCount;

            permListTrue = permListTrue
                .Where(perm => CheckTheSpelling(perm) == true)
                .OrderBy(perm => perm);
            var permListFalse = permList
                .Distinct()
                .Except(permListTrue)
                .OrderBy(perm => perm);

            //Count answers
            int answersFound = permListTrue.Count();

            StringBuilder tempDisplay = new StringBuilder();

            try
            {
                foreach(string permutation in permListTrue)
                {
                    tempDisplay.AppendLine(permutation + " (true)");
                }
                tempDisplay.AppendLine("-------------------");
                foreach(string permutation in permListFalse)
                {
                    tempDisplay.AppendLine(permutation + " (false)");
                }
                tempDisplay.AppendLine("-------------------");
                tempDisplay.AppendLine("Total Permutations: " +
                    allPermCount.ToString());
                tempDisplay.AppendLine("Unique Permutations: " +
                    uniquePermCount.ToString());
                tempDisplay.AppendLine("Words Found: " + answersFound);
            }
            catch(Exception ex)
            {
                return ex.ToString();
            }
            finally
            {
                wordApp.Quit(ref missing, ref missing, ref missing);
            }
            return tempDisplay.ToString();
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Paychex
United States United States
I am a senior software developer, architect, and project manager, specializing in .NET, JavaScript, Java, and database development, and build automation. I am currently a Lead Developer (.NET) / Developer IV for Paychex Enterprise Business Solutions. Paychex (PAYX) provides payroll, human resources, and benefits outsourcing and web-based solutions to business.

Prior to Paychex, I served as Lead Software Engineer, Operations Manager, and Technical Product Manager at Bio-Optronics. Bio-Optronics develops, deploys and operates information technology solutions to help healthcare professionals manage and optimize workflow to enhance quality, productivity, and patient and staff satisfaction and safety. Previously, I held positions of President, COO, Chief Technology Officer (CTO), and SVP of Technology for Lazer Incorporated. Lazer is a successful, digital imaging and Internet-based content management services provider.

Comments and Discussions