77
\$\begingroup\$

Ever fancied creating cool twitter hashtags such as #brexit or #brangelina? this golf is for you.


Write a program that accepts two strings A & B as input and merges them according to the following algorithm:

  1. let n be the number of vowels groups in A (e.g. britain has 2 vowels groups : i in position 3 and ai in position 5).
    • if n = 1 : truncate A starting at its first vowel group position (example: bill => b)
    • if n > 1 : truncate A starting at its n-1th vowel group position (example: programming => progr, britain => br)
  2. remove all consonants at the beginning of B (jennifer => ennifer)
  3. concatenate the modified A & B

Vowels are aeiou; consonants are bcdfghjklmnpqrstvwxyz.

Input

You can assume the input strings are lowercase and contain at least one vowel and one consonant.

Examples

brad + angelina      => brangelina
britain + exit       => brexit
ben + jennifer       => bennifer
brangelina + exit    => brangelexit
bill + hillary       => billary
angelina + brad      => angelad
programming + puzzle => progruzzle
code + golf          => colf
out + go             => o
\$\endgroup\$
10
  • 69
    \$\begingroup\$ New test case? donald trump. \$\endgroup\$ Commented Sep 26, 2016 at 7:45
  • 5
    \$\begingroup\$ These are essentially portmanteaus. \$\endgroup\$ Commented Sep 26, 2016 at 14:48
  • 3
    \$\begingroup\$ Related \$\endgroup\$ Commented Sep 27, 2016 at 2:07
  • 1
    \$\begingroup\$ @ETHproductions this seems to produce much different combinations, such as Django + Angular = Djular \$\endgroup\$ Commented Sep 27, 2016 at 13:00
  • \$\begingroup\$ What's "n-1th vowel group position" \$\endgroup\$ Commented May 23, 2018 at 23:18

17 Answers 17

23
\$\begingroup\$

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.

\$\endgroup\$
10
  • \$\begingroup\$ Nice regex! Mind if I use part of it in my JS answer? \$\endgroup\$ Commented Sep 26, 2016 at 3:06
  • \$\begingroup\$ Sure, go crazy. \$\endgroup\$ Commented Sep 26, 2016 at 3:08
  • 3
    \$\begingroup\$ You can golf the regex a bit more by capturing the [^aeiou] as a subexpression: /([aeiou]+([^aeiou]*)){,2} \g<2>/ \$\endgroup\$ Commented Sep 26, 2016 at 17:28
  • 5
    \$\begingroup\$ Crossed out 44 is still regular 44 ;( \$\endgroup\$ Commented Sep 26, 2016 at 18:28
  • 1
    \$\begingroup\$ @Anko See "Special invocations" in this answer. TL;DR: Only count bytes in addition to the default invocation. The default invocation for Ruby is ruby -e "...". For this it's ruby -pe "...", so it only adds one byte. \$\endgroup\$ Commented Sep 28, 2016 at 16:47
13
\$\begingroup\$

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
\$\endgroup\$
1
  • 1
    \$\begingroup\$ I always upvote happy code \$\endgroup\$ Commented Oct 14, 2016 at 15:00
11
\$\begingroup\$

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]*/,"")
\$\endgroup\$
4
  • \$\begingroup\$ Maybe could just throw out the match bit and use a replace? \$\endgroup\$ Commented Sep 26, 2016 at 3:13
  • \$\begingroup\$ @ConorO'Brien That kinda feels like stealing Jordan's answer :/ \$\endgroup\$ Commented Sep 26, 2016 at 3:14
  • \$\begingroup\$ You quite literally read my mind. And yeah, that's true \$\endgroup\$ Commented Sep 26, 2016 at 3:14
  • 1
    \$\begingroup\$ Currying (a,b)=> to a=>b=> saves 1 byte. \$\endgroup\$ Commented Sep 26, 2016 at 20:19
7
\$\begingroup\$

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"
\$\endgroup\$
1
  • \$\begingroup\$ Beautifully explained! \$\endgroup\$ Commented Sep 27, 2016 at 16:26
