I am creating a function
The return string will have the same number of words as the input string, and the same letters as the input string, but the individual words can be of different length. ie
perm_lets("try this") == "ist thry"
is a valid return-value. By "number of words" in a string X
, we mean the length of the list X.split(' ')
, ie one more than the number of blank spaces in the string. A "word" means a string of letters with no spaces. Lastly,
My function can only shuffle the letters of the input string. I would like to know how to isolate the vowel
import random as rd
def perm_lets(input_string):
nS = ''.join(rd.sample(input_string,len(input_string)))
print(nS)
I expect the output of perm_lets("this is a loop") to be something like "si olo pit ahs" but the actual output is " ph siioaos lt" (spaces in the wrong place and vowels are not isolated).
Brute force randomization with disqualifying tests:
import re
import random
import time
def perm_lets(s):
s = list(s)
start = time.perf_counter()
while True:
random.shuffle(s)
p = ''.join(s)
if ' ' in p: continue # no spaces together
if p.startswith(' ') or p.endswith(' '): continue # don't start or end with space
if re.search(r'[aeiou]{2}',p): continue # no vowels together
elapsed = time.perf_counter() - start
return p,elapsed
print(perm_lets('this is a loop'))
print(perm_lets('i bid you adieu'))
Output (4 runs):
('sopihats o i l', 0.0009378000000026532)
('ade udo ibiyi u', 0.07766600000000068)
('i o ha tpsislo', 0.00026450000000011187)
('o adebudu iyi i', 0.00632540000000148)
('o la sstipi ho', 5.2900000000022374e-05)
('udobida eyi i u', 0.3843909999999937) # 1/3 of a second for a tough sentence
('ipa hts o soli', 0.00028810000000589753)
('idida e obu uyi', 0.18083439999999484)
Note: "adieu louie" has no solution.
Here is one way to attempt what you are after. Separates vowels from consonants, shuffles them for randomness, zips vowels and consonants in a poor attempt to isolate the vowels (but this will fail if there are too many more vowels than consonants), randomly selects word length ensuring minimum of one character per word and that the number of output words is the same as the number of input words.
You could probably do a better job isolating vowels by generating more single vowel words when necessary. However, depending on the vowel to consonant ratio and the number of words, there will always be scenarios where you can't both isolate vowels and output the desired number of words.
from itertools import chain, zip_longest
from random import randint, random, shuffle
s = 'this is a loop'
vowels = []
consonants = []
for char in s.replace(' ', ''):
if char in 'aeiouAEIOU':
vowels.append(char)
else:
consonants.append(char)
shuffle(vowels)
shuffle(consonants)
if len(vowels) > len(consonants) or random() > 0.5:
a, b = vowels, consonants
else:
a, b = consonants, vowels
letters = ''.join([c for c in chain.from_iterable(zip_longest(a, b)) if c])
words = []
for i in range(s.count(' '), -1, -1):
x = randint(1, len(letters) - i)
words.append(letters[:x])
letters = letters[x:]
s = ' '.join(words)
print(s)
# EXAMPLE RANDOM OUTPUT:
# si hipa lo tos
you can do it like this also
import random
import re
def perm_lets(st):
ls = re.findall(r"([aeiouAEIOU])|(.)", st)
vs, cs = [c for c,_ in ls if len(c)>0], [v for _,v in ls if len(v)>0]
positions = list(range(len(cs)))
result = ""
for v in vs:
if len(positions)==0:
cs.append(" "+v)
else:
p = random.choice(positions)
positions.remove(p)
cs[p//2] += v
while True:
random.shuffle(cs)
result = "".join(cs)
if not (result.startswith(" ") or result.endswith(" ") or " " in result):
break
return result
print(perm_lets("this is a loop"))
print(perm_lets("teis iou")) # more vowels than consonants
Output
tp so hal osii
si u tei o
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.