Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Given two words, spoonerise them by switching their initial consonant clusters. Fewest bytes wins.

plaster man -> master plan
blushing crow -> crushing blow
litigating more -> mitigating lore
strong wrangler -> wrong strangler
def ghi -> ghef di
few years -> yew fears

The consonants appearing before the first vowel (aeiou) are switched.

Input: Two lowercase strings that start with different consonants and each contain a vowel aeiou.

Output: The two spoonerised strings, in the right order.

For input and/or output, the two strings may also be in a list or the like, or as a single string with separator.

    var QUESTION_ID=69385,OVERRIDE_USER=20260;function answersUrl(e){return"https://api.stackexchange.com/2.2/questions/69385/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"https://api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var r=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(r="<h1>"+e.body.replace(OVERRIDE_REG,"")+"</h1>")});var a=r.match(SCORE_REG);a&&e.push({user:getAuthorName(s),size:+a[2],language:a[1],link:s.share_link})}),e.sort(function(e,s){var r=e.size,a=s.size;return r-a});var s={},r=1,a=null,n=1;e.forEach(function(e){e.size!=a&&(n=r),a=e.size,++r;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;/<a/.test(o)&&(o=jQuery(o).text()),s[o]=s[o]||{lang:e.language,user:e.user,size:e.size,link:e.link}});var t=[];for(var o in s)s.hasOwnProperty(o)&&t.push(s[o]);t.sort(function(e,s){return e.lang>s.lang?1:e.lang<s.lang?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;
    body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table>

**Leaderboard:**


This is a near-dupe of this old question, but I'm hoping to write a spec that is clearer and more stable so that the old one can be closed as a dupe.

share|improve this question
    
What if a word starts with a vowel, such as "snoozing otter"? – Hand-E-Food Jan 14 at 5:59
3  
The words start with consonants. – xnor Jan 14 at 6:01
17  
Answer should be "oozing snotter" imo~ – Patrick Roberts Jan 14 at 19:45
2  
@PatrickRoberts I agree, but this makes the challenge a bit simpler. – xnor Jan 14 at 21:24
    
Well for some regexes you can just replace the + with * and add a ^ at the beginning to negate the greedy search – Patrick Roberts Jan 14 at 22:02

35 Answers 35

Vim, 18 keystrokes

/[aeiou]<CR>dbwvnhp0P

The crucial trick is that pasting over something in Visual mode actually puts the old contents of the visual selection in the paste buffer.

share|improve this answer
    
... oh, duh, didn't think of that. Kept getting thrown off by v being inclusive and trying to select from the vowel back. – Doorknob Jan 14 at 2:20
6  
As a casual vim user, I kept being amazed as I typed each successive command – Aaron Jan 14 at 14:35
4  
<CR> means carriage return (old typewriter term!), also known as Enter – Kai Carver Jan 14 at 18:50

brainfuck, 238 207 bytes

,[[<+<+>>-]++++[<-------->-]-[<<-->>-----]<<+++++[----[----[------[------>>]]]]>[>>]>,]<<++++++++[<[++++<<]<++++<[++++<<]>>[>>]>>[>>]<-]<[<<]-[<+>---]>[>.>]<[<<]<<[<<]>[>>]>[.>>]<.<[<<]>[>.>]>[>>]>[>>]>[.>>]

Requires , to return 0 on EOF, 8-bit wrapping cells and the ability to move left from cell 0. In my experience, these are the most common default settings.

I'm pretty happy with this one. My first try was 314 bytes and this is certainly an improvement. :)

It works by storing every byte from input in two cells; one with the actual value of the byte and the other with the output of the following code when given (the value of the byte - 97):

[
    ----
    [
        ----
        [
            ------
            [
                ------>>
            ]
        ]
    ]
]

If the character is a consonant, it comes out of that with a non-zero value. If it's a vowel, it becomes 0. From there it's just a matter of finding where the second word starts and printing everything in order.

The 238 byte version of this program found the space character after collecting all the input. It was a headache because doing so involved creating a cell that contained 0 right where I was trying to loop over it. The way I solved that had the effect of subtracting 30 from every character in the first word and 32 from every character after it. A fairly large portion of the code was dedicated to handling that nonsense.

Now, 32 is subtracted from every character in the input loop, which is shorter and has a similar side effect that's easier to deal with. As a bonus, doing it this way allowed me to create my own space character in a shorter way: Instead of subtracting 139 from 171 (171 is what you get when you run a space through the vowel detector above), the loop that adds 32 to every character goes out of its way to also add 32 to the 171 cell. This costs four bytes there, but means I can subtract 171 from it later (instead of subtracting 139) for a net total of 3 bytes saved.

With comments:

For every input character
,[

  Make a copy
  [<+<+>>-]

  Subtract 32 from one
  ++++[<-------->-]

  Subtract 97 from the other
  -[<<-->>-----]<<+++++

  If nonzero:
  [

    Subtract 4
    ----

    If nonzero:
    [

      Subtract 4
      ----

      If nonzero:
      [

        Subtract 6
        ------

        If nonzero:
        [

          Subtract 6
          ------>>

        ]

      ]

    ]

  ]

>[>>]>,]

Add 32 to every character and the 171 that the space left behind
<<++++++++[<[++++<<]<++++<[++++<<]>>[>>]>>[>>]<-]

Go to the space
<[<<]

Subtract 171 from (32 plus 171)
-[<+>---]

~~~~~~~~~~~~~~~

Ready to print!

~~~~~~~~~~~~~~~

Print letters from the second word until the value to the left is zero
>[>.>]

Go to the beginning of the first word
<[<<]<<[<<]

Look at cells to the left of letters in the first word until reaching a zero
>[>>]

Print the rest of the letters in the first word
>[.>>]

Print a space
<.

Go to the beginning of the first word
<[<<]

Print letters from the first word until the value to the left is zero
>[>.>]

Go to the beginning of the second word
>[>>]

Look at cells to the left of letters in the second word until reaching a zero
>[>>]

Print the rest of the letters in the second word
>[.>>]
share|improve this answer
    
This counts y as a vowel, but the question says it's not. (nye cat -> ce nyat) – Loovjo Jan 22 at 13:11
    
@Loovjo that's really odd, because the code that checks for vowels definitely treats y as a consonant... I'll look into why it's doing that. – undergroundmonorail Jan 22 at 13:18

vim, 23

/[aeiou]<cr>"xd0wndb0Pw"xP

I wonder if vim is actually competitive in this challenge. Probably not with the golfing languages, but perhaps with Ruby/Python/Perl/etc.

/[aeiou]<cr>  Find the first vowel
"xd0          "Delete" (cut), to register "x, everything from here to BOL
w             Go to next word
n             Find next vowel
db            "Delete back" - delete from here to the beginning of the word
0             Go to BOL
P             Paste what we just "deleted" (cut) behind the cursor
w             Next word
"xP           Paste backwards from register "x
share|improve this answer
7  
I do this in Insert mode, right? – Alex A. Jan 15 at 6:57
2  
@AlexA. ಠ_ಠ​​​​ – Doorknob Jan 15 at 12:12
    
@AlexA. Insert mode would be an extra keystroke :)~ – pydsigner Jan 15 at 20:10
    
