Can anyone spot the bug in my Damerau-Levenshtein Distance implementation?
<p>I've got a funky bug that's driving me nuts.  Can anyone help me find it?  Try calling the function with two words that differ only by a missing last character ("garble" vs "garbl").  The function is returning 0 instead of the expected 1.  It's supposed to return 1, right?</p>

<p>I've tried fiddling with the array bounds but that's only causing <code>IndexOutOfRangeExceptions</code>.</p>

<pre><code>public static class FuzzyStringMatcher
{
    private const int DELETION = 0;
    private const int INSERTION = 1;
    private const int SUBSTITUTION = 2;
    private const int TRANSPOSITION = 3;

    private const int COST_OF_DELETION = 1;
    private const int COST_OF_INSERTION = 1;
    private const int COST_OF_TRANSPOSITION = 1;
    private const int COST_OF_SUBSTITUTION = 1;

    public static int Compute_DamerauLevenshtein_Distance(string a, string b)
    {
        int[,] rows = new int[a.Length + 1, b.Length + 1];
        int cost_ratio;
        int[] calculations = new int[4];

        //
        // Init the array
        //
        for (int i = 0; i &lt; rows.GetUpperBound(0); i++)
            rows[i, 0] = i;

        for (int i = 0; i &lt; rows.GetUpperBound(1); i++)
            rows[0, i] = i;


        for (int aidx = 1; aidx &lt; rows.GetUpperBound(0); aidx++)
        {
            for (int bidx = 1; bidx &lt; rows.GetUpperBound(1); bidx++)
            {
                if (a[aidx - 1] == b[bidx - 1])
                    cost_ratio = 0;
                else
                    cost_ratio = 1;

                calculations[DELETION] = rows[aidx - 1, bidx] + COST_OF_DELETION;
                calculations[INSERTION] = rows[aidx, bidx - 1] + COST_OF_INSERTION;
                calculations[SUBSTITUTION] = rows[aidx - 1, bidx - 1] + cost_ratio * COST_OF_SUBSTITUTION;
                calculations[TRANSPOSITION] = int.MaxValue;

                if (aidx &gt; 1 &amp;&amp; bidx &gt; 1 &amp;&amp; a[aidx] == b[bidx - 1] &amp;&amp; a[aidx - 1] == b[bidx])
                    calculations[TRANSPOSITION] = rows[aidx - 2, bidx - 2] + cost_ratio * COST_OF_TRANSPOSITION;

                rows[aidx, bidx] = calculations.Min();
            }
        }

        int score = rows[rows.GetUpperBound(0) - 1, rows.GetUpperBound(1) - 1];
        if (a.Contains(b) || b.Contains(a))
            score = score / 2;
        return score;
    }
}
</code></pre>

<p>My implementation is based off the algorithm given in the Wikipedia page on <a href="http://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance" rel="nofollow">Damerau-Levenshtein-Distance</a></p>
