Home Generate range between two strings [AA] -> [CD] or [CCC] -> [DMK]
Reply: 2

Generate range between two strings [AA] -> [CD] or [CCC] -> [DMK]

PyQL
1#
PyQL Published in 2017-12-07 21:10:42Z

I want to generate a sequence of strings between two groups that can be either 1 letter [A] -> [F] , 2 letters such as [AA] -> [CD] or any other length like 3 or 4 letters using c#.

For example I can specify the start and end values, and it will generate the sequence.

From [AA] to [CD] should generate

AA
AB
AC
AD

BA
BB
BC
BD

CA
CB
CC
CD

I tried to utilize base-26 algorithm to generate the required sequence but failed to get the required output.

string from ="AA";
string to = "CD";
IEnumerable<string> mysequence = Enumerable.Range(ConvertNumber(from), ConvertNumber(to) - ConvertNumber(from)).Select(ConvertAlpha).ToList();

public static string ConvertAlpha(int value)
{
    const int a = (int)'A';
    value = value - 1;
    var returnValue = new StringBuilder();
    while (value > -1)
    {
        var remainder = value % 26;
        returnValue.Insert(0, (char)(a + remainder));
        value = value / 26 - 1;
    }
    return returnValue.ToString();
}

public static int ConvertNumber(string value)
{
    const int a = (int)'A' - 1;
    int returnValue = 0;
    foreach (var character in value.ToUpper())
    {
        returnValue *= 26;
        returnValue += (int)character - a;
    }
    return returnValue;
}
CalC
2#
CalC Reply to 2017-12-07 22:15:51Z

Using recursion (but with brute-force rather than elegance):

static void Main(string[] args)
{
    string fromStr = "AAA";
    string toStr = "CDE";
    List<string> outputList = new List<string>();

    BuildSequence(fromStr, toStr, outputList);

    outputList.ForEach(s => { Console.WriteLine(s); });
    Console.ReadLine();
}

private static void BuildSequence(
    string fromStr,
    string toStr,
    List<string> outputList,
    int index = 0,
    string prev = "")
{
    IEnumerable<string> newStrList = Enumerable
        .Range(fromStr[index], toStr[index] - fromStr[index] + 1)
        .Select(c => String.Concat(prev, (char)c));

    index += 1;

    if (index < fromStr.Length)
    {
        foreach (string newStr in newStrList)
        {
            BuildSequence(fromStr, toStr, outputList, index, newStr);
        }
    }
    else
    {
        outputList.AddRange(newStrList);
    }
}
Jim Mischel
3#
Jim Mischel Reply to 2017-12-08 10:15:55Z

The problem you describe is harder than just converting a base-26 representation to an integer, doing some calculation, and then converting back. Your alpha strings aren't necessarily base-26. For example, you say that given AA and CD, you want to generate

AA, AB, AC, AD
BA, BB, BC, BD
CA, CB, CC, CD

What you really have is a base-4 system that uses the characters A, B, C, and D to represent the numbers 0, 1, 2, and 3. What you're saying here is that you want to generate all the 2-digit, base-4 numbers from 00 through 33.

Given CCC => DMK, it's a base-11 system using digits C through M. It's unclear from your description whether you want:

CCC, CCD, CCE ... CCK
CDC, CDD, CDE ... CDK
...

Or if you want

CCC, CCD, CCE ... CCM
CDC, CDD, CDE ... CDM
...

If you want the former, then each digit position is a different base, and things get even more complicated.

How you define things changes how you would write the code to generate the values.

Regardless or how you want to interpret your alpha values, it's clear that your base-26 conversion functions are incorrect.

Your conversion from int to string has a few errors. In particular, subtracting 1 from the value is going to give you trouble. You can see that if you were to pass 0 to the function. The result would be an empty string.

Here's a correct function:

static string ConvertToBase26(int value)
{
    const int a = (int)'A';
    var result = new StringBuilder();
    do
    {
        var remainder = value % 26;
        value /= 26;
        result.Insert(0, (char)(a + remainder);
    } while (value > 0);
    return result.ToString();
}

Your conversion from base26 to integer has similar errors, due to subtracting 1 from things. Remember, A acts like 0. The corrected function:

static int ConvertFromBase26(string value)
{
    const int a = (int)'A';
    int result = 0;
    foreach (var c in value.ToUpper())
    {
        result = (result * 26) + (c - a);
    }
    return result;
}

I recommend renaming your base conversion functions. Your ConvertAlpha function converts an integer to a base-26 string. That's not at all clear in the name, as one could misconstrue "ConvertAlpha" to mean "ConvertFromAlpha". I would recommend ConvertToBase26 and ConvertFromBase26, which are much more explicit and unambiguous.

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.305168 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO