Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Logic to decrease character values

I am working on a logic that decreases the value of an alphanumeric List<char>. For example, A10 becomes A9, BBA becomes BAZ, 123 becomes 122. And yes, if the value entered is the last one(like A or 0), then I should return -

An additional overhead is that there is a List<char> variable which is maintained by the user. It has characters which are to be skipped. For example, if the list contains A in it, the value GHB should become GGZ and not GHA.

The base of this logic is a very simple usage of decreasing the char but with these conditions, I am finding it very difficult.

My project is in Silverlight, the language is C#. Following is my code that I have been trying to do in the 3 methods:

    List<char> lstGetDecrName(List<char> lstVal)//entry point of the value that returns decreased value
    {
        List<char> lstTmp = lstVal;
        subCheckEmpty(ref lstTmp);
        switch (lstTmp.Count)
        {
            case 0:
                lstTmp.Add('-');
                return lstTmp;
            case 1:
                if (lstTmp[0] == '-')
                {
                    return lstTmp;
                }
                break;
            case 2:
                if (lstTmp[1] == '0')
                {
                    if (lstTmp[0] == '1')
                    {
                        lstTmp.Clear();
                        lstTmp.Add('9');
                        return lstTmp;
                    }
                    if (lstTmp[0] == 'A')
                    {
                        lstTmp.Clear();
                        lstTmp.Add('-');
                        return lstTmp;
                    }
                }
                if (lstTmp[1] == 'A')
                {
                    if (lstTmp[0] == 'A')
                    {
                        lstTmp.Clear();
                        lstTmp.Add('Z');
                        return lstTmp;
                    }
                }
                break;
        }
        return lstGetDecrValue(lstTmp,lstVal);
    }



    List<char> lstGetDecrValue(List<char> lstTmp,List<char> lstVal)
    {
        List<char> lstValue = new List<char>();
        switch (lstTmp.Last())
        {
            case 'A':
                lstValue = lstGetDecrTemp('Z', lstTmp, lstVal);
                break;
            case 'a':
                lstValue = lstGetDecrTemp('z', lstTmp, lstVal);
                break;
            case '0':
                lstValue = lstGetDecrTemp('9', lstTmp, lstVal);
                break;
            default:
                char tmp = (char)(lstTmp.Last() - 1);
                lstTmp.RemoveAt(lstTmp.Count - 1);
                lstTmp.Add(tmp);
                lstValue = lstTmp;
                break;
        }
        return lstValue;
    }






    List<char> lstGetDecrTemp(char chrTemp, List<char> lstTmp, List<char> lstVal)//shifting places eg unit to ten,etc.
    {
        if (lstTmp.Count == 1)
        {
            lstTmp.Clear();
            lstTmp.Add('-');
            return lstTmp;
        }
        lstTmp.RemoveAt(lstTmp.Count - 1);
        lstVal = lstGetDecrName(lstTmp);
        lstVal.Insert(lstVal.Count, chrTemp);
        return lstVal;
    }

I seriously need help for this. Please help me out crack through this.

like image 959
vaibhav Avatar asked Nov 03 '22 20:11

vaibhav


1 Answers

The problem you are trying to solve is actually how to decrement discreet sections of a sequence of characters, each with it's own counting system, where each section is separated by a change between Alpha and Numeric. The rest of the problem is easy once you identify this.

The skipping of unwanted characters is simply a matter of repeating the decrement if you get an unwanted character in the result.

One difficultly is the ambiguous definition of the sequences. e.g. what to do when you get down to say A00, what is next? "A" or "-". For the sake of argument I am assuming a practical implementation based loosely on Excel cell names (i.e. each section operates independently of the others).

The code below does 95% of what you wanted, however there is a bug in the exclusions code. e.g. "ABB" becomes "AAY". I feel the exclusions need to be applied at a higher level (e.g. repeat decrement until no character is in the exclusions list), but I don't have time to finish it now. Also it is resulting in a blank string when it counts down to nothing, rather than the "-" you wanted, but that is trivial to add at the end of the process.

Part 1 (divide the problem into sections):

public static string DecreaseName( string name, string exclusions )
{
    if (string.IsNullOrEmpty(name))
    {
        return name;
    }

    // Split the problem into sections (reverse order)
    List<StringBuilder> sections = new List<StringBuilder>();
    StringBuilder result = new StringBuilder(name.Length);
    bool isNumeric = char.IsNumber(name[0]);
    StringBuilder sb = new StringBuilder();
    sections.Add(sb);
    foreach (char c in name)
    {
        // If we change between alpha and number, start new string.
        if (char.IsNumber(c) != isNumeric)
        {
            isNumeric = char.IsNumber(c);
            sb = new StringBuilder();
            sections.Insert(0, sb);
        }
        sb.Append(c);
    }

    // Now process each section
    bool cascadeToNext = true;
    foreach (StringBuilder section in sections)
    {
        if (cascadeToNext)
        {
            result.Insert(0, DecrementString(section, exclusions, out cascadeToNext));
        }
        else
        {
            result.Insert(0, section);
        }
    }

    return result.ToString().Replace(" ", "");
}

Part2 (decrement a given string):

private static string DecrementString(StringBuilder section, string exclusions, out bool cascadeToNext)
{
    bool exclusionsExist = false;
    do
    {
        exclusionsExist = false;
        cascadeToNext = true;
        // Process characters in reverse
        for (int i = section.Length - 1; i >= 0 && cascadeToNext; i--)
        {
            char c = section[i];
            switch (c)
            {
                case 'A':
                    c = (i > 0) ? 'Z' : ' ';
                    cascadeToNext = (i > 0);
                    break;
                case 'a':
                    c = (i > 0) ? 'z' : ' ';
                    cascadeToNext = (i > 0);
                    break;
                case '0':
                    c = (i > 0) ? '9' : ' ';
                    cascadeToNext = (i > 0);
                    break;
                case ' ':
                    cascadeToNext = false;
                    break;
                default:
                    c = (char)(((int)c) - 1);
                    if (i == 0 && c == '0')
                    {
                        c = ' ';
                    }
                    cascadeToNext = false;
                    break;
            }
            section[i] = c;
            if (exclusions.Contains(c.ToString()))
            {
                exclusionsExist = true;
            }
        }
    } while (exclusionsExist);
    return section.ToString();
}

The dividing can of course be done more efficiently, just passing start and end indexes to the DecrementString, but this is easier to write & follow and not much slower in practical terms.

like image 159
Gone Coding Avatar answered Nov 15 '22 00:11

Gone Coding