5
\$\begingroup\$

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.

\$\endgroup\$
4
\$\begingroup\$

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.

\$\endgroup\$
6
  • 1
    \$\begingroup\$ Any plans to add vowel and non-vowel classes? ;-) \$\endgroup\$ Commented Sep 26, 2016 at 14:54
  • \$\begingroup\$ @ETHproductions If I can ever be bothered to implement my own regex flavour (or at least tokenise it so that it can be transpiled to .NET regex), sure! :P \$\endgroup\$ Commented Sep 26, 2016 at 15:06
  • \$\begingroup\$ Ruby can do pattern backreferences (same pattern that can match a different sequence of characters). These would be useful here. For example, matching parentheses are matched by /^((\(\g<1>\))*)$/ in Ruby. \$\endgroup\$ Commented Sep 27, 2016 at 14:42
  • 1
    \$\begingroup\$ @JanDvorak Too bad Retina is written in .NET, huh? ;) I did consider bundling it with github.com/ltrzesniewski/pcre-net so that you can switch flavours, but didn't get around to that yet, and some other features are increasingly relying on .NET-specific match behaviour. \$\endgroup\$ Commented Sep 27, 2016 at 14:55
  • 1
    \$\begingroup\$ Time to drop the .net specific behavior and rewrite everything in Ruby? Ruby is better anyways :-) \$\endgroup\$ Commented Sep 27, 2016 at 14:59
4
\$\begingroup\$

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.)

\$\endgroup\$
3
  • \$\begingroup\$ Would d[aeiou]+[^aeiou]*[aeiou]*[^aeiou]* [^aeiou]* be any shorter? \$\endgroup\$ Commented Sep 27, 2016 at 2:06
  • \$\begingroup\$ @ETHproductions I tried that, it was the same byte count :( \$\endgroup\$ Commented Sep 27, 2016 at 15:04
  • \$\begingroup\$ The language name should be Cinnum. \$\endgroup\$ Commented Sep 25, 2025 at 21:47
3
\$\begingroup\$

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];
\$\endgroup\$
4
  • 1
    \$\begingroup\$ You can use + instead of {1,2}. \$\endgroup\$ Commented Sep 26, 2016 at 17:10
  • \$\begingroup\$ @Titus more important was to eliminate the bug for 1 case and now I can try to golf it down \$\endgroup\$ Commented Sep 26, 2016 at 17:18
  • \$\begingroup\$ Use $v=aeiou; to save 3 more. \$\endgroup\$ Commented Sep 26, 2016 at 17:33
  • \$\begingroup\$ @Titus I had the same idea but with a little variant. Thank You \$\endgroup\$ Commented Sep 26, 2016 at 17:47
3
\$\begingroup\$

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

\$\endgroup\$
3
\$\begingroup\$

Lua, 66 bytes

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

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.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ 20 bytes: tio.run/##K/v/P8ulzMg@OjE1M780NkabqyDBJsXv//…. But `< feels stupid \$\endgroup\$ Commented Oct 8, 2025 at 20:57
  • \$\begingroup\$ @H.PWiz If it means the code gets shorter, I'm willing to be stupid :P By the way, it's criminal that you only have two Vim answers; you're really good at Vim golf! \$\endgroup\$ Commented Oct 9, 2025 at 17:01
  • \$\begingroup\$ I only play on code.golf now :) \$\endgroup\$ Commented Oct 10, 2025 at 3:01
2
\$\begingroup\$

Perl 5, 39 bytes

38, plus 1 for -pe instead of -e

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

Hat tip.

\$\endgroup\$
1
  • \$\begingroup\$ Same as the sed answer linked to within, but we may as well have it in Perl also. \$\endgroup\$ Commented Sep 26, 2016 at 16:50
2
\$\begingroup\$

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
\$\endgroup\$
2
\$\begingroup\$

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.

\$\endgroup\$
2
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

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!

\$\endgroup\$
1
\$\begingroup\$

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.
\$\endgroup\$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.