g | x | w | all
Bytes Lang Time Link
020Vim250929T174519ZAaroneou
044Dyalog APL250925T170104ZAaron
nanRuby160926T025233ZJordan
018Japt180523T231023ZBubbler
045Jq 1.5171015T015658Zjq170727
023Cinnamon Gum160926T155837Za spaghe
066Lua160927T200752ZEgor Skr
072JavaScript ES6160926T013549ZETHprodu
108Haskell160927T235917ZLaikoni
065Lithp160927T114827ZAndrakis
030MATL160926T012410ZSuever
139Python 2160927T014822ZQuelklef
095PHP160926T162322ZJör
022Jelly160926T160037ZJonathan
039Perl 5160926T163351Zmsh210
076PowerShell v2+160926T142410ZAdmBorkB
035Retina160926T074846ZMartin E

Vim, 23 20 bytes

-3 bytes thanks to @H.PWiz

jDv2?[aeiou]\+
p`<dN­⁡​‎‎⁡⁠⁡‏⁠‎⁡⁠⁢‏‏​⁡⁠⁡‌⁢​‎‎⁡⁠⁣‏‏​⁡⁠⁡‌⁣​‎‎⁡⁠⁤‏⁠‎⁡⁠⁢⁡‏⁠‎⁡⁠⁢⁢‏⁠‎⁡⁠⁢⁣‏⁠‎⁡⁠⁢⁤‏⁠‎⁡⁠⁣⁡‏⁠‎⁡⁠⁣⁢‏⁠‎⁡⁠⁣⁣‏⁠‎⁡⁠⁣⁤‏⁠‎⁡⁠⁤⁡‏⁠‎⁡⁠⁤⁢‏‏​⁡⁠⁡‌⁤​‎‎⁢⁠⁡‏⁠‏​⁡⁠⁡‌⁢⁡​‎‎⁢⁠⁢‏⁠‎⁢⁠⁣‏‏​⁡⁠⁡‌⁢⁢​‎‎⁢⁠⁤‏⁠‎⁢⁠⁢⁡‏‏​⁡⁠⁡‌­

jD              # ‎⁡Move to the second word and delete it
  v             # ‎⁢Select from the end of the first word...
   2?[aeiou]\+  # ‎⁣...to the start of the penultimate vowel group (or just the one if there's just the one)...
p               # ‎⁤Overwrite selection with the previously deleted second word
 `<             # ‎⁢⁡Jump to the start of the previously selected section (now the start of the second word)
   dN           # ‎⁢⁢Delete from the start of the second word to before the first vowel group
💎

Created with the help of Luminespire.

Try it online!

Forget just being competitive, it's rare when Vim beats Jelly. It's not winning, but just ignore that part.

Dyalog APL, 44 bytes

Takes the two words as one left and one right arg

