[Question]
  [
A **[portmanteau word](https://en.wikipedia.org/wiki/Portmanteau)** is a combination of two words that takes part of each word and makes them into a single new word. For example, **lion** + **tiger** => **liger**.
Let's write a program to generate portmanteaus from a pair of input words. Computers aren't the best at English, so we'll need to establish some rules to ensure that the output portmanteaus are pleasant to the eye and ear.
(Examples here are shown with a separator between the prefix and suffix for clarity: `li|ger`. However, the program's actual outputs should not have a separator: `liger`.)
* Each portmanteau will consist of a nonempty prefix of the first word concatenated to a nonempty suffix of the second word: yes to `li|ger`, no to `|iger`.
* If the prefix ends with a vowel, the suffix must start with a consonant, and vice versa: yes to `lio|ger` or `l|er`, no to `lio|iger` or `l|ger`. **You may decide whether to count `y` as a vowel or a consonant.** Your solution must pick one option and stick with it, however.
* The resulting word must not contain either of the original words in full: yes to `lio|ger`, no to `lion|iger` or `li|tiger`.
	+ This rule holds even if the portion in question is formed from parts of both words: with input of `two` + `words`, output `tw|ords` is still illegal because it contains the substring `words`. (The only valid output for this pair would be `t|ords`.)
Your program or function must take two words and output/return **a list of all pleasant portmanteaus** that can be formed from those words in that order.
## Details
* [Standard input and output methods](https://codegolf.meta.stackexchange.com/q/2447/16766) apply. [Standard loopholes](https://codegolf.meta.stackexchange.com/q/1061/16766) are forbidden.
* Words will consist only of lowercase letters (or, if you prefer, only of uppercase letters).
* You may take the two input words as a list, tuple, two separate inputs, a single string with a non-letter delimiter, etc.
* Output format is similarly flexible; if you return or output a string, it should be delimited such that it's clear where one portmanteau word ends and the next one begins.
* There should be no delimiters inside a portmanteau word.
* It's okay if your output list includes duplicate results; it's also okay to remove duplicates.
## Test cases
```
> lion, tiger
< liger, ler, liger, lir, lioger, lior
> tiger, lion
< tion, ton, tin, tigion, tigon, tigen
> spoon, fork
< sork, spork, spork, spok, spoork, spook
> smoke, fog
< sog, smog, smog, smokog
> gallop, triumph
< giumph, gumph, gariumph, gamph, gaph, gah, galiumph, galumph, galliumph, gallumph, galloriumph, gallomph, galloh
> breakfast, lunch
< bunch, brunch, brench, brech, breh, breanch, breach, breah, breakunch, breakfunch, breakfanch, breakfach, breakfah, breakfasunch
> two, words
< tords
> harry, ginny (if y is treated as a consonant)
< hinny, hanny, hany, hay, harinny, harrinny
> harry, ginny (if y is treated as a vowel)
> hinny, hy, hanny, hany, harinny, hary, harrinny
```
## Reference solution
Here's a [reference solution in Pip](https://tio.run/##K8gs@P@/wqpQIbKQq7rCzzNRrRJI1Cq4eSrEuzgXK/gqVCdEJ6Zm5pfGKkDpBJCqhOg4mGgcQhiizwukrcLBJkZHucI5oNLBTke58v//nMz8PK6SzPTUov@6OQA) (treats `y` as a consonant).
---
This is [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'"): the shortest answer in each language wins!
  
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E), 28 bytes
`y` is a vowel (same byte count as consonant though).
```
нη¨sθ.s¨âʒ`нsθ‚žOsåË_}Jʒs¢Z_
```
[Try it online!](https://tio.run/##AUcAuP8wNWFiMWX//9C9zrfCqHPOuC5zwqjDosqSYNC9c8644oCaxb5Pc8Olw4tffUrKknPColpf//9bJ2hhcnJ5JywnZ2lubnknXQ "05AB1E – Try It Online")
or as a slightly modified [Test Suite](https://tio.run/##MzBNTDJM/V9TVqns8v/C3nPbD60oPrdDr/jQisOLTk1KuLAXyHvUMOvoPv/iw0sPd8fXep2aVKl8aFFU/P/aSqXD@xV07RQO71fS@Z@TmZ@nUJKZnlrEBSYVQAJcxQX5QOG0/KJsruLc/OxUIDOdKz0xJye/QKGkKLM0tyCDK6koNTE7LbG4RCGnNC85g6ukPF@hPL8opZgrI7GoqFIhPTMvrxIA)
[Answer]
## [Retina](https://github.com/m-ender/retina/wiki/The-Language), 72 bytes
```
L$w`(?<=[aeiou]()|.())((.+),(.+))\B(?!\4)(?<!\5\3)(?([aeiou])\2|\1)
$`$'
```
[Try it online!](https://tio.run/##LYpBasMwEADv@4uASySyGNK0txZDLr30B1XBm1S2hWWtWMmYQP7uyCWXYRhGbHaBjuuL@mrX72ppVfPx@UPW8fyr9L1WWitVHzRu0Oasmp1502XamXdzKqKeszavd3PUULXVfjUBcPWOA2bXW4F/4hYgRS65YxkhTTzaoj305D1HzOLmKQ5wEUtjRymjn8N1gLwwLix/CQYSuWHvQrhB9JYShYyRJU9FLM3pAQ "Retina – Try It Online")
[Answer]
# [Pyth](https://github.com/isaacg1/pyth), 38 bytes
```
f!s}RTQm+hd_edfxFm}ed"aeiou"T*._hQ.__e
```
Input is a list of the two words, and y isn't treated as a consonant.
Try it online [here](https://pyth.herokuapp.com/?code=f%21s%7DRTQm%2Bhd_edfxFm%7Ded%22aeiou%22T%2A._hQ.__e&input=%5B%22gallop%22%2C%22triumph%22%5D&debug=0&input_size=2), or verify all test cases at once [here](https://pyth.herokuapp.com/?code=f%21s%7DRTQm%2Bhd_edfxFm%7Ded%22aeiou%22T%2A._hQ.__e&test_suite=1&test_suite_input=%5B%22lion%22%2C%20%22tiger%22%5D%0A%5B%22tiger%22%2C%20%22lion%22%5D%0A%5B%22spoon%22%2C%20%22fork%22%5D%0A%5B%22smoke%22%2C%20%22fog%22%5D%0A%5B%22gallop%22%2C%20%22triumph%22%5D%0A%5B%22breakfast%22%2C%20%22lunch%22%5D%0A%5B%22two%22%2C%20%22words%22%5D%0A%5B%22harry%22%2C%20%22ginny%22%5D&debug=0).
```
f!s}RTQm+hd_edfxFm}ed"aeiou"T*._hQ.__e   Implicit: Q=eval(input())
                                hQ       First input word
                              ._         All prefixes of the above
                                     e   Second input word (Q inferred)
                                  .__    Reverse, take all prefixes
                             *           Cartesian product of the above
              f                          Filter the above using:
                 m          T              Map d in the current element using:
                   ed                        The last letter of the word part
                  }  "aeiou"                 Is it contained in the vowel list?
               xF                          Take the XOR of the list
                                         (This ensures that the word parts meet at one consonant)
       m                                 Map d in the filtered set using:
        +hd_ed                             Add the first part to the reversed second part