@AlexA. Insert mode? Did you mean insert command? – Blacklight Shining Jan 16 at 3:43
    
@BlacklightShining Nope. It was a joke because if you're in insert mode and you type that stuff, it won't execute any commands; you will have just typed it in a file. – Alex A. Jan 16 at 4:22
up vote 12 down vote
+100

Python, 68 63 60 bytes

import re
lambda s:re.sub('([^aeiou]+|.+ )'*3,r'\3\2\1',s,1)

Try it online on Ideone.

How it works

The pattern string is repeated thrice (*3), resulting in the pattern

([^aeiou]+|.+ )([^aeiou]+|.+ )([^aeiou]+|.+ )

All instances will either match a non-empty string of non-vowels, or a non-empty string followed by a single space character.

The first instance will match the consonants at the beginning of the first word. Since + is greedy, it will attempt to match as many as possible, i.e., all up to the first vowel.

Because of this, the second instance will start at a vowel, so it will match the remainder of the first word, up to and including the space that separates the words.

Similarly to the first instance, the third will match all consonants at the beginning of the second word, resulting in a successful match for the entire pattern.

The raw string \3\2\1 (r prevents Python from replacing \3 etc. with control characters) reverses the order of the matches of the parenthesized patterns, i.e., it replaces them with the consonants at the beginning of the second word, then all characters from the first vowel of the first word up to the space, and finally the consonants at the beginning of the first word.