{(⍺↑⍨¯1+(2⊃2⍴⌽)⍸2</0,⍺∊v),⍵/⍨×+\⍵∊v←'aeiou'}­⁡​‎‎⁡⁠⁣⁡⁣‏⁠‎⁡⁠⁣⁡⁤‏⁠‎⁡⁠⁣⁢⁡‏⁠‎⁡⁠⁣⁢⁢‏⁠‎⁡⁠⁣⁢⁣‏⁠‎⁡⁠⁣⁢⁤‏⁠‎⁡⁠⁣⁣⁡‏⁠‎⁡⁠⁣⁣⁢‏⁠‎⁡⁠⁣⁣⁣‏‏​⁡⁠⁡‌⁢​‎‎⁡⁠⁣⁡⁡‏⁠‎⁡⁠⁣⁡⁢‏‏​⁡⁠⁡‌⁣​‎‎⁡⁠⁢⁤⁣‏⁠‎⁡⁠⁢⁤⁤‏‏​⁡⁠⁡‌⁤​‎‎⁡⁠⁢⁤⁢‏‏​⁡⁠⁡‌⁢⁡​‎‎⁡⁠⁢⁣⁣‏⁠‎⁡⁠⁢⁣⁤‏⁠‎⁡⁠⁢⁤⁡‏‏​⁡⁠⁡‌⁢⁢​‎‎⁡⁠⁢‏⁠‎⁡⁠⁢⁣⁡‏⁠‎⁡⁠⁢⁣⁢‏‏​⁡⁠⁡‌⁢⁣​‎‎⁡⁠⁢⁢⁢‏⁠‎⁡⁠⁢⁢⁣‏⁠‎⁡⁠⁢⁢⁤‏‏​⁡⁠⁡‌⁢⁤​‎‎⁡⁠⁢⁡⁤‏⁠‎⁡⁠⁢⁢⁡‏‏​⁡⁠⁡‌⁣⁡​‎‎⁡⁠⁢⁡⁡‏⁠⁠‎⁡⁠⁢⁡⁣‏‏​⁡⁠⁡‌⁣⁢​‎‎⁡⁠⁢⁡⁢‏‏​⁡⁠⁡‌⁣⁣​‎‎⁡⁠⁤⁤‏‏​⁡⁠⁡‌⁣⁤​‎‎⁡⁠⁣⁡‏⁠‎⁡⁠⁤⁣‏‏​⁡⁠⁡‌⁤⁡​‎‎⁡⁠⁤⁢‏‏​⁡⁠⁡‌⁤⁢​‎‎⁡⁠⁣⁤‏⁠‎⁡⁠⁤⁡‏‏​⁡⁠⁡‌⁤⁣​‎‎⁡⁠⁣⁢‏⁠‎⁡⁠⁣⁣‏‏​⁡⁠⁡‌⁤⁤​‎‎⁡⁠⁢⁢‏⁠‎⁡⁠⁢⁣‏⁠‎⁡⁠⁢⁤‏‏​⁡⁠⁡‌⁢⁡⁡​‎‎⁡⁠⁣‏⁠‎⁡⁠⁤‏⁠‎⁡⁠⁢⁡‏‏​⁡⁠⁡‌­
                                  v←'aeiou'   # ‎⁡Save the (v)owels
                                ⍵∊            # ‎⁢Find where they appear in the right arg
                              +\              # ‎⁣Sum-scan
                             ×                # ‎⁤Direction (meaning, zeroes stay zero, everything else becomes 1)
                          ⍵/⍨                 # ‎⁢⁡and select those from the right arg
                                              # ‎⁢⁡This will skip over only the initial consonants as the sum-scan starts to add up once we hit the initial vowel 
 (                      ),                    # ‎⁢⁢Concat with
                     ⍺∊v                      # ‎⁢⁣Find the vowels in the left arg
                   0,                         # ‎⁢⁤Prepend a zero
                2 /                           # ‎⁣⁡Find for every pair
                 <                            # ‎⁣⁢  where the left is smaller than the right
                                              # ‎⁣⁢  This gives the start of each group of vowels
               ⍸                              # ‎⁣⁣Get the indices of these locations
        (     )                               # ‎⁣⁤Pick the second to last (or the only one) by
             ⌽                                # ‎⁤⁡  Reverse the vector
           2⍴                                 # ‎⁤⁢  take 2 entries (or the only entry twice)
         2⊃                                   # ‎⁤⁣  and grab the second entry
     ¯1+                                      # ‎⁤⁤Subtract one to backup to the previous consonant
  ⍺↑⍨                                         # ‎⁢⁡⁡Take that many from the left arg
💎

Created with the help of Luminespire.

Ruby, 44 43 40 + 1 = 41 bytes

+1 byte for -p flag. Takes space-separated input on STDIN.
-1 byte thanks to Martin Ender
-2 bytes thanks to histocrat

sub /([aeiou]+([^aeiou]*)){,2} \g<2>/,""

Try it online!

GNU sed, 39 37 + 1 = 38 bytes

+1 byte for -E flag. Takes space-separated input on STDIN.
-1 byte thanks to Martin Ender

s/([aeiou]+[^aeiou]*){,2} [^aeiou]*//

Try it online!

Not posting this as a separate answer because it is literally the same solution.

