Re: Permuting beyond one collection



Think digital clock.

When the minute's number reaches nine, you set it back to zero and
increment the ten's number. If the ten's number goes back to 0,
increment the hour.

I wrote a generic method called CascadingRotation that performs this
action. This what I came up with:

public static IEnumerable<T[]> CascadingRotation<T>(params
IEnumerable<T>[] collections)
{
Debug.ArgumentNull(collections, "collections");
ArrayList<ArrayList<T>> lists = new
ArrayList<ArrayList<T>>();
foreach (IEnumerable<T> collection in collections)
{
Debug.ArgumentNull(collection, "collection");
ArrayList<T> list = new ArrayList<T>(collection);
Debug.LessThanN(list.Count, 1);
lists.Add(list);
}
int i = 0;
int k;
do
{
k = i;
ArrayList<T> tops = new ArrayList<T>();
for (int top = lists.Count - 1; top >= 0; --top)
{
int remainder;
k = System.Math.DivRem(k, lists[top].Count, out
remainder);
tops.Add(lists[top][remainder]);
}
if (k == 0)
{
Reverse<T>(tops.GetFirst(), tops.GetPast());
yield return tops.ToArray();
++i;
}
}
while (k == 0);
}

Its nice because it uses only one indexer, namely i, and uses modulus
properties to get the indexes of each column. It is fast and light on
memory.

Here is the final result of my code:

class Program
{
public static void Main()
{
using (OrderedSet<string> words = getWords())
{
while (true)
{
string number = Console.In.ReadLine();
foreach (string permutation in
getAllPermutations(number))
{
if (words.Contains(permutation))
{
Console.Out.WriteLine(permutation);
}
}
}
}
}

private static OrderedSet<string> getWords()
{
OrderedSet<string> words = new
OrderedSet<string>(Functional.Less<string>);
using (StreamReader reader = new
StreamReader(File.OpenRead(@"E:\Repertoire\data\words.txt")))
{
string line;
while ((line = reader.ReadLine()) != null)
{
words.Add(line.Trim().ToLower());
}
}
return words;
}

private static Regex onlyNumbers = new Regex(@"[2-9]+",
RegexOptions.Compiled);
private static char[][] values =
{
new char[]{ 'a', 'b', 'c' },
new char[]{ 'd', 'e', 'f' },
new char[]{ 'g', 'h', 'i' },
new char[]{ 'j', 'k', 'l' },
new char[]{ 'm', 'n', 'o' },
new char[]{ 'p', 'q', 'r', 's' },
new char[]{ 't', 'u', 'v' },
new char[]{ 'w', 'x', 'y', 'z' }
};

private static IEnumerable<string> getAllPermutations(string
number)
{
ArrayList<string> options = new ArrayList<string>();
if (onlyNumbers.IsMatch(number))
{
ArrayList<char[]> possibleValues = new
ArrayList<char[]>();
foreach (char c in number)
{
possibleValues.Add(values[(int)c - '2']);
}

foreach (char[] option in
Algorithms.CascadingRotation<char>(possibleValues.ToArray()))
{
yield return new String(option);
}
}
}
}
.



Relevant Pages

  • Improve an IEnumerable function
    ... code (don't pay attention to the int factor): ... MyCSharp2Class myClass = new MyCSharp2Class ... foreach (KeyValuePair<int, string> akp in myClass.GetValues()) ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: DataGridView.GetClipboardContent does not call ParseFormattedValue
    ... Does anyone know how to force it do this, or how to implement GetClipboardContent so that it does. ... Dictionary<int, string> rt, rc; ... foreach ... foreach (int i in tabs.Keys) ...
    (microsoft.public.dotnet.framework.windowsforms)
  • Re: String to int & back again
    ... >I am looking to increase the value of myString by 10. ... >is a string I can't really increment it..., ... for String> int and int> String. ...
    (comp.lang.java.help)
  • Re: How to get a part of a string using reg exp
    ... Get the substring, parse it to an int, increment it, then turn it back into ... a string and put it back in. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: How to get a part of a string using reg exp
    ... But we do not know the length of the string, ... We only want to increment the number embeded inside the string. ... public string Increment ... int i = int.Parse; ...
    (microsoft.public.dotnet.languages.csharp)