The final argument to sub (1) makes it return immediately after the first successful replacement, to avoid nonsensical replacements in the remainder of the second word. This is required since the pattern can match any string of three or more consecutive consonants.

share|improve this answer
    
Congrats on the bounty, for bringing the regex magic to Python with a very efficient regex. Nice explanation too. – xnor Jan 23 at 8:22

JavaScript (ES6), 54 bytes

s=>s.replace(r=/\b[^aeiou ]+/g,(_,i)=>s.match(r)[+!i])

Explanation

s=>
  s.replace(
    r=/\b[^aeiou ]+/g,     // r = regex to match consonants
    (_,i)=>s.match(r)[+!i] // replace consonants with the consonants from the other word
  )

Test

var solution = s=>s.replace(r=/\b[^aeiou ]+/g,(_,i)=>s.match(r)[+!i])
<input type="text" id="input" value="plaster man" />
<button onclick="result.textContent=solution(input.value)">Go</button>
<pre id="result"></pre>

share|improve this answer
    
Ohh, my bad, I misunderstood. I'll take a look at the mdn docs for match when I get home – Patrick Roberts Jan 14 at 22:30
    
The +!i trick is a nice solution. +1 – ETHproductions Jan 22 at 2:30

CJam, 27 24 22 bytes

2{l_{"aeiou"&}#/(N\}*o

I/O is one word per line. Try it online!

How it works

2{                 }*   Do the following twice:
  l                       Read a line from STDIN.
   _                      Push a copy.
    {"aeiou"&}#           Find the index of the first character that has a non-
                          empty intersection with the string "aeiou".
               /          Split the string into chunks of that size.
                (         Shift out the first chunk, i.e., all leading consonants.
                 N\       Swap the shifted out chunk with a linefeed.
                     o  Print the topmost stack item.
share|improve this answer

Perl, 33 bytes

s/([^aeiou]+)(.+ )((?1))/\3\2\1/

The above code is 32 bytes long and requires the -p switch (+1 byte).

The substitution is very similar to the one @DigitalTrauma's Retina answer, but this answer takes advantage of PCRE's recursive subpatterns.

Try it online on Ideone.

share|improve this answer

Python 3, 108 101 99 bytes

(No use of regex)

This function expects input via 2 arguments, e.g. f('blushing','crow'). Returns the new words in a tuple.

S=lambda s,p="":s[0]in"aeiou"and(p,s)or S(s[1:],p+s[0])
def f(x,y):a,b=S(x);c,d=S(y);return c+b,a+d

There are a lot of regex solutions, so I wanted to write something that didn't use Python's re library.

How it works

The only complicated part is the lambda expression S (the abbreviation means "Split before the first vowel"). It recursively "iterates" over the given word, moving one character at a time from the beginning of s (which starts with the whole word) to the end of p (which starts empty). At the first vowel encountered it returns (p,s), i.e. (prefix, suffix). Notice that that is the wrong order compared to the parameters!

I thought it made more sense for the returned order to be prefix, then suffix (because generally a prefix goes before a suffix). This order might make the a,b=S(x) code slightly easier to read.

But I had no choice of order in the lambda's parameters, so I couldn't define p before s. The first parameter, s, had to take the entire word because p had a default value, and default parameters go last. Doing that, I didn't need to call the function S with an empty string twice, and a few bytes could be saved. However, perhaps it was simply a bad decision to return prefix/suffix in the opposite order as it was used within the lambda expression.

As for the choice of lambda expression over function, it takes more bytes to say def S(s,p=""):return than S=lambda s,p="":. I can make that choice because Python has short-circuit evaluation, and the ternary operator. However, I cannot adequately explain how I used short-circuits; it's hard to reason about.


This is my first answer. I hope I did this correctly, and that there's value to posting a solution that cannot win.

Edits: Thank-you commenters: Reduced the byte count a bit, twice, and removed unnecessary info. Attempted to improve writing. Hopefully made no mistakes.

share|improve this answer
    
welcome to ppcg, great first answer :) just fyi, most programs on this site don't have a trailing newline, so you don't have to mention it (in the rare cases when it is necessary, that's when people mention it) – undergroundmonorail Jan 18 at 4:50
3  
Welcome to Programming Puzzles & Code Golf! 1. You don't have to worry about the input format. The challenge explicitly says that you can take a list. 2. Per the defaults mentioned in the tag wiki, you can submit either full programs or functions to code golf challenges. For this particular problem, a function should be 7 bytes shorter. – Dennis Jan 18 at 6:24
4  
Regarding the last sentence, "I hope [...] there's value to posting a solution that cannot win." There most certainly is! We're all here to have fun and contribute and learn from each other. I find this answer particularly clever as the more obvious solution is to use regular expressions. Very nice work! – Alex A. Jan 18 at 9:07
    
A excellent first answer. It's quite similar to what I came up with for non-regex. You had a good thought about using short-circuiting logical expressions, and it turns out they can shorten the expression, though perhaps you'd like to think yourself about how to do that. – xnor Jan 20 at 5:49
    
I really like the fact you used a recursive solution. Very elegantly implemented! – Ogaday Jan 21 at 1:18

C#6, 115 bytes

string S(string a)=>System.Text.RegularExpressions.Regex.Replace(a,"([^aeiou]*)(.*) ([^aeiou]*)(.*)","$3$2 $1$4");

It's just a pain the namespace for regex is so long.

share|improve this answer
2  
My gosh that is verbose. – Cᴏɴᴏʀ O'Bʀɪᴇɴ Jan 14 at 2:34
4  
System.Text.RegularExpressions.Regex.Replace 44 characters! +1 because that must be some kind of record. – Level River St Jan 14 at 10:01
2  
...and now you have 44 problems. ;) – Mason Wheeler Jan 15 at 21:04

Retina, 34

([^aeiou]+)(.+ )([^aeiou]+)
$3$2$1

Try it online.

share|improve this answer

JavaScript ES6, 93 58 52 bytes

Saved 6 bytes thanks to ETHProductions!

x=>x.replace(/([^aeiou]+)(.+ )([^aeiou]+)/,"$3$2$1")

Test it! (ES6 only)

F=x=>x.replace(/([^aeiou]+)(.+ )([^aeiou]+)/,"$3$2$1");

console.log=_=>u.innerHTML+=_;

console.log(`plaster man -> master plan
blushing crow -> crushing blow
litigating more -> mitigating lore
strong wrangler -> wrong strangler
def ghi -> ghef di`.split`\n`.map(e=>(e=e.split` -> `,`${e[0]} => ${e[1]} ||> `+(F(e[0])==e[1]))).join`<br>`);
html { font-family: Consolas, monospace; }
<div id=u></div>

share|improve this answer
    
I was just about to click post answer on my 58 byte solution when you made this edit haha – user81655 Jan 14 at 2:40
    
@user81655 Oh, sorry that it happened like that. – Cᴏɴᴏʀ O'Bʀɪᴇɴ Jan 14 at 12:00
    
You don't need the fourth capturing group or the $4 at all ;) – ETHproductions Jan 14 at 13:01
    
@ETHproductions Oh, yeah! Thanks! – Cᴏɴᴏʀ O'Bʀɪᴇɴ Jan 14 at 13:11

C, 255 201 199 bytes

I don't see a lot of C answers around here, so enjoy; Also, first time golfing, suggestions and critique are welcome.

#define S(w,p)p=strpbrk(w,"aeiou")-w
#define c ;strcpy(r
#define l c+strlen(v[1])+b+1
main(int q,char**v){char r[64],S(v[1],a),S(v[2],b)c,v[2])c+b,v[1]+a);strcat(r," ")l-a,v[1])l,v[2]+b);puts(r);}

