# ANNNOUNNNCCCEEERRR VOICCCEEE

Write a function that takes a string of letters and spaces (no need to handle non-letters) and performs the ANNOUNCER VOICE translation algorithm as follows:

• First, uppercase everything.
• For each word,
• Elongate each consonant cluster by tripling each letter; except, if the word begins with a consonant cluster, do not elongate that cluster. For example, other should become OTTTHHHEEERRR but mother should become MOTTTHHHEEERRR.
• Elongate the final vowel by tripling it.
• In both cases of elongation, if you're tripling a letter, first coalesce it with duplicate letters on either side. For example, hill should become HIIILLL and bookkeeper should become BOOKKKEEPPPEEERRR.
• For the purposes of this challenge, y counts as a consonant.
• Clarification/simplification: You may assume that each pair of words is separated by a single space, and that the input contains no consecutive spaces, and that the input will not be the empty string.
• Shortest code wins!

Test vectors:

> sunday sunday
SUNNNDDDAAAYYY SUNNNDDDAAAYYY
> mia hamm
MIAAA HAAAMMM
> chester alan arthur
CHESSSTTTEEERRR ALLLAAANNN ARRRTTTHHHUUURRR
ATTTENNNTTTIOOONNN PLEASSSEEE
> supercalifragilisticexpialidocious
SUPPPERRRCCCALLLIFFFRRRAGGGILLLISSSTTTICCCEXXXPPPIALLLIDDDOCCCIOUUUSSS
> moo
MOOO
> Aachen
AACCCHHHEEENNN
> Oooh
OOOHHH
> grifffest
GRIFFFEEESSSTTT
> k
K
> aaaabbbbc
AAAABBBBCCC


Here's a reference implementation which I would move to an answer except that as of this morning the question's been closed. :P

import itertools,re
def j(s):return re.match('^[AEIOU]+$',s) def c(s):return ''.join(sum(([h,h,h]for h in[k for k,g in itertools.groupby(s)]),[])) def v(s): while len(s)>=2 and s[-2]==s[-1]:s=s[:-1] return s+s[-1]+s[-1] def a(n): r='' for w in n.split(): if r:r+=' ' ss=re.split('([AEIOU]+)', w.upper()) for i,s in enumerate(ss): r += [v(s),s][any(j(t) for t in ss[i+1:])]if j(s)else[s,c(s)][i>0] return r while 1:print a(raw_input('> '))  • A request for the future: please avoid words and phrases like consonant cluster, coalesce, and elongation. A non-native English speaker like myself might need a dictionary to understand your post. Jul 21 '17 at 15:51 • It should be the vowels that are "elongated" :( Jul 21 '17 at 19:56 • What is consonant cluster? Nov 11 '18 at 20:41 ## 6 Answers # APL (Dyalog), 175 bytes 1↓' +'⎕R' '⊢'[AEIOU][^AEIOU]+ '⎕R{m/⍨1,3×2≠/m←⍵.Match}'([AEIOU])\1*([^AEIOU]*? )' ' [AEIOU]' ' [^ AEIOU]+' '([^AEIOU ])\1*'⎕R'\1\1\1\2' '&' '&' '\1\1\1'⊢'$| |^'⎕R'  '⊢1(819⌶)⍞


Try it online!

⍞ prompt for character input

1(819⌶) convert to uppercase (819 ≈ Big)

⊢ pass the result further (serves to separate the strings and the 1)

'$| |^'⎕R' 'Replace: the end, any space, and the beginning → two spaces ⊢ pass the result further (serves to separate two groups of strings) '([AEIOU])\1*([^AEIOU]*? )' ' [AEIOU]' ' [^ AEIOU]+' '([^AEIOU ])\1*'⎕R'\1\1\1\2' '&' '&' '\1\1\1'Replace: any number of identical vowels and any number of non-vowels and a space → the vowel thrice and the unmodified consonants a space and a vowel → themselves a space and a consonant cluster → themselves a run of identical consonants → three of those vowels '[AEIOU][^AEIOU]+ '⎕R{}Replace: a run of non-vowels and a space → the result of the following anonymous function with the namespace ⍵ as argument: ⍵.Match the text that was found m← assign that to m 2≠/ pair-wise different-from 3× multiply by three 1, prepend one m/⍨ use that to replicate m ⊢ pass the result further (serves to separate two strings) ' +'⎕R' 'Replace: one or more spaces → with a single space 1↓ drop the initial letter (a space) • Does this work? 1↓' +'⎕R' '⊢'[AEIOU][^AEIOU]+ '⎕R{m/⍨1,3×2≠/m←⍵.Match}'([AEIOU])\1*([^AEIOU]*? )' ' [AEIOU]' ' [^ AEIOU]+' '([^AEIOU ])\1*'⎕R(s,'\2')'&' '&'(s←6⍴'\1')⊢'$| |^'⎕R' '⊢1(819⌶)⍞ Jul 20 '17 at 20:34
• ^ Saves two bytes if it works ^ Jul 20 '17 at 20:35

# APL, 90 bytes

{1↓∊{s←{⍵⊂⍨1,2≠/⍵}⋄x↑⍨¨(3⌈≢¨s⍵)⌊≢¨x←s⍵/⍨(1+2×{⌽<\⌽⍵}∨~∧∨\)⍵∊'AEIOU'}¨w⊂⍨w=⊃w←' ',1(819⌶)⍵}


Explanation:

• 1(819⌶)⍵: convert to uppercase
• w⊂⍨w=⊃w←' ',: split on spaces
• {...}¨: for each word...
• s←{⍵⊂⍨1,2≠/⍵}: s is a function that splits a string into groups of contiguous matching characters
• ⍵∊'AEIOU': mark the vowels
• (...): see which characters to triplicate
• ~∧∨\: all consonants past the first vowel,
• {⌽<\⌽⍵}: the last vowel.
• 2×: multiply the bit vector by two,
• 1+: and add one. Now all selected characters have 3 and the rest have 1.
• ⍵/⍨: replicate each character in ⍵ by the given amount
• x←s: split it up into strings of matching characters, and store this in x.
• (3⌈≢¨s⍵): the length of each group of matching characters in the input word, with a maximum of 3.
• ⌊≢¨: the minimum of that and the lengths of the groups in x.
• x↑⍨¨: make each group be that length
• 1↓∊: flatten the result and drop the first character (the space that was added at the beginning to help with splitting)
• You beat Adám ... wow. Jul 21 '17 at 23:32
• very neat! If you shuffle it around a bit and write it as a program (using prompt as suggested by Adám) you can shave off another 15 bytes: 1↓∊{c/⍨(≢¨g)⌈3×((⌽<\∘⌽)∨~∧∨\)'AEIOU'∊⍨c←⊃¨g←⍵⊂⍨1,2≠/⍵}¨w⊂⍨w=⊃w←' ',1(819⌶)⍞
– Gil
Aug 24 '17 at 22:26

# JS (ES6), 138134 129 bytes

s=>s.toUpperCase()[r="replace"](/(\w)\1/g,"$1")[r](/[AEIOU](?=[^AEIOU]*( |$))/g,s=>s+s+s)[r](/\B./g,s=>/[AEIOU]/.test(s)?s:s+s+s)


WAAAYYY TOOO MAAANNNYYY BYYYTTTEEESSS. Contains AEIOU 3 times, but I can't golf those into one.

-4 bytes thanks to HyperNeutrino

### Ungolfed

function v(str){
return str.toUpperCase().replace(/(\w)\1/g,"$1").replace(/[AEIOU](?=[^AEIOU]*( |$))/g,s=>s+s+s).replace(/\B./g,s=>[..."AEIOU"].includes(s)?s:s+s+s);
}


I like to write, not read code.

• "WAAAYYY TOOO MAAANNNYYY BYYYTTTEEESSSS" ... is in first place, ahead of APL. Jul 20 '17 at 20:49
• I don't know JS, but can you replace s=>/[AEIOU]/.test(s) with /[AEIOU]/.test? Jul 20 '17 at 21:44
• @musicman523 sadly, no, because it is the conditional in a ternary operator statement.
– ABot
Jul 20 '17 at 22:27
• FYI, your handling of consonant clusters appears to be slightly incorrect; the proper output would be WAAAYYY TOOO MAAANNNYYY BYTEEESSS (i.e. don't elongate the initial cluster BYT). Jul 20 '17 at 22:47
• Well, was in first place. Jul 21 '17 at 23:34

## Python, 417 bytes

Here's a reference implementation in Python. Not terribly golfed.

import itertools,re
def j(s):return re.match('^[AEIOU]+$',s) def c(s):return ''.join(sum(([h,h,h]for h in[k for k,g in itertools.groupby(s)]),[])) def v(s): while len(s)>=2 and s[-2]==s[-1]:s=s[:-1] return s+s[-1]+s[-1] def a(n): r='' for w in n.split(): if r:r+=' ' ss=re.split('([AEIOU]+)',w.upper()) for i,s in enumerate(ss): r+=[v(s),s][any(j(t) for t in ss[i+1:])]if j(s)else[s,c(s)][i>0] return r  Test with: while True: print a(raw_input('> '))  • Shouldn't you at least golf it down further a little by removing unnecessary spaces and changing ss to S? Jul 21 '17 at 19:11 # Python 3, 238 bytes def f(s): s=s.upper();k=[s[0]];s=''.join(k+[s[i]for i in range(1,len(s))if s[i]!=s[i-1]]) for i in range(1,len(s)):k+=[s[i]]*(3-2*(s[i]in'AEIOU'and i!=max(map(s.rfind,'AEIOU')))) return''.join(k) print(' '.join(map(f,input().split())))  Try it online! • Can you save bytes by setting v to 'AEIOU'? Jul 20 '17 at 20:33 • @Zacharý Thanks, but unfortunately it doesn't change the bytecount. Jul 20 '17 at 20:34 • Oh, the spaces around the first v. Jul 20 '17 at 20:37 # Perl 5, 139 + 1 (-p) = 140 bytes $_=uc,s/^([^AEIOU]*)//,$s=$1,s/([^AEIOU])\1*/$1x(($q=length$&)>3?$q:3)/ge,s/.*?\K([AEIOU])\1*/$1x(($q=length$&)>3?$q:3)/e,print"$s$_ "for@F


Try it online!

Even handles the "aaaabbbbc" test case in accordance with the example.