21
\$\begingroup\$

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."
user3094403
8,3757 gold badges46 silver badges71 bronze badges
asked Dec 10, 2015 at 14:49
\$\endgroup\$
1
  • 2
    \$\begingroup\$ You should include some more tests with mixed cases, like aaYYAAaaaAERGH. \$\endgroup\$ Commented Dec 11, 2015 at 1:20

24 Answers 24

11
\$\begingroup\$

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 increment vs back to -3 so we will continue to refuse to print vowels;
  • otherwise, print the character.
answered Dec 10, 2015 at 21:12
\$\endgroup\$
2
  • 1
    \$\begingroup\$ This language is true to its name. \$\endgroup\$ Commented 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\$ Commented Dec 11, 2015 at 12:43
10
\$\begingroup\$

Retina, 25 bytes

i`([aeiou]{3})[aeiou]+
1ドル

Try it online.

Fairly straightforward regex substitution. This also works for the same byte count:

Ri`(?<=[aeiou]{3})[aeiou]
answered Dec 10, 2015 at 14:53
\$\endgroup\$
1
  • 5
    \$\begingroup\$ Finally! An online interpreter! You should consider linking to it on your github page. \$\endgroup\$ Commented Dec 11, 2015 at 17:21
8
\$\begingroup\$

JavaScript (ES6), 42

As an anonymous function

s=>s.replace(/[aeiou]+/gi,v=>v.slice(0,3))
answered Dec 10, 2015 at 20:41
\$\endgroup\$
6
\$\begingroup\$

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
answered Dec 10, 2015 at 19:54
\$\endgroup\$
5
\$\begingroup\$

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.
answered Dec 10, 2015 at 15:13
\$\endgroup\$
3
  • 2
    \$\begingroup\$ When I wrote up the Retina answer I thought "I wish .NET regex had \K". :) \$\endgroup\$ Commented 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\$ Commented 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\$ Commented Dec 10, 2015 at 15:54
3
\$\begingroup\$

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 unbox
  • 1↓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.
answered Jun 27, 2016 at 16:59
\$\endgroup\$
3
\$\begingroup\$

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."
answered May 6, 2023 at 6:08
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Try it online! 56 bytes \$\endgroup\$ Commented May 10, 2023 at 2:07
2
\$\begingroup\$

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
answered Dec 11, 2015 at 15:41
\$\endgroup\$
2
\$\begingroup\$

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])
answered Dec 15, 2015 at 18:51
\$\endgroup\$
2
\$\begingroup\$

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?

answered Dec 11, 2015 at 11:45
\$\endgroup\$
2
\$\begingroup\$

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.
answered Jun 6, 2016 at 13:30
\$\endgroup\$
2
  • \$\begingroup\$ Save one byte by removing the space between String[] and a. String[]a \$\endgroup\$ Commented Jun 27, 2016 at 19:23
  • \$\begingroup\$ Save 2 bytes by using print rather than println. I don't believe the spec requires a trailing newline. \$\endgroup\$ Commented Jun 27, 2016 at 19:26
2
\$\begingroup\$

Arturo, 44 bytes

$=>[replace&{/(?i)([aeiou]{3})[aeiou]+}"1ドル"]

Try it

answered May 5, 2023 at 23:40
\$\endgroup\$
2
\$\begingroup\$

Vyxal s, 60 bits1, 7.5 bytes

(AḊƛAa[3Ẏ

Try it Online!

answered May 6, 2023 at 4:14
\$\endgroup\$
2
\$\begingroup\$

Japt, 9 bytes

r"%v+"È ̄3

Try it

r"%v+"È ̄3 :Implicit input of string
r :Replace
 "%v+" :RegEx /[aeiou]+/gi
 È :Pass each match through the following function
 ̄3 : Slice to length 3
answered May 5, 2023 at 23:49
\$\endgroup\$
2
\$\begingroup\$

Thunno 2 , 24 bytes

Oı"([%]+)"kWDL+%ḄıDhṃ?3ɱ

Attempt This Online!

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
answered May 14, 2023 at 13:22
\$\endgroup\$
1
  • \$\begingroup\$ In 2.2.0, 11 bytes with J flag: µñṃıDJṃh?3ɱ \$\endgroup\$ Commented May 14, 2023 at 14:44
1
\$\begingroup\$

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.
answered Dec 10, 2015 at 18:17
\$\endgroup\$
1
\$\begingroup\$

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)

answered Dec 10, 2015 at 18:46
\$\endgroup\$
1
  • \$\begingroup\$ 136 bytes \$\endgroup\$ Commented Mar 9, 2020 at 7:13
1
\$\begingroup\$

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
answered Dec 11, 2015 at 5:44
\$\endgroup\$
1
\$\begingroup\$

Seriously, 34 bytes

,;ù0╗`Ok"aeiou"Okd-Y;╜+*;╗4>`M@░εj

Hex Dump:

2c3b9730bb604f6b226165696f75224f6b
642d593bbd2b2a3bbb343e604d40b0ee6a

Try it online

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

answered Dec 11, 2015 at 17:10
\$\endgroup\$
1
\$\begingroup\$

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
answered Dec 12, 2015 at 22:11
\$\endgroup\$
1
\$\begingroup\$

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.

Try it at ideone.

answered Dec 10, 2015 at 23:29
\$\endgroup\$
1
\$\begingroup\$

V, 21 bytes (noncompeting)

ñ[aeiou]ñÍãqû3}úsq*

Try it online!

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)

answered Jun 7, 2016 at 19:30
\$\endgroup\$
1
\$\begingroup\$

Jelly, (削除) 12 (削除ここまで) 11 bytes

ḟ€ØckŻḣ4ドルFḊ

Try it online!

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.
answered May 6, 2023 at 4:46
\$\endgroup\$
0
\$\begingroup\$

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.
Doorknob
72k20 gold badges146 silver badges392 bronze badges
answered Dec 12, 2015 at 17:33
\$\endgroup\$
2
  • \$\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 of gets? \$\endgroup\$ Commented Dec 15, 2015 at 16:24
  • \$\begingroup\$ @manatwork that's a really good point, thank you! Think it might save 2-3 bytes :) \$\endgroup\$ Commented Dec 15, 2015 at 16:38

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.