If main() is not required we can save 24 bytes, getting to 179 bytes

#define S(w,p)p=strpbrk(w,"aeiou")-w
#define c ;strcpy(r
#define l c+strlen(x)+b+1
s(char*x,char*y){char r[64],S(x,a),S(y,b)c,y)c+b, x+a);strcat(r," ")l-a,x)l,y+b);puts(r);}

Ungolfed:

void spoonerise(char* w1, char* w2)
{
    char rt[64];

    int p1 = strpbrk(w1, "aeiou")-w1;
    int p2 = strpbrk(w2, "aeiou")-w2;

    strcpy(rt, w2);
    strcpy(rt+p2, w1+p1);

    strcat(rt, " ");

    strcpy(rt+strlen(w1)+p2+1-p1, w1);
    strcpy(rt+strlen(w1)+p2+1, w2+p2);

    puts(rt);
}

EDIT: Thanks to feersum's suggestion I saved 54 bytes. =D

share|improve this answer
    
I recommend looking into strpbrk. – feersum Jan 16 at 19:11
    
+1 This is a great first answer. Welcome to the site. – wizzwizz4 Jan 16 at 20:25
    
Thanks for the recommedation @feersum. And thanks for the welcoming @wizzwizz4! – Lince Assassino Jan 16 at 21:28

Python 2, 364 352 269 251 bytes

EDIT: Thanks so much to @Cyoce for helping me golf 83 bytes!

Please help me golf this! Anyway, at least I am the first Python answerer. And I hope I can beat Java, if there ever is a Java answer!

i=input()
f=l=''
A='aeiou'
for j in A:
 I=i[0];J=I.find(j)
 if ~J:
  if f:
   if f>I[0][:J]:f=I[:J];break
  else:f=I[:J]
for j in A:
 Y=i[1];J=Y.find(j)
 if ~J:
  if l:
   if l>Y[:J]:l=Y[:J];break
  else:l=Y[:J]
print I.replace(f,l,1),Y.replace(l,f,1)

Try it here

share|improve this answer
5  
-1 for not making an attempt to golf this beyond single-character variables – Mego Jan 14 at 3:06
    
@Mego I promise I am working on that ASAP. Right now. But I am working on a regex version. – TanMath Jan 14 at 3:07
    
@Mego please see edit. – TanMath Jan 14 at 3:23

Japt, 26 25 bytes

Fortunately, I added a vowel class to Japt's regex features a few days ago. Unfortunately, I didn't add a non-vowel class or a way around the double backslashes in regex strings.

#¿s4 £Uf"[^\\v]+|.+
?" gX

The ¿ should be the raw char U+0093. Input is a multi-line string, one word/line. Try it online!

EDIT: I've now added the non-vowel class \V and a way around \\ (with %), so this code now works for 21 bytes: (Try it online)

#¿s4 £Uf"%V+|.+
?" gX

How it works

                     // Implicit: U = input string
#¿s4                 // Convert the char code (147) into a base-4 string "2103".
     £               // Map each char X in this string to:
      Uf"[^\\v]+|.+  //  Match each group in U of non-vowels or non-newlines,
?"                   //  with an optional trailing newline.
   gX                //  Get the item at position X in the resulting array.
                     // Implicit: output last expression

Old version (26 bytes):

UrA="\\b[^\\v ]+"@UfA gÂ!Y

Try it online!

How it works

UrA="\\b[^\\v ]+"@UfA gÂ!Y  // Implicit: U = input string
  A="\\b[^\\v ]+"           // Set variable A to this regex string, which matches
                            // a word boundary followed by one or more non-vowels.
UrA              @          // Take U and replace each match X of A and its index Y with:
                  UfA       //  Take U.match(A).
                      gÂ!Y  //  Get the item at index ~~!Y (converts 0 to 1, anything else to 0).
                            // Implicit: output last expression
share|improve this answer
    
I wish mainstream languages had a vowel meta for regexes! – CJ Dennis Jan 16 at 13:53

Python 3, 100 (or 99) bytes

import re
def f(*g):a,b=[re.split("[aeiou]",r)[0] for r in g];return b+g[0][len(a):],a+g[1][len(b):]

Played with a few versions but can't seem to get it below. Can get it down 99 bytes by using def f(g) instead so it takes a list of strings rather than two seperate strings, but I prefer the two arg roue.

