I don't like strings with more than three vowels in a row. Can you write a program that removes all the vowels I don't want from words?
You may write a program or function, taking input via STDIN (or closest alternative), command-line argument or function argument and outputting the result via STDOUT (or closest alternative), function return value or function (out) parameter.
Input is a string containing only printable ASCII character (0x20 to 0x7E, inclusive).
Output is a string containing only runs of at most 3 consecutive vowels. If there is a run of more than 3 consecutive vowels in the input string, your program should produce an output string including the first three vowels encountered in that run, discarding any further consecutive vowels.
Y is not a vowel for the purposes of this challenge.
This is code golf, so the shortest code (in bytes) wins.
Test Cases
"Aeiou" => "Aei"
"screeeen" => "screeen"
"We're queueing up for the Hawaiian movie." => "We're queung up for the Hawaiin movie."
"Spaces break runs: aei iou." => "Spaces break runs: aei iou."
24 Answers 24
Unreadable, 1647 bytes
'"""""'""'""""""'"""'""""""'""'""'"""'""""""""""'"""""""""'"""""""""'""""""'"""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'"""""""'"""'"""""""""'""""""'"""'""""""""'""""""""'""""""""'""""""""'"""""""'"""'"""""""""'""""""'"""'""""""""'""""""""'""""""""'""""""""'"""""""'"""'"""""""""'""""""'"""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'"""""""'"""'"""""""""'""""""'"""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'"""""""'"""'"""""""""'""""""'"""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'"""""""'"""'"""""""""'""""""'"""'""""""""'""""""""'""""""""'""""""""'"""""""'"""'"""""""""'""""""'"""'""""""""'""""""""'""""""""'""""""""'"""""""'"""'"""""""""'""""""'"""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'"""""""'"""'"""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'"""""""'"""'""""""""'"""'"""'"""'"""'"""'"""'"""'"""'"""'"""'"""'"""""""""'""'""'""'""'""""""'""'"""'""""""""'"""""""'""'"""'"'"""""""'""'""'"""'""""""'""'"""'""'"""""""'""'"""'""""'"'"""""""'""'""'"""'""""""'""'"""'""""""""'"""
Explanation
This program is equivalent to pseudocode like this:
while (cp = (ch = read)) + 1 {
(
(cp -= 65) ? // A
(cp -= 4) ? // E
(cp -= 4) ? // I
(cp -= 6) ? // O
(cp -= 6) ? // U
(cp -= 12) ? // a
(cp -= 4) ? // e
(cp -= 4) ? // i
(cp -= 6) ? // o
(cp - 6) ? // u
0
: 1
: 1
: 1
: 1
: 1
: 1
: 1
: 1
: 1
: 1
) ? ((--vs)+4) ? print(ch) : (++vs) : {
print(ch)
vs = 0
}
}
with the following variable assignments:
0 (unused) (13 bytes)
1 cp ( 4 bytes; occurs ×ばつ in the code)
2 vs ( 7 bytes; occurs ×ばつ in the code)
3 ch (10 bytes; occurs ×ばつ in the code)
As you can see, I avoided variable slot 0 because 0
is such a long constant to write.
So we read each character and store the value in both cp
and ch
. We will modify cp
but keep ch
around so that we can print it if necessary. We successively subtract numbers 65, 4, 4, 6, etc. from cp
to check if it’s each of the 10 possible vowel characters in ASCII (note the very last one doesn’t need to be an assignment).
vs
always contains 3 less than the number of vowels still allowed to be printed. It starts out at 0
, so 3 vowels can be printed. When it reaches -3
, we stop printing vowels.
If we encounter a non-vowel (including the space), we execute print(ch)
followed by vs = 0
. As you have probably guessed, this resets the vowels counter.
If we encounter a vowel, we execute ((--vs)+4) ? print(ch) : (++vs)
. Let’s break this down:
- decrement
vs
; - if the value is now
-4
, we’ve gone too far, so don’t print anything, but incrementvs
back to-3
so we will continue to refuse to print vowels; - otherwise, print the character.
-
1\$\begingroup\$ This language is true to its name. \$\endgroup\$jqkul– jqkul2015年12月11日 07:46:38 +00:00Commented Dec 11, 2015 at 7:46
-
2\$\begingroup\$ I always wonder in these languages... "Did they actually write this out by hand? If so, I pity them..." +1 \$\endgroup\$Addison Crump– Addison Crump2015年12月11日 12:43:12 +00:00Commented Dec 11, 2015 at 12:43
Retina, 25 bytes
i`([aeiou]{3})[aeiou]+
1ドル
Fairly straightforward regex substitution. This also works for the same byte count:
Ri`(?<=[aeiou]{3})[aeiou]
-
5\$\begingroup\$ Finally! An online interpreter! You should consider linking to it on your github page. \$\endgroup\$mbomb007– mbomb0072015年12月11日 17:21:57 +00:00Commented Dec 11, 2015 at 17:21
JavaScript (ES6), 42
As an anonymous function
s=>s.replace(/[aeiou]+/gi,v=>v.slice(0,3))
Pyth, 21 bytes
sfg3=Z&}rT0"aeiou"hZz
Try it online: Demonstration or Test Suite
Explanation:
I iterate through all chars and keep track of how many vowels I passed using a counter. Every time I pass a char, which is not a vowel, I reset the counter to 0. I reomve chars, whenever the counter is> 4.
sfg3=Z&}rT0"aeiou"hZz implicit: z = input string
Z = 0
f z test every char T in z; keep chars, that return true:
rT0 convert T to lower
} "aeiou" test if T is a vowel
& hZ logical and with Z+1,
gives 0 if ^ is false, otherwise Z+1
=Z update Z with this value
g3 test if 3 >= Z
s sum up all remaining chars and print
Perl, 27 characters
(26 characters code + 1 character command line option)
s/[aeiou]{3}\K[aeiou]+//gi
Not a big deal, just a rare occasion I remember \K
exists.
Sample run:
bash-4.3$ perl -pe 's/[aeiou]{3}\K[aeiou]+//gi' <<< "
> Aeiou
> screeeen
> We're queueing up for the Hawaiian movie.
> Spaces break runs: aei iou."
Aei
screeen
We're queung up for the Hawaiin movie.
Spaces break runs: aei iou.
-
2\$\begingroup\$ When I wrote up the Retina answer I thought "I wish .NET regex had
\K
". :) \$\endgroup\$Martin Ender– Martin Ender2015年12月10日 15:15:19 +00:00Commented Dec 10, 2015 at 15:15 -
\$\begingroup\$ Interesting, @MartinBüttner. I had the feeling those regular expressions were put on serious steroid diet. For curiosity, do they have recursive subpattern? Can help to spare one vowel enumeration, though the result is longer:
s/([aeiou]{1,3})(?1)+/1ドル/gi
. \$\endgroup\$manatwork– manatwork2015年12月10日 15:49:01 +00:00Commented Dec 10, 2015 at 15:49 -
\$\begingroup\$ Unfortunately, they don't have pattern reuse either. Those are the two things that occasionally make me switch to Perl or PCRE. When I get around to patching some simple things into Retina's regex flavour, I think I'll add those (not true recursion, but at least pattern reuse and finite recursion). \$\endgroup\$Martin Ender– Martin Ender2015年12月10日 15:54:40 +00:00Commented Dec 10, 2015 at 15:54
APL, 40 chars
{⍵/⍨1↓4≠⊃+/(1-⍳4)⌽ ̈⊂'aeiouAEIOU'∊⍨' ',⍵}
In English:
'aeiouAEIOU'∊⍨' ',⍵
: find the vowels (and prepend a space to break on rotation);(1-⍳4)⌽ ̈⊂
: rotate 0, 1, 2, 3 times (with wrap-around) pushing to the right the boolean vector;⊃+/ sum
: the rotations and unbox1↓4≠
: find the different than 4, and remove the first one (to cather for the space we prepended)⍵/⍨
: in the argument, keep only the element where the sum was different than 4.
Tcl, (削除) 82 (削除ここまで) 56 bytes
Saved 26 bytes thanks to the comment of @naffetS
Golfed version. Try it online!
proc f s {regsub -all {(?i)([aeiou]{3})[aeiou]*} $s \1円}
Ungolfed version. Try it online!
proc remove_vowels {s} {
regsub -all -- {([aeiouAEIOU]{1,3})[aeiouAEIOU]*} $s {1円} result
return $result
}
puts [remove_vowels "Aeiou"]
puts [remove_vowels "screeeen"]
puts [remove_vowels "We're queueing up for the Hawaiian movie."]
puts [remove_vowels "Spaces break runs: aei iou."]
# "Aeiou" => "Aei"
# "screeeen" => "screeen"
# "We're queueing up for the Hawaiian movie." => "We're queung up for the Hawaiin movie."
# "Spaces break runs: aei iou." => "Spaces break runs: aei iou."
-
1\$\begingroup\$ Try it online! 56 bytes \$\endgroup\$naffetS– naffetS2023年05月10日 02:07:18 +00:00Commented May 10, 2023 at 2:07
C, 166 bytes
not the shortest answer by far but nicely golfed I think..
#define V v[1][i]!=
#define P printf("%c",v[1][i]),j
j;main(i,v)char**v;{for(i=0;V 0;i++)(V 97&V 'e'&V 'i'&V 'o'&V 'u'&V 65&V 69&V 73&V 79&V 85)?P=0:j>3?j++:P++;}
test case:
$ a.exe "We're queueing up for the Hawaiian movie."
We're queung up for the Hawaiin movie.
$ wc -c vowels.c
166 vowels.c
Javascript ES6, 43 chars
s=>s.replace(/([aeiou]{3})[aeiou]*/gi,"1ドル")
Test:
f=s=>s.replace(/([aeiou]{3})[aeiou]*/gi,"1ドル")
;`"Aeiou" => "Aei"
"screeeen" => "screeen"
"We're queueing up for the Hawaiian movie." => "We're queung up for the Hawaiin movie."
"Spaces break runs: aei iou." => "Spaces break runs: aei iou."`
.replace(/"/g,"").split("\n").every(s=>f((s=s.split(" => "))[0])==s[1])
Mathematica, 68 bytes
a=Characters@"aeiouAEIOU";StringReplace[#,b:a~Repeated~{3}~~a..:>b]&
The regex answer would be the same length, but who uses regex?
Java, 115 bytes
class a{public static void main(String[] a){System.out.println(a[0].replaceAll("(?i)([aeiou]{3})[aeiou]*","1ドル"));}}
Expects input as program parameter.
Unit test output:
Aei
screeen
We're queung up for the Hawaiin movie.
-
\$\begingroup\$ Save one byte by removing the space between
String[]
anda
.String[]a
\$\endgroup\$Poke– Poke2016年06月27日 19:23:01 +00:00Commented Jun 27, 2016 at 19:23 -
\$\begingroup\$ Save 2 bytes by using
print
rather thanprintln
. I don't believe the spec requires a trailing newline. \$\endgroup\$Poke– Poke2016年06月27日 19:26:00 +00:00Commented Jun 27, 2016 at 19:26
Thunno 2 Ṡ
, 24 bytes
Oı"([%]+)"kWDL+%ḄıDhṃ?3ɱ
Feel like maybe I'm doing something wrong
Explained
Oı"([%]+)"kWDL+%ḄıDhṃ?3ɱ
O # Split the input on spaces
ı # to each item in that:
"([%]+)"kWDL+%Ḅ # split on the regex ([AEIOUaeiou]+) - the () makes it so that the group is retained
ı # to each group:
Dhṃ? # if it starts with a vowel:
3ɱ # keep only the first three items
# Ṡ flag joins on spaces before printing
-
\$\begingroup\$ In 2.2.0, 11 bytes with
J
flag:µñṃıDJṃh?3ɱ
\$\endgroup\$The Thonnu– The Thonnu2023年05月14日 14:44:19 +00:00Commented May 14, 2023 at 14:44
Perl 6, (削除) 36 (削除ここまで) 35 bytes
(削除)
{S:g:i/(<[aeiou]>**3)<[aeiou]>+/0ドル/} # 36 bytes
(削除ここまで)
$ perl6 -pe 's:g:i/(<[aeiou]>**3)<[aeiou]>+/0ドル/' # 34 + 1 = 35 bytes
usage:
$ perl6 -pe 's:g:i/(<[aeiou]>**3)<[aeiou]>+/0ドル/' <<< "
> Aeiou
> screeeen
> We're queueing up for the Hawaiian movie.
> Spaces break runs: aei iou."
Aei
screeen
We're queung up for the Hawaiin movie.
Spaces break runs: aei iou.
C (205 bytes)
#include <stdio.h>
#define T(x)for(i=0;i<10;++i){if(v[i]==x){b=x;m=1;break;}}putchar(c);
main(b,c,i,m){char v[]="aeiouAEIOU";
while((c=getchar())!=EOF){if(!m){T(c);}else{if(b==c)continue;else{m=0;T(c);}}}}
(One line break added for clarity)
-
\$\begingroup\$ 136 bytes \$\endgroup\$ceilingcat– ceilingcat2020年03月09日 07:13:49 +00:00Commented Mar 9, 2020 at 7:13
Scala, 107 bytes
readLine.foldLeft("",0)((a,n)=>if(!"aeiou".contains(n|32))a._1+n->0 else if(a._2>2)a else(a._1+n,a._2+1))_1
Seriously, 34 bytes
,;ù0╗`Ok"aeiou"Okd-Y;╜+*;╗4>`M@░εj
Hex Dump:
2c3b9730bb604f6b226165696f75224f6b
642d593bbd2b2a3bbb343e604d40b0ee6a
It uses the same algorithm as the Pyth answer, mapping over the string while keeping track of the length of the current run of vowels in a register, incrementing it whenever the current character is a vowel, and checking whether it has exceeded the allowed length, returning 0 if so, and then filtering the original string with this generated filter. It will be a lot shorter once we can use set subtraction on strings. (The Ok
can be deleted and the Okd
can be replaced with just @
). I hear this feature is coming in the next update....
x86 MS-DOS .COM file, (削除) 44 bytes (削除ここまで) 36 bytes
.COM files are widely supported from MS-DOS 1 through the present---I'm running in dosemu, using 8086 commands only.
Reduced from 44 to 36 bytes by using REPNE SCASB to test for vowels instead of using a separate command to test each vowel.
Hex dump, reversible using `xxd -r -seek -256`:
0100: b3 03 43 b4 08 cd 21 88 c2 24 df b1 05 bf 1f 01 ..C...!..$......
0110: f2 ae 74 02 b3 05 4b 74 e9 b4 02 cd 21 eb e4 41 ..t...Kt....!..A
0120: 45 49 4f 55 EIOU
Unassembled using debug:
0100 B303 MOV BL,03 ; initialize counter to 3 (will increment by 1 to be 4)
0102 43 INC BX ; increment counter--runs each time it hits 0 so it never goes <0
0103 B408 MOV AH,08 ;
0105 CD21 INT 21 ; with AH=8, read 1 char without echo
0107 88C2 MOV DL,AL ; copy input for potential output
0109 24DF AND AL,DF ; make input uppercase for testing
010B B105 MOV CL,05 ; count of 5 vowels to test against
010D BF1F01 MOV DI,011F ; location of first vowel to test against
0110 F2AE REPNE SCASB ; test input against each vowel
0112 7402 JZ 0116 ; if input was not a vowel:
0114 B305 MOV BL,05 ; reset counter to 5 (will decrement by 1 to be 4)
0116 4B DEC BX ; decrement counter regardless
0117 74E9 JZ 0102 ; if hit 0 (fourth or later vowel): goto 102
0119 B402 MOV AH,02 ;
011B CD21 INT 21 ; with AH=2, print char
011D EBE4 JMP 0103 ; go to 103 for next character
bytes 011f-0123 contain the uppercase vowels AEIOU
Matlab / Octave, 54 bytes
@(s)regexprep(s,'(?<=[aeiouAEIOU]{3})[aeiouAEIOU]','')
Example:
>> @(s)regexprep(s,'(?<=[aeiouAEIOU]{3})[aeiouAEIOU]','')
ans =
@(s)regexprep(s,'(?<=[aeiouAEIOU]{3})[aeiouAEIOU]','')
>> ans('We''re queueing up for the Hawaiian movie.')
ans =
We're queung up for the Hawaiin movie.
V, 21 bytes (noncompeting)
ñ[aeiou]ñÍãqû3}úsq*
Explanation:
ñ[aeiou]ñ "Assign the string `[aeiou]` to register 'q'
Íã "Search and replace on multiple lines (case insensitive):
<C-r>q "Register 'q'
û3} "Repeated 3 times
ús "Mark the following to be removed:
<C-r>q* "Register 'q' repeated any number of times
This is just barely shorter than the more straightforward solution:
Íã[aeiou]û3}ús[aeiou]*
(22 bytes)
Jelly, (削除) 12 (削除ここまで) 11 bytes
ḟ€ØckŻḣ4ドルFḊ
Copy-paste from my answer to a similar challenge, except somehow even worse. e€Øc×ばつ\\<4x@
is nicer for one more byte (check edit history for an explanation).
€ For each character of the input,
ḟ filter out
Øc vowels.
Ż Prepend a 0 to the input, and
k partition that after truthy (nonempty) positions in the original.
ḣ4ドル Keep the first 4 elements of each slice,
F flatten the slices,
Ḋ and remove the 0.
Ruby, 44 bytes
><<$<.read.gsub(/([aeiou]{3})[aeiou]+/i,'1円')
Example:
% ruby -e "$><<$<.read.gsub(/([aeiou]{3})[aeiou]+/i,'1円')" <<< "
Aeiou
screeeen
We're queueing up for the Hawaiian movie.
Spaces break runs: aei iou."
Aei
screeen
We're queung up for the Hawaiin movie.
Spaces break runs: aei iou.
-
\$\begingroup\$ You wrote it: "Input is a string containing only printable ASCII character (0x20 to 0x7E, inclusive)." Then why spending extra characters with
$<.read
to make it handle multiline input (thus containing out of range character 0x0a) instead ofgets
? \$\endgroup\$manatwork– manatwork2015年12月15日 16:24:50 +00:00Commented Dec 15, 2015 at 16:24 -
\$\begingroup\$ @manatwork that's a really good point, thank you! Think it might save 2-3 bytes :) \$\endgroup\$Joseph Weissman– Joseph Weissman2015年12月15日 16:38:09 +00:00Commented Dec 15, 2015 at 16:38
aaYYAAaaaAERGH
. \$\endgroup\$