Japt, 18 bytes

r/\v+\V*){1,2} \V*

Try it online!

Direct port of short JS solution which is in turn the port of Jordan's Ruby solution.

How it works

Ur/\v+\V*){1,2} \V*/

Ur    Replace on the input...
/\v+\V*){1,2} \V*/  this regex with empty string.
      \v == [AEIOUaeiou], \V == [^AEIOUaeiou], `g` flag is on by default in Japt
      so the uncompressed regex is roughly /([aeiou]+[^aeiou]*){1,2} [^aeiou]*/g.

Jq 1.5, 45 bytes

gsub("([aeiou]+[^aeiou]*){1,2} [^aeiou]*";"")

Nothing special, just a port of msh210's perl solution to jq's PCRE.

Try it online!

Cinnamon Gum, 23 bytes

0000000: 64d3 884e 4ccd cc2f 8dd5 8e8e 8330 b434  d..NL../.....0.4
0000010: b108 d92b c0d9 00                        ...+...

Try it online.

Explanation

This decompresses to d([aeiou]+[^aeiou]*)([aeiou]+[^aeiou]*)? [^aeiou]*, which deletes anything matching that regex. (Note that Jordan's golfier d([aeiou]+[^aeiou]*){,2} [^aeiou]* compresses to 24 bytes due to the lack of repeated elements to compress.)

Lua, 66 bytes

$ cat merge.lua
print(((...):gsub(("[]+[^]*[]*[^]*+[^]*"):gsub("]","aeiou]"),"")))
$ lua merge.lua brad+angelina
brangelina
$ lua merge.lua programming+puzzle
progruzzle

JavaScript (ES6), 81 73 72 bytes

Saved 8 bytes thanks to @Jordan, 1 thanks to @DavidConrad

a=>b=>a.match(/.*?(?=(?:[aeiou]+[^aeiou]*){1,2}$)/)+b.match(/[aeiou].*/)

Even though .match returns an array, array+array returns a string with the contents of the arrays concatenated (i.e. [0]+[1] returns "01").

Test snippet

f=a=>b=>console.log(a,"+",b,"=",a.match(/.*?(?=(?:[aeiou]+[^aeiou]*){1,2}$)/)+b.match(/[aeiou].*/))
f("brad")("angelina")
f("britain")("exit")
f("ben")("jennifer")
f("brangelina")("exit")
f("bill")("hillary")
f("angelina")("brad")
f("programming")("puzzle")
f("code")("golf")
f("progruzzle")("colf")
f("out")("go")
<input id=A value="super">
<input id=B value="chafouin">
<button onclick="f(A.value)(B.value)">Run</button>

Jordan's excellent Ruby solution would be 53 bytes in JS:

x=>x.replace(/([aeiou]+[^aeiou]*){1,2} [^aeiou]*/,"")

Haskell, 111 108 bytes

v x=elem x"aeiou"
d=dropWhile
e=d v
k=d$not.v
r=reverse
f a|c<-e.k.e.k$a,""/=c=c|1<3=e.k$a
a!b=(r.f.r)a++k b

This non-regex solution turned out longer than expected. Ideone it anyway.

Lithp, 65 bytes

#X::((replace X (regex "([aeiou]+[^aeiou]*){1,2} [^aeiou]*") ""))

This is basically a port of the JavaScript answer above, in my Lisp-ish functional programming language.

Example usage:

(
    % Note, you can define this as a function, or assign it to a variable
    % and use the call function instead.
    (def f #X::((replace X (regex "([aeiou]+[^aeiou]*){1,2} [^aeiou]*") "")))
    (print (f "programming puzzle"))
)

No online interpreter yet. I'll provide one soon. It won't be difficult, my language is written in JavaScript.

Instead, this puzzle solution is implemented as a working example for my language. It can be run with the following command:

node run.js l_src/progruzzle-colf.lithp

MATL, 31 30 bytes

t13Y2XJmFwhdl=fql_):)itJmYsg)h

Try it Online

Explanation