The alternative is equal length:

import re
s=re.split
def f(x,y):v="[aeiou]";a,b=s(v,x)[0],s(v,y)[0];return b+x[len(a):],a+y[len(b):]

I tried replace, like @TanMath uses, but I couldn't get it any shorter. Also, TanMath can get his answer shorter by a byte by also using "[aeiou]" instead of "[aeiou]+" because we only need to match the single instances. Finally, the implementation of input() seems to have changed between py2 and py3 - it automatically evaluates stdin as a string.

share|improve this answer
1  
Presumably you mean s=re.split in the alternative? – xnor Jan 16 at 4:13
    
Yes! Definitely. This is my first time golfing ever, so any feedback and advice is appreciated. – Ogaday Jan 16 at 15:01
1  
1. The question explicitly allows to take the two strings as a list, so there seems to be no good reason for the * in *g. 2. The second version can be golfed down to lambda x,y,s=lambda s:re.split("[aeiou]",s)[0]:(s(y)+x[len(s(x)):],s(x)+y[len(s(y)):]). – Dennis Jan 16 at 15:54
    
Thanks @Dennis, that does indeed work, nice refactoring. Interesting that the brackets are needed, and you don't need to pass s as an arg to the second lambda do you? That solution gives me 98 bytes, with a leading import statement and f=. – Ogaday Jan 18 at 18:37
1  
No, s is a default argument, so you don't have to specify it. An unnamed lambda is an acceptable submission; f= is not required. – Dennis Jan 18 at 18:50

sed, 38 characters

s/([^aeiou]+)(.+ )([^aeiou]+)/\3\2\1/

Using extended regular expression from the Retina solution.

The above is 37 characters long and requires the -r switch (+1 character).

Example:

$ cat input | tee /dev/tty | sed -r 's/([^aeiou]+)(.+ )([^aeiou]+)/\3\2\1/'
plaster man
blushing crow
litigating more
strong wrangler
def ghi
master plan
crushing blow
mitigating lore
wrong strangler
ghef di
share|improve this answer
    
Welcome to Programming Puzzles & Code Golf! – Dennis Jan 17 at 14:28

𝔼𝕊𝕄𝕚𝕟, 24 chars / 42 bytes

ïē/⟮(⁅ᶌ]+)⟯(.+ )Ⅰ/,`⑶⑵⑴`

Try it here (Firefox only).

If you need help comprehending this, this translates to ES6 as

input.replace(/([^aeiou]+)(.+ )([^aeiou]+)/g,'$3$2$1')
share|improve this answer
    
What language is this in? I'm getting box-characters for even that. – Jesse Williams Jan 14 at 17:21
    
@JesseWilliams It's called ESMin. – ETHproductions Jan 14 at 17:46
    
It would be nice if the interperator had something like the Japt one where it shows you the js the 𝔼𝕊𝕄𝕚𝕟 becomes – Generic User Jan 17 at 13:34
    
Compiled JS is logged in the JS console when the code is run. – Mama Fun Roll Jan 17 at 17:12

PowerShell, 52 bytes

"$args "-replace('(.*?)([aeiou]\S+) '*2),'$3$2 $1$4'

e.g. 
PS C:\scripts\> .\Spoonerise.ps1 'blushing crow'
crushing blow

It's a regex replace with four capture groups; with:

  • String multiplication to expand:
    • ('(.*?)([aeiou]\S+) '*2) to '(.*?)([aeiou]\S+) (.*?)([aeiou]\S+) '
  • The "$args " forces the args array into a string, and adds a trailing space so the trailing space in the regex won't break it.
share|improve this answer

JavaScript (ES6), 120 107 102 101 99 92 bytes

  • Thanks downgoat!

This takes into account if the parameters were an object like this, and backward:
var a = {x: "man", y:"plaster"]}

a.b=(e=>e.slice(e.search`[aeiou]`));with(a){c=b(x),d=b(y),x=x.replace(c,d);y=y.replace(d,c)}
share|improve this answer
    
.match(/[aeiou]/).index can become: .search`[aeiou]` – Upgoat Jan 15 at 5:10

Python, 129 108 105 109 bytes

This program takes in a list of words like this ["master","plan"]

