Remove more than n consecutive vowels from input string

Unreadable, 1647 bytes

'"""""'""'""""""'"""'""""""'""'""'"""'""""""""""'"""""""""'"""""""""'""""""'"""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'"""""""'"""'"""""""""'""""""'"""'""""""""'""""""""'""""""""'""""""""'"""""""'"""'"""""""""'""""""'"""'""""""""'""""""""'""""""""'""""""""'"""""""'"""'"""""""""'""""""'"""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'"""""""'"""'"""""""""'""""""'"""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'"""""""'"""'"""""""""'""""""'"""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'"""""""'"""'"""""""""'""""""'"""'""""""""'""""""""'""""""""'""""""""'"""""""'"""'"""""""""'""""""'"""'""""""""'""""""""'""""""""'""""""""'"""""""'"""'"""""""""'""""""'"""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'"""""""'"""'"""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'"""""""'"""'""""""""'"""'"""'"""'"""'"""'"""'"""'"""'"""'"""'"""'"""""""""'""'""'""'""'""""""'""'"""'""""""""'"""""""'""'"""'"'"""""""'""'""'"""'""""""'""'"""'""'"""""""'""'"""'""""'"'"""""""'""'""'"""'""""""'""'"""'""""""""'"""

Explanation

This program is equivalent to pseudocode like this:

while (cp = (ch = read)) + 1 {
    (
        (cp -= 65) ?    // A
            (cp -= 4) ?     // E
                (cp -= 4) ?     // I
                    (cp -= 6) ?     // O
                        (cp -= 6) ?     // U
                            (cp -= 12) ?    // a
                                (cp -= 4) ?     // e
                                    (cp -= 4) ?     // i
                                        (cp -= 6) ?     // o
                                            (cp - 6) ?      // u
                                                0
                                            : 1
                                        : 1
                                    : 1
                                : 1
                            : 1
                        : 1
                    : 1
                : 1
            : 1
        : 1
    ) ? ((--vs)+4) ? print(ch) : (++vs) : {
        print(ch)
        vs = 0
    }
}

with the following variable assignments:

0   (unused)   (13 bytes)
1   cp         ( 4 bytes; occurs 20× in the code)
2   vs         ( 7 bytes; occurs  5× in the code)
3   ch         (10 bytes; occurs  3× in the code)

As you can see, I avoided variable slot 0 because 0 is such a long constant to write.

So we read each character and store the value in both cp and ch. We will modify cp but keep ch around so that we can print it if necessary. We successively subtract numbers 65, 4, 4, 6, etc. from cp to check if it’s each of the 10 possible vowel characters in ASCII (note the very last one doesn’t need to be an assignment).

vs always contains 3 less than the number of vowels still allowed to be printed. It starts out at 0, so 3 vowels can be printed. When it reaches -3, we stop printing vowels.

If we encounter a non-vowel (including the space), we execute print(ch) followed by vs = 0. As you have probably guessed, this resets the vowels counter.

If we encounter a vowel, we execute ((--vs)+4) ? print(ch) : (++vs). Let’s break this down:

  • decrement vs;
  • if the value is now -4, we’ve gone too far, so don’t print anything, but increment vs back to -3 so we will continue to refuse to print vowels;
  • otherwise, print the character.

Retina, 25 bytes

i`([aeiou]{3})[aeiou]+
$1

Try it online.

Fairly straightforward regex substitution. This also works for the same byte count:

Ri`(?<=[aeiou]{3})[aeiou]

JavaScript (ES6), 42

As an anonymous function

s=>s.replace(/[aeiou]+/gi,v=>v.slice(0,3))