t       % Implicitly grab the input and duplicate it
13Y2    % Push the string literal 'aeiouAEIOU'
XJ      % Store this in clipboard J for later use
m       % Check which characters from the input are vowels (true for vowel)
Fwh     % Prepend FALSE to this logical array
dl=     % Compute the difference and find where we went from not-vowel to vowel
f       % Find the indices of these transitions
q       % Subtract 1 to get the location of the last consonant in each transition
l_)     % Get the next-to-last one of these
:)      % Grab the first string up to this location

% Now for the second component!

it      % Explicitly grab the input and duplicate
J       % Retrieve the string literal 'aeiouAEIOU' from clipboard J
m       % Find where the vowels are (true for vowel)
Ys      % Compute the cumulative sum along the array. The result will be 0
        % for all characters before the first vowel and non-zero after
g)      % Convert to logical and use this as an index so any characters
        % after the first value are retrieved

% Now to combine them

h       % Horizontally concatenate the first and second pieces together
        % Implicitly display the result

Python 2, 139 bytes

n=lambda a,b:a[:a.index(([l for l in[[l,"!"][i!=0and a[i-1]in v]for i,l in enumerate(a)]if l in v]*2)[-2])]+b[sorted([(b+v).index(c)for c in v])[0]:]

This one was hard.

Check it out on repl.it

PHP, 95 Bytes

$t="aeiou]";echo($p=preg_filter)("#([$t+[^$t*){1,2}$#","",$argv[1]).$p("#^[^$t*#","",$argv[2]);

with preg_match instead of preg_filter 110 Bytes

$t="aeiou]";($p=preg_match)("#(.*?)([$t+[^$t*){1,2}$#",$argv[1],$m);$p("#[$t.*#",$argv[2],$n);echo$m[1].$n[0];

Jelly, 23 22 bytes

eۯcT
ǵḟ‘-ị’
Ç⁸ḣ⁹ÑḢ⁹ṫ

TryItOnline

How?

eۯcT    - Link 1, vowel indexes: s   e.g. "colouring"
  Øc     - yield vowels, "AEIOUaeiou"
e€       - in for each                     [0,1,0,1,1,0,1,0,0]
    T    - truthy indexes (1-based)        [2,4,5,7]

ǵḟ‘-ị’  - Link 2, n-1th or only vowel group index start - 1: s
 µ       - monadic chain separation
Ç        - call last link (1) as a monad   [2,4,5,7]
   ‘     - increment                       [3,5,6,8]
  ḟ      - filter out                      [2,4,7]
    -    - -1
     ị   - index value                     [4]
               (Jelly is 1-based and has modular indexing,
                so the last but one item is at index -1,
                and when there is only 1 item in the list it is also at index -1)
      ’  - decrement                       [3]

Ç⁸ḣ⁹ÑḢ⁹ṫ - Main link: a, b                      e.g. "colouring", "pencils"
Ç        - call last link (2) as a monad with a      [3]
 ⁸       - link's left argument, a
  ḣ      - head a[:y]                                "col"
   ⁹  ⁹  - link's right argument, b
    Ñ    - call next link (1) as a monad                          [2,5]
     Ḣ   - pop head                                               [2]
       ṫ - tail b[y-1:]                                           "encils"
         - implicit print                            "colencils"

Perl 5, 39 bytes

38, plus 1 for -pe instead of -e

s/([aeiou]+[^aeiou]*){1,2} [^aeiou]*//

Hat tip.

PowerShell v2+, 76 bytes

param($n,$m)($n-replace'([aeiou]+[^aeiou]*){1,2}$')+($m-replace'^[^aeiou]*')

Apparently this is a popular regex ... ;-)

Uses the -replace operator to pull off the appropriate pieces, then string-concatenates the results together. Adds on a $ to the first to ensure we pull the end of the string, and adds a ^ to the second to ensure we pull off the front of the string.

Retina, 35 bytes

([aeiou]+[^aeiou]*){1,2} [^aeiou]*

Try it online! (The first line enables a linefeed-separated test suite.)

Simply removes all matches of the regex on the first line.