EDIT: Thanks @Volatility

EDIT: Now using re.split

import re
a=re.split
c='[aeiou]+'
i,j=input()
f=a(c,i)[0]
l=a(c,j)[0]
print i.replace(f,l,1),j.replace(l,f,1)

This answer uses regex as most of them do.

Try it here

share|improve this answer
    
Note that str.replace replaces all instances of a substring, so you want to limit it to one replacement by having .replace(f,l,1). However, you can save a bunch by using i,j=input(), and rebinding re.findall and '[^aeiou]+' to single character variables. – Volatility Jan 14 at 4:06
    
@Volatility Thanks! – TanMath Jan 14 at 4:08
    
This doesn't work as it is; even two one-letter words will give you three characters, and you're trying to unpack input() into two variables. Did you mean i,j=input().split() (and raw_input() in Python 2)? – Blacklight Shining Jan 16 at 4:03
1  
@BlacklightShining the word needs to have at least one vowel and one consonant. The input takes in a list of the strings so i is the first word and j is the second. – TanMath Jan 16 at 4:26
    
@TanMath as far as i know that is allowed by default, but you should probably say in the answer somewhere that it's required – undergroundmonorail Jan 16 at 4:26

Java 8, 343 Bytes

Here you have your first Java-Answer. Not that experienced with golfing, so every suggestion is appreciated!

java.util.function.Function;public class C{public static void main(String[] a){Function<String, Integer>f=s->{for(int i=0;i<s.length();++i)if("aeiou".contains(s.substring(i,i+1)))return i;return 0;};int i1=f.apply(a[0]),i2=f.apply(a[1]);System.out.println(a[1].substring(0,i2)+a[0].substring(i1)+" "+a[0].substring(0,i1)+a[1].substring(i2));}}

Ungolfed:

public class SpooneriseWords {
    public static void main(String[] args)
    {       
        Function<String, Integer> f = s -> {
            for(int i = 0; i < s.length(); ++i)
                if("aeiou".contains(s.substring(i, i + 1))) 
                    return i;
            return 0;
        };

        int i1 = f.apply(args[0]);
        int i2 = f.apply(args[1]);
        System.out.println(args[1].substring(0, i2) + args[0].substring(i1));
        System.out.println(args[0].substring(0, i1) + args[1].substring(i2));
    }
}
share|improve this answer
    
What's java.util.function.Function? I highly doubt it needs to be there, unless you mean import, but drop the import because you only refer to it once. Change public class C{public static void Main(String[] a) to interface C{void Main(String[]a) – cat Mar 5 at 23:34
    
Function<String, Integer> doesn't need whitespace – cat Mar 5 at 23:34
    
change the for loop from for(int i=0;i<s.length();++i)if("aeiou".contains(s.substring(i,i+1)))return i; to for(int i=0;i++<s.length();if("aeiou".contains(s.substring(i,i+1))){return i;}) – cat Mar 5 at 23:36
    
i1 is a terrible, far too long varname. – cat Mar 5 at 23:37
    
That is, change Function<String, Integer> to java.util.function.Function<String,Integer> and drop the import – cat Mar 5 at 23:39

Octave, 96 bytes

Thanks to Octave's inline assignments and 'index-anywhere' functionality, this entire thing is just the definition of a single, anonymous function. Basically, we reconstruct the spoonerized string while storing the cut-off points in a and b. I'm especially happy with the inline f function, which finds the cut-off point, and prevented me from having to use the whole 'find(ismember(a,b),1)' thing twice. Also, no regex :).

@(p,q)[q(1:(a=(f=@(m)find(ismember(m,'aeoui'),1))(q))-1),p(b=f(q):end),32,p(1:b-1),q(a:end)];
share|improve this answer

C#6, 165 bytes

string S(string a,string b){int i=V(a),j=V(b);return b.Remove(j)+a.Substring(i)+" "+a.Remove(i)+b.Substring(j);}int V(string s)=>s.IndexOfAny("aeiou".ToCharArray());

Expanded:

string S(string a,string b){
    int i=V(a),
        j=V(b);
    return b.Remove(j)+a.Substring(i)+" "+a.Remove(i)+b.Substring(j);
}
int V(string s)=>s.IndexOfAny("aeiou".ToCharArray());
share|improve this answer

