title: Regex character count, but some count for three
body: <p>I'm trying to build a regular expression that places a limit on the input length, but not all characters count equal in this length. I'll put the rationale at the bottom of the question. As a simple example, let's limit the maximum length to 12 and allow only <code>a</code> and <code>b</code>, but <code>b</code> counts for 3 characters.</p>
  
  <p>Allowed are:</p>
  
  <ul>
  <li><code>aa</code> (anything less than 12 is fine).</li>
  <li><code>aaaaaaaaaaaa</code> (exactly 12 is fine).</li>
  <li><code>aaabaaab</code> (6 + 2 * 3 = 12, which is fine).</li>
  <li><code>abaaaaab</code> (still 6 + 2 * 3 = 12).</li>
  </ul>
  
  <p>Disallowed is:</p>
  
  <ul>
  <li><code>aaaaaaaaaaaaa</code> (13 <code>a</code>'s).</li>
  <li><code>bbbba</code> (1 + 4 * 3 = 13, which is too much).</li>
  <li><code>baaaaaaab</code> (7 + 2 * 3 = 13, which is too much).</li>
  </ul>
  
  <p>I've made an attempt that gets fairly close:</p>
  
  <pre><code>^(a{0,3}|b){0,4}$
  </code></pre>
  
  <p>This matches on up to 4 clusters that may consist of 0-3 <code>a</code>'s or one <code>b</code>.</p>
  
  <p>However, it fails to match on my last positive example: <code>abaaaaab</code>, because that forces the first cluster to be the single <code>a</code> at the beginning, consumes a second cluster for the <code>b</code>, then leaves only 2 more clusters for the rest, <code>aaaaab</code>, which is too long.</p>
  
  <h1>Constraints</h1>
  
  <ul>
  <li>Must run in JavaScript. This regex is supplied to Qt, which apparently uses JavaScript's syntax.</li>
  <li>Doesn't really need to be fast. In the end it'll only be applied to strings of up to 40 characters. I hope it validates within 50ms or so, but slightly slower is acceptable.</li>
  </ul>
  
  <h1>Rationale</h1>
  
  <p>Why do I need to do this with a regular expression?</p>
  
  <p>It's for a user interface in Qt via PyQt and QML. The user can type a name in a text field here for a profile. This profile name is url-encoded (special characters are replaced by %XX), and then saved on the user's file system. We encounter problems when the user types a lot of special characters, such as Chinese, which then encode to a very long file name. Turns out that at somewhere like 17 characters, this file name becomes too long for some file systems. The URL-encoding encodes as UTF-8, which has up to 4 bytes per character, resulting in up to 12 characters in the file name (as each of these gets percent-encoded).</p>
  
  <p>16 characters is too short for profile names. Even some of our default names exceed that. We need a variable limit based on these special characters.</p>
  
  <p>Qt normally allows you to specify a Validator to determine which values are acceptable in a text box. We tried implementing such a validator, but that resulted in a segfault upstream, due to a bug in PyQt. It can't seem to handle custom Validator implementations at the moment. However, PyQt also exposes three built-in validators. Two apply only to numbers. The third is a regex validator that allows you to put a regular expression that matches all valid strings. Hence the need for this regular expression.</p>