f                                        Filter the above using:
  s}RTQ                                    Does the portmanteau contain either of the input words?
 !                                         Logical NOT (remove from list if the above is true)
```
[Answer]
# Java 8, ~~228~~ ~~225~~ 215 bytes
```
v->w->{String r="",t,p=" aeiou";for(int i=w.length(),j;--i>0;)for(j=1;j<v.length();)r+=(t=v.substring(0,j)+w.substring(i)).matches(v+".*|.*"+w)|p.indexOf(t.charAt(j-1))*p.indexOf(t.charAt(j++))>0?"":t+" ";return r;}
```
Takes two Strings in currying syntax and returns a String. Treats `y` as a consonant. Try it online [here](https://tio.run/##lZCxbsMgFEVn@ysQE8Q2StYSu@rSreqQsepAHOJAbEDwbDdK8u2u3SRVqnbpBNwDh6erRScy66TRm/2gGmc9ID1mrAVVs21rSlDWsOfrhsexa9e1KlFZixDQi1AGHePoGgYQMC6dVRvUjIiswCtTvb0j4atAp5vRTbW8sBT9Ci5rUaBpmkYYkKINKEdDlxV9VhwvHPkc4xRSl2MkpLIt5lvriTKAVN6zWpoKdoSmmmeZKuacTlTnC66X3Tfl1Cc5gbxjoV2HLy@Zp5om/V2gKGWNgHInA@kSzGYnNsNJT0@OKbORH69bAqzcCf8ERGcLSmd/gSShtJg/YvwACUaYewmtN8jz8xBFfCxmdQggG2ZbYG78F2pD7gtgwrn6QHA9VoXp7QSqkh5T@g/B9clP338Ewdn7EcZe95MgiuLoHJ@HTw).
Thanks to [DLosc](https://codegolf.stackexchange.com/users/16766/dlosc) for golfing 2 bytes.
Ungolfed:
```
v -> w -> { // lambda taking two String parameters in currying syntax
    String r = "", // result
    t, // temporary variable used for storing
       // the portmanteau candidate currently being evaluated
    p = " aeiou"; // vowels for the purposes of this function;
                  // the leading space is so that they all have a positive index
    for(int i = w.length(), j; --i > 0; ) // loop over all proper suffixes
                                          // of the second word
        for(j = 1; j < v.length(); )      // loop over all proper prefixes
                                          // of the first word
            r += // construct the portmanteau candidate
                 (t = v.substring(0, j) + w.substring(i))
                 // if it contains one of the input words ...
                 .matches(v + ".*|.*" + w)
                 // ... or the boundary is consonant-consonant 
                 // or vowel-vowel (here we make use of the facts
                 // that all the vowels have a positive index, and
                 // indexOf() returns -1 in case of no match) ...
                 | p.indexOf(t.charAt(j-1)) * p.indexOf(t.charAt(j++)) > 0
                 ? "" // ... reject it ...
                 : t + " "; // ... else add it to the result
    return r; // return the result
}
```
[Answer]
# [Japt](https://github.com/ETHproductions/japt), 32 bytes
```
å+ ïVw å+)f_xè"%v$" uÃmrÈ+YwÃkøN
```
[Japt Interpreter](https://ethproductions.github.io/japt/?v=1.4.6&code=5Ssg71Z3IOUrKWZfeOgiJXYkIiB1w21yyCtZd8Nr+E4=&input=Imxpb24iICJ0aWdlciI=)
Saved 10 bytes thanks to Shaggy's clearer understanding of Japt's syntax.
Saved 8 bytes due to a new language feature
Saved 2 byte thanks to some suggestions from ETHproductions
The newest version of Japt introduced the Cartesian Product function, which saved quite a few bytes and allowed me to restore the ordering of inputs (so "lion" "tiger" outputs "liger" and such). "y" is still treated as a consonant.
Explanation:
```
   ï     )       Cartesian product of...
å+                prefixes of first input
    Vw å+         and suffixes of second input.
f_         Ã     Remove the ones where...
  xè"%v$"         the number of vowels at the joining point
          u       is not 1.
m     Ã          Replace each pair with...
 rÈ+Yw            the prefix and suffix joined together
       køN       then remove the ones that contain either input
```
[Answer]
## [Python 3](https://docs.python.org/3.6/), ~~156~~ 150 bytes
I've considered `y` as a consonant.
```
lambda a,b:{a[:i]+b[j:]for i in range(1,len(a))for j in range(1,len(b))if((a[i-1]in'aeiou')^(b[j]in'aeiou'))*0**(a in a[:i]+b[j:]or b in a[:i]+b[j:])}
```
-6 bytes thanks to [Jonathan Frech](https://codegolf.stackexchange.com/users/73111/jonathan-frech)
[Try it online!](https://repl.it/repls/DraftyUnrealisticDataset)
[Answer]
# JavaScript (ES6), 124 bytes
Takes the 2 words in currying syntax `(a)(b)` and prints the results with `alert()`. Assumes ***y*** is a consonant.
```
a=>b=>[...a].map(c=>[...b].map((C,j)=>!(w=s+b.slice(j)).match(a+'|'+b)&v.test(c)-v.test(C)&&alert(w),s+=c),s='',v=/[aeiou]/)
```
[Try it online!](https://tio.run/##VVFdbvMgEHzvKfikKgaF2icgLz1GFKmLSzAxMRaQRFXbs@fjNyV@mJmd3R2t8Amu4EarVv@2mE9xP7I7sB1nu33f93Doz7DiMVc8V/idngjb/cM35ra8d1qNAp8ICU0/Thi23U@35WRz7b1wHo/krah3stmAFtbjG6Fuy8aArOvolQ17EMpcDgO5pwHE0GgWZ7TotZEvcTtYGCjiBLFd28Qf@9dv@EUDev3mv4cPgn7QEQPBPKp2kLykINxpZZaOos4rKWxHUP6GAeloUKQTFK0SmFIYWzLybghJYU2GDzVFPoFKILOjZCGxlAy3mnzI0di5zXChpii0nyljrcxcY85mFjlGPlJyjAyT5yecy3PiToLWZk3vYNXlvE5pN6zJVFEkC4GtBhTKmEA/evohGq8xjW1s86emcg@3AuYjOJ9e9bKM6aBwD486/HlbWVQulBGqC5ULzY@9kN9qaHUj/5SL4/WP30y87Gbsp3t6Zh@dMjSBtV9xTKpl@apjYWiKNUUTVEqYwNaWTer@Hw "JavaScript (Node.js) – Try It Online")
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), 27 bytes
```
¹Ƥp¹ÐƤ}Ø.ị"e€Øc⁻/ƲƇẎ€wÐḟƒ@,
```
[Try it online!](https://tio.run/##AVYAqf9qZWxsef//wrnGpHDCucOQxqR9w5gu4buLImXigqzDmGPigbsvxrLGh@G6juKCrHfDkOG4n8aSQCz/w6crL@KCrMWS4bmY//9nYWxsb3D/dHJpdW1waA "Jelly – Try It Online")
**Yy** is a consonant. Both cases supported. Returns duplicates.
Output has been prettified over TIO. Remove `+/€` from the footer to see the actual output.
[Answer]
# C++ 11, ~~217~~ 202 bytes
```
[](auto v,auto w){auto r=v,t=v,p=v;r="",p="aeiou";for(int i=w.size(),j;--i;)for(j=v.size();j;)(t=v.substr(0,j)+w.substr(i)).find(v)+1|t.find(w)+1|p.find(t[j-1])<5==p.find(t[j--])<5?v:r+=t+" ";return r;}
```
Makes heavy use of `std::string#find`. Treats `y` as a consonant. Try it online [here](https://tio.run/##hZBBbsMgEEXX9SnQdAOyHSWLboxpD5JGFXVohOsAgsGWmubsLiSulCyqLtD8@cxjxO@cqw9dN8uIljjr8SgNKhkDEfN2Ry/2WF3KxE6X6sVYYTpOjNwLgCRAKm0j8A/rqTZItJhWQX8pyqqe17XmLN/0Ylxc3nNGMbfxPaCn66pn5fTbacZWH9rs6cjKzTde9ZS1u2rc9vVmx9onIW6cOjsvY@NLgSUQ4F5h9IZ4fp55UTxq0w1xr0irbdqi5PG5KGLQ5kAC7pumsxH5rZGGkn4bNCovh9A01iWB1gOE9F7@51FqQxk5FQ@ZJm17FyGFQVsDoSKA@qA8BJZH4NUA/4tYBhNyZf8ngrPLkpTx5z2xJLDmxXn@AQ).
Ungolfed:
```
// lambda; relies on auto to keep declarations short
[] (auto v, auto w) {
    // let's declare some strings. To keep it terse, we're using auto and the type of the arguments.
    auto r = v, // result string
    t = v,      // temporary string for storing the portmanteau candidate
    p = v;      // vowels string
    // now assign them their values
    r = "",    // result starts empty
    p = "aeiou"; // vowels don't include 'y'
    for(int i = w.size(), j; --i; ) // suffixes of the second word
        for(j = v.size(); j; ) // prefixes of the first word
            // create the portmanteau candidate
            (t = v.substr(0, j) + w.substr(i))
            // if it includes one of the input words ...
            .find(v) + 1 | t.find(w) + 1
            // ... or the boundary is consonant-consonant or vowel-vowel ...
            | p.find(t[j - 1]) < 5 == p.find(t[j--]) < 5
            ? v // ... discard it ...
            : r += t + " "; // ... else add it to the result.
    return r; // return the result
}
```
[Answer]
# [Python 2](https://docs.python.org/2/), ~~179~~ ~~176~~ ~~166~~ 162 bytes
```
lambda s,t:[w for w in g(s,t)if(s in w)<1>(t in w)]
g=lambda s,t:s[:-1]and[s[:-1]+t[j:]for j in range(1,len(t))if(s[-2]in'aeiou')^(t[j]in'aeiou')]+g(s[:-1],t)or[]
```
[Try it online!](https://tio.run/##TU7LDoMgELz7FdwWoh70aGp/hNIEKyjWLgYwpF9PfRzqbR47M7t8w2ixTrp9pFl@ul4SX4SGR6KtI5EYJAPdFGY09TuL7FbdaTihyIb2kvK8KSshsecnygOfGrEXTfu9kzgoWhWzQhrY0cjLWhgEqYxdgT3pFrhwkW/bR9P2gHVcpMUZDERTCNFCAdG63gPL/rIZlIOCwGwsXo3OKfnW0ofDXPE1AkvpBw "Python 2 – Try It Online")
3 bytes from [Jonathan Frech](https://codegolf.stackexchange.com/users/73111/jonathan-frech). And 10 bytes thx to [The Matt](https://codegolf.stackexchange.com/users/81432/the-matt).
In my world, `y` is not a vowel. (It's a yowl!)
[Answer]
# [Ruby](https://www.ruby-lang.org/), ~~113 112 109~~ 104 bytes
`y` is a consonant
This outputs the same duplicates as the examples in the question, I must be using the same loop
```
->a,b,i=j=1{r=a[0,i]+b[j..-1];g=:aeiou;!g[a[i-1]]^g[b[j]]|r[a]|r[b]||z=[*z,r];b[j+=1]||a[i+=j=1]?redo:z}
```
[Try it online!](https://tio.run/##VVHBbqMwFLznK97mkm7jouaayNvTnnqolKvllUxDjAPhoQeoSsp@e/ps7JReZsYzzLONacgvt6O8Pf0xIhdOnuTmk6RRz8Lpda5OWfa00Tsrt6ZwOOx@WWWUY0v/s4pjrUdSxkOux/Eq1eNVkN5xspYbdvjjtZ@pX6g44Pb6/6YWAGpVO2wE9M4WtBLASxYC6gBRuwAYF0grLUK1Tzk2vtpPk6Zx08w0O23RpGrXoveOSJWvdswC2PxJE6YVVvf2GavCt@1Utpyff2DFUfzYmrrGlvcnN5zb0jdsUAJsJEPJMJEmDFDfs/ouZt7MRJrZ@K3KdJScClMdTdfzTxua93CW3AsBOSUuEkea0CTXJI5U3Xs8eq7NXM/kt@rCGdJjfqCAD6RDF94yiBiVhujCd3FNc/Fh6YWA0iQKGIBSREGt9EJn/shwQBhd0w58dRx65pFHM3VwVI8hyLq2dv2D3@C3zk7omkmDlLECL7B8e13CFpZ/9/u3/XJRNIfbFw "Ruby – Try It Online")
[Answer]
# [Emacs Lisp](https://www.gnu.org/software/emacs/manual/html_node/elisp/index.html#Top), 306 + 13 = 319 bytes
*+13 for `(require'seq)`*
```
(require'seq)(lambda(a b)(dotimes(i(1-(length b)))(dotimes(j(1-(length a)))(progn(setq w(substring a 0(1+ j))x(substring b(1+ i))c(concat w x))(defun V(c)(seq-contains"aeiou"(elt c 0)'char-equal))(if(not(or(string-prefix-p a c)(string-suffix-p b c)))(if(V(substring w -1))(if(not(V x))(print c))(if(V x)(print c))))))))
```
[Try It Online!](https://tio.run/##TY/BsoMgDEX3/YoMm4Z5w0z9GfeRRksfAgKO/r2NulCW5yYnFx7JFuNdSRumHIfwwMzT7DI/C0/6gf0cLHm/oaexexMSdBrfsbqRCzpsDHoOQ/0I1lfwvQW0B4cbC9cJFixzV2p2YQCCFzZ/8NV6vdFuZ05rizbK9QoLrLucpQy0aLWIJiNZJReKInZxVsi@goWXftoPZSOfIC9LrscQK8aMp9ykzL1bTZLbu@iEZe5P2Ak8t9pboQVMc7nao02SpO7Tx7Cgi5xvUyXFGBSoPuZ/JeAH)
Defines an anonymous lambda function. Outputs a sequence of newline-separated portmanteaus with each one surrounded by quotes. Golfing tips are welcome. The letter `y` is considered a consonant.
## Ungolfed
```
(require 'seq)                                                                                                                                                           
(defun Portmanteus(word1 word2)
  "Find all valid portmanteus of the two given words"
  (dotimes (i (1- (length word2)))
    (dotimes (j (1- (length word1)))
      (progn
        (setq w (substring word1 0 (1+ j)) w2 (substring word2 (1+ i)) comb (concat w w2))
        (defun isVowel (c) (seq-contains "aeiou" (elt c 0) 'char-equal))
        (if (not (or (string-prefix-p word1 comb) (string-suffix-p word2 comb)))
          (if (isVowel (substring w -1))
            (if (not (isVowel w2))
              (princ (format "%s\n" comb))
            )
            (if (isVowel w2)
              (princ (format "%s\n" comb))
            )
          )
        )
      )
    )
  )
)
```
]