TeaScript, 27 bytes

xg/(\w+)(.+ )(\w+)/,"$3$2$1

\w is actually [^aeiou].

share|improve this answer
    
Hang on, you changed the default \w regex meta to [^aeiou]? Why? – ETHproductions Jan 21 at 1:45
    
@ETHproductions when I was creating the custom char classes. I forgot that \w was already used by JavaScript. I'll change it back soon – Upgoat Jan 21 at 1:51

Elixir, 143 117 Bytes

s=fn w->String.split_at(w,elem(hd(Regex.run(~r/[aeiou]/,w,return: :index)),0))end
{v,w}=s.(a)
{x,y}=s.(b)
[x<>w,v<>y]

Split up the two strings (a, b) on the first vowel and construct new strings to return.

EDIT: Got a few bytes off by using pattern matching instead of clunky elem calls to get the values out of the tuples.

share|improve this answer

Java, 147 Bytes

I'm assuming just a function is fine too.

String s(String[]i){String r="[aeiou]",f=i[0].split(r)[0],s=i[1].split(r)[0];return s+i[0].substring(f.length())+" "+f+i[1].substring(s.length());}

split(regex) unfortunately consumes the delimiter, which means that I have to use substring to get the suffixes.

share|improve this answer

Pyth, 30 28 bytes

Takes input and gives output as a list of the two words.

ACm,Kh:d"[aeiou]"3.-dKQ+V_GH

Try it online.

share|improve this answer
    
I think you're looking for ACm,Kh:d"[aeiou]"3.-dKQ+V_GH. A assigns a two-element list to G and H, and C transposes. There may be something even better. – lirtosiast Jan 21 at 3:29
    
Awesome, thanks! – Luke Jan 21 at 15:14

Python (no regexes), 85 bytes

t=lambda s:s[1]in'aeiou'or-~t(s[1:])
lambda a,b:(b[:t(b)]+a[t(a):],a[:t(a)]+b[t(b):])

Sample run:

>>> t=lambda s:s[1]in'aeiou'or-~t(s[1:])
>>> lambda a,b:(b[:t(b)]+a[t(a):],a[:t(a)]+b[t(b):])
<function <lambda> at 0x7f495e534398>
>>> _('plaster', 'man')
('master', 'plan')

t is a recursive function that computes the index of the earliest vowel after the first character in its argument s. If the second character s[1] is a vowel, it evaluates to True, which has int value 1. Otherwise it makes a recursive call with the first character removed, and adds 1 to the resulting index using -~ (two’s complement of one’s complement). Finally, the results of t are used as indices for string slicing to compute the spoonerism.

share|improve this answer

GNU Awk 4.0, 48 characters

split($0,a,/\<[^aeiou]+/,s)&&$0=s[2]a[2]s[1]a[3]

Sample run:

bash-4.3$ for s in 'plaster man' 'blushing crow' 'litigating more' 'strong wrangler' 'def ghi'; do
>     echo -n "$s -> "
>     awk 'split($0,a,/\<[^aeiou]+/,s)&&$0=s[2]a[2]s[1]a[3]' <<< "$s"
> done
plaster man -> master plan
blushing crow -> crushing blow
litigating more -> mitigating lore
strong wrangler -> wrong strangler
def ghi -> ghef di
share|improve this answer

Lua, 80 bytes

function f(a)return a:gsub('([^aeiou]*)(.*)%s([^aeiou]*)(.*)','%3%2 %1%4'),''end

You can test it here.

Ungolfed:

function f( a )
    return a:gsub(
        '([^aeiou]*)(.*)%s([^aeiou]*)(.*)', -- Get non-vowels, anything else, space, repeat
        '%3%2 %1%4' -- Re-arrange captures
    ),'' -- Get rid of number of gsubs (1)
end

You need to print the output, of course, which would add some more bytes.

share|improve this answer
    
Is some of the whitespace at parentheses removable? – ETHproductions Jan 21 at 1:23
    
Good catch, it is. I always forget to do those things. – DavisDude Jan 21 at 1:38

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.