5

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.

4

5 回答 5

2

您要解决的问题实际上是如何减少字符序列的离散部分,每个部分都有自己的计数系统,其中每个部分由 Alpha 和 Numeric 之间的变化分隔。一旦你确定了这一点,剩下的问题就很容易了。

如果您在结果中得到不需要的字符,则跳过不需要的字符只是重复递减的问题。

一个困难是序列的模糊定义。例如,当你下定决心要说 A00 时该怎么办,下一步是什么?“A”或“-”。为了论证,我假设一个基于 Excel 单元名称的实际实现(即每个部分独立于其他部分运行)。

下面的代码完成了您想要的 95%,但是排除代码中有一个错误。例如“ABB”变成“AAY”。我觉得需要在更高级别应用排除项(例如重复递减直到排除列表中没有字符),但我现在没有时间完成它。此外,当它倒计时到零时,它会产生一个空白字符串,而不是你想要的“-”,但这在过程结束时添加是微不足道的。

第 1 部分(将问题分成多个部分):

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(递减一个给定的字符串):

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();
}

当然,划分可以更有效地完成,只需将开始和结束索引传递给 DecrementString,但这更容易编写和遵循,并且实际上不会慢很多。

于 2012-07-04T10:49:02.463 回答
0

Without writing all your code for you, here's a suggestion as to how you can break this down:

char DecrementAlphaNumericChar(char input, out bool hadToWrap)
{
    if (input == 'A')
    {
        hadToWrap = true;
        return 'Z';
    }
    else if (input == '0')
    {
        hadToWrap = true;
        return '9';
    }
    else if ((input > 'A' && input <= 'Z') || (input > '0' && input <= '9'))
    {
        hadToWrap = false;
        return (char)((int)input - 1);
    }
    throw new ArgumentException(
        "Characters must be digits or capital letters",
        "input");
}

char DecrementAvoidingProhibited(
    char input, List<char> prohibited, out bool hadToWrap)
{
    var potential = DecrementAlphaNumericChar(input, out hadToWrap);
    while (prohibited.Contains(potential))
    {
        bool temp;
        potential = DecrementAlphaNumericChar(potential, out temp);
        if (potential == input)
        {
            throw new ArgumentException(
                "A whole class of characters was prohibited",
                "prohibited");
        }
        hadToWrap |= temp;
    }
    return potential;
}

string DecrementString(string input, List<char> prohibited)
{
    char[] chrs = input.ToCharArray();
    for (int i = chrs.Length - 1; i >= 0; i--)
    {
        bool wrapped;
        chrs[i] = DecrementAvoidingProhibited(
                      chrs[i], prohibited, out wrapped);
        if (!wrapped)
            return new string(chrs);
    }
    return "-";
}

The only issue here is that it will reduce e.g. A10 to A09 not A9. I actually prefer this myself, but it should be simple to write a final pass that removes the extra zeroes.

For a little more performance, replace the List<char>s with Hashset<char>s, they should allow a faster Contains lookup.

于 2012-07-04T09:57:16.357 回答
0

我通过其他一些解决方法找到了我自己的答案的解决方案。

调用函数:

    MyFunction()
    {
        //stuff I do before
        strValue = lstGetDecrName(strValue.ToList());//decrease value here
        if (strValue.Contains('-'))
        {
            strValue = "-";
        }
        //stuff I do after
    }

总共有4个功能。2个主要功能和2个辅助功能。

    List<char> lstGetDecrName(List<char> lstVal)//entry point, returns decreased value
    {
        if (lstVal.Contains('-'))
        {
            return "-".ToList();
        }
        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;
        }

        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);
                subCheckEmpty(ref lstTmp);
                lstValue = lstTmp;
                break;
        }
        lstGetDecrSkipValue(lstValue);
        return lstValue;

    }


    List<char> lstGetDecrSkipValue(List<char> lstValue)
    {
        bool blnSkip = false;
        foreach (char tmpChar in lstValue)
        {
            if (lstChars.Contains(tmpChar))
            {
                blnSkip = true;
                break;
            }
        }
        if (blnSkip)
        {
            lstValue = lstGetDecrName(lstValue);
        }
        return lstValue;
    }


    void subCheckEmpty(ref List<char> lstTmp)
    {
        bool blnFirst = true;
        int i = -1;
        foreach (char tmpChar in lstTmp)
        {
            if (char.IsDigit(tmpChar) && blnFirst)
            {
                i = tmpChar == '0' ? lstTmp.IndexOf(tmpChar) : -1;
                if (tmpChar == '0')
                {
                    i = lstTmp.IndexOf(tmpChar);
                }
                blnFirst = false;
            }
        }
        if (!blnFirst && i != -1)
        {
            lstTmp.RemoveAt(i);
            subCheckEmpty(ref lstTmp);
        }
    }


    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);
        subCheckEmpty(ref lstVal);
        return lstVal;
    }
于 2012-07-05T10:11:18.350 回答
0

检查它是否是数字,如果是,则对数字进行减法运算,如果是字符串,则将其更改为字符代码,然后将字符代码减 1

于 2012-07-04T09:45:07.330 回答
0

昨天我一直在想这个,所以这里有一个想法。请注意,这只是伪代码,未经测试,但我认为这个想法是有效的并且应该可以工作(进行一些修改)。

要点是直接定义你的“字母表”,并指定其中哪些字符是非法的,应该跳过,然后使用这个字母表中的位置列表或数组来定义你开始的单词。

我现在不能再花时间在这上面了,但是如果你决定使用它并让它工作,请告诉我!

string[] alphabet = {a, b, c, d, e};
string[] illegal = {c, d};


public string ReduceString(string s){
            // Create a list of the alphabet-positions for each letter:
    int[] positionList = s.getCharsAsPosNrsInAlphabet();
    int[] reducedPositionList = ReduceChar(positionList, positionList.length);

    string result = "";
    foreach(int pos in reducedPositionList){
        result += alphabet[pos];
    }

    return result;
}


public string ReduceChar(string[] positionList, posToReduce){
    int reducedCharPosition = ReduceToNextLegalChar(positionList[posToReduce]);
    // put reduced char back in place:
    positionList[posToReduce] = reducedCharPosition; 

    if(reducedCharPosition < 0){
        if(posToReduce <= 0){
            // Reached the end, reduced everything, return empty array!:
            return new string[](); 
        }
        // move to back of alphabet again (ie, like the 9 in "11 - 2 = 09"):
        reducedCharPosition += alphabet.length;     
        // Recur and reduce next position (ie, like the 0 in "11 - 2 = 09"):
        return ReduceChar(positionList, posToReduce-1); 
    }

    return positionList;
}


public int ReduceToNextLegalChar(int pos){
    int nextPos = pos--;
    return (isLegalChar(nextPos) ? nextPos : ReduceToNextLegalChar(nextPos));
}


public boolean IsLegalChar(int pos){
        return (! illegal.contains(alphabet[pos]));
}
enter code here
于 2012-07-05T06:23:47.340 回答