Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>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.</p> <p>The skipping of unwanted characters is simply a matter of repeating the decrement if you get an unwanted character in the result.</p> <p>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). </p> <p>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.</p> <h2>Part 1 (divide the problem into sections):</h2> <pre><code>public static string DecreaseName( string name, string exclusions ) { if (string.IsNullOrEmpty(name)) { return name; } // Split the problem into sections (reverse order) List&lt;StringBuilder&gt; sections = new List&lt;StringBuilder&gt;(); 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(" ", ""); } </code></pre> <h2>Part2 (decrement a given string):</h2> <pre><code>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 &gt;= 0 &amp;&amp; cascadeToNext; i--) { char c = section[i]; switch (c) { case 'A': c = (i &gt; 0) ? 'Z' : ' '; cascadeToNext = (i &gt; 0); break; case 'a': c = (i &gt; 0) ? 'z' : ' '; cascadeToNext = (i &gt; 0); break; case '0': c = (i &gt; 0) ? '9' : ' '; cascadeToNext = (i &gt; 0); break; case ' ': cascadeToNext = false; break; default: c = (char)(((int)c) - 1); if (i == 0 &amp;&amp; c == '0') { c = ' '; } cascadeToNext = false; break; } section[i] = c; if (exclusions.Contains(c.ToString())) { exclusionsExist = true; } } } while (exclusionsExist); return section.ToString(); } </code></pre> <p>The dividing can of course be done more efficiently, just passing start and end indexes to the DecrementString, but this is easier to write &amp; follow and not much slower in practical terms.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload