5

英数字 の値を減らすロジックに取り組んでいますList<char>。たとえば、A10A9になり、BBABAZになり、123122になります。はい、入力された値が最後の値(A0など)の場合は、 -を返す必要があります

追加のオーバーヘッドはList<char>、ユーザーによって維持される変数があることです。スキップする文字があります。たとえば、リストにAが含まれている場合、値GHBGHAではなくGGZになります。

このロジックの基本は、減らすという非常に単純な使用法ですcharが、これらの条件では、非常に難しいと感じています。

私のプロジェクトはSilverlightで、言語はC#です。以下は、3つの方法で実行しようとしているコードです。

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

私はこれについて真剣に助けが必要です。これをクラックするのを手伝ってください。

4

5 に答える 5

2

あなたが解決しようとしている問題は、実際には、文字のシーケンスの目立たないセクションをどのようにデクリメントするかであり、それぞれが独自のカウントシステムを備えており、各セクションはアルファと数値の間の変更によって分離されます。これを特定すれば、残りの問題は簡単です。

不要な文字をスキップするのは、結果に不要な文字が含まれている場合にデクリメントを繰り返すだけです。

難しいのは、シーケンスの定義があいまいなことです。たとえば、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

数値かどうかを確認し、数値のマイナス計算を行います。文字列の場合は、文字コードに変更してから、文字コードから1を引いた値に変更します。

于 2012-07-04T09:45:07.330 に答える
0

すべてのコードを記述せずに、これをどのように分解できるかについての提案を次に示します。

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 "-";
}

ここでの唯一の問題は、それが例えばないように減少A10するということです。私は実際にこれを自分で好みますが、余分なゼロを削除する最終パスを書くのは簡単なはずです。A09A9

もう少しパフォーマンスを上げるには、List<char>をハッシュセットに置き換えます。これにより、ルックアップ<char>が高速化されます。Contains

于 2012-07-04T09:57:16.357 に答える
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 に答える
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 に答える