WhyWhyWhy
WhyWhyWhy

Reputation: 63

Find every two (non-overlapping) vowels inbetween consonants

Task You are given a string . It consists of alphanumeric characters, spaces and symbols(+,-). Your task is to find all the substrings of the origina string that contain two or more vowels. Also, these substrings must lie in between consonants and should contain vowels only.

Input Format: a single line of input containing string .

Output Format: print the matched substrings in their order of occurrence on separate lines. If no match is found, print -1.

Sample Input: rabcdeefgyYhFjkIoomnpOeorteeeeet

Sample Output:

ee
Ioo
Oeo
eeeee


The challenge above was taken from https://www.hackerrank.com/challenges/re-findall-re-finditer

The following code passes all the test cases:

import re

sol = re.findall(r"[^aiueo]([aiueoAIUEO]{2,})(?=[^aiueo])", input())

if sol:
    for s in sol:
        print(s)
else:
    print(-1)

The following doesn't.

import re

sol = re.findall(r"[^aiueo]([aiueoAIUEO]{2,})[^aiueo]", input())

if sol:
    for s in sol:
        print(s)
else:
    print(-1)

The only difference beteen them is the final bit of the regex. I can't understand why the second code fails. I would argue that ?= is useless because by grouping [aiueoAIUEO]{2,} I'm already excluding it from capture, but obviously I'm wrong and I can't tell why.

Any help?

Upvotes: 6

Views: 2441

Answers (3)

Rafayet Ullah
Rafayet Ullah

Reputation: 1158

You can use re.IGNORECASE our re.I flag to ignore case sensitivity. Also, you can avoid vowels, digits from alphanumeric characters and space, + and - characters mentioned in the problem.

import re

vowels = re.findall(r"[^aeiou\d\s+-]([aeiou]{2,})(?=[^aeiou\d\s+-])", input(), re.I)
if len(vowels):
    for vowel in vowels:
        print(vowel)
else:
    print("-1")

Upvotes: 0

ConstantStranger
ConstantStranger

Reputation: 1

Here's an alternative solution that doesn't require using the special () characters for grouping, relying instead on a "positive lookbehind assertion" with (?<=...) RE syntax:

import re
sol=re.findall(r"(?<=[QWRTYPSDFGHJKLZXCVBNMqwrtypsdfghjklzxcvbnm])[AEIOUaeiou]{2,}(?=[QWRTYPSDFGHJKLZXCVBNMqwrtypsdfghjklzxcvbnm])", input())
if sol:
    print(*sol, sep="\n")
else:
    print(-1)

Upvotes: 0

Sebastian Proske
Sebastian Proske

Reputation: 8413

The lookahead approach allows the consonant that ends one sequence of vowels to start the next sequence, whereas the non-lookahead approach requires at least two consonants between those sequences (one to end a sequence, another to start the next, as both are matched).

See

import re
print(re.findall(r'[^aiueo]([aiueoAIUEO]{2,})(?=[^aiueo])', 'moomoom'))
print(re.findall(r'[^aiueo]([aiueoAIUEO]{2,})[^aiueo]', 'moomoom'))

Which will output

['oo', 'oo']
['oo']

https://ideone.com/2Wn1TS

To be a bit picky, both attempts aren't correct regarding your problem description. They allow for uppercase vowels, spaces and symbols to be separators. You might want to use [b-df-hj-np-tv-z] instead of [^aeiou] and use flags=re.I

Upvotes: 8

Related Questions