По заданной строке s найдите подстроку с k элементами, которая содержит максимальное количество гласных в списке [«a», «e», «i», «o», «u»]

#python #arrays #string #combinations #itertools

#python #массивы #строка #комбинации #itertools

Вопрос:

Учитывая строку s, я хочу найти подстроку длиной k, которая содержит максимальное количество гласных в списке [«a», «e», «i», «o», «u»] Пользователь может ввести строку s и ее длину k. Например, если s = «sfjfio» и k = 3, то выводом должна быть строка «fio». Если у меня есть несколько подстрок, удовлетворяющих этому условию, то выводом должна быть подстрока, которая начинается с наименьшего индекса. Если ни одна из подстрок не удовлетворяет требованиям, я хочу, чтобы на выходе была только исходная строка s обратно. Я начал с этого кода, но я немного запутался и застрял. Кажется, это работает, но не всегда дает правильный ответ, когда я пробую несколько примеров. Я только начал с python несколько дней назад и еще не очень хорошо осведомлен. Любая помощь была бы действительно замечательной!

 s = input("please enter s ")
k = input("please enter k ")

from itertools import combinations

allsubstrings = [s[a:b] for a, b in combinations(range(len(s)   1), r = 2)]
#if I am right this should give me all the possible substrings in s

#I will only take the ones of length k and put them in an array
substring = []
for i in allsubstrings:
    if len(i) == k:
        substring.append(i)

vowels = ["a", "e", "i", "o", "u"]
vowcount = []
#here I create an empty array to store the number of vowels in each substring

#now I will loop over each substring and check if it contains a vowel 
#I need to check if it contains each one of my vowels though I am not really sure if my code does that or just checks for one of the vowels
for j in substring:
    count = 0
    for i in vowels:
        if i in j:
            count = count   1
        vowcount.append(count)

#now I check the maximum number of vowels in a given substring
#since I am looping through the substrings in order their vowel count also gets stored in order in my vowcount array thus I can take the index of the max(vowcount) as the index of the substring j that satisfies the condition
if vowcount:
    if max(vowcount) != 0:
        print(substring[vowcount.index(int(max(vowcount)))])
else:
   print(s)
 

Комментарии:

1. Пожалуйста, приведите пример ввода, который дает неправильный результат, результат, который вы получаете, и результат, который вы ожидаете вместо этого.

2. В любом случае, я не понимаю, почему вы создаете все подстроки, а затем фильтруете их до подстрок соответствующей длины. Подсказка: можете ли вы придумать математическое правило, учитывая, что ваша подстрока s[a:b] и желаемая длина k относятся a к b ?

3. Я бы рекомендовал прочитать ericlippert.com/2014/03/05/how-to-debug-small-programs .

4. @KarlKnechtel Привет, Карл, это неудачный пример: s = ioosdfghjkaeibnffbjfbnfoii при k = 4 вывод должен быть «ioos», но программа возвращает полную строку s обратно

5. На самом деле для части s [a:b] я не совсем понимаю, что означают a или b? (Я только что скопировал его из документации) дает ли диапазон [a:b] мне длину, поскольку длина этого интервала равна длине моих подстрок? если это так, я мог бы сделать [0:k-1] ?

Ответ №1:

Для этого вам не нужны itertools, вы можете просто перебирать все возможные подстроки, которые начинаются с позиций 0 len(s)-k и имеют k длину символов. Вам также не нужно сохранять количество гласных для каждой подстроки, просто сохраняйте подстроку всякий раз, когда количество гласных превышает предыдущий максимум. Вы должны объединить свой код в функцию, чтобы упростить вызов различных комбинаций входных данных. Например:

 def max_vowels(s, k):
    vowels = ['a', 'e', 'i', 'o', 'u']
    # initialise our state variables
    vmax = -1     # maximum number of vowels seen in a subatring
    smax = ''     # the substring in which we found the maximum
    # iterate over all the possible substrings, which start from positions 0 to len(s)-k
    for i in range(len(s)-k 1):
        # extract the substring
        substr = s[i:i k]
        # count the number of vowels
        num_vowels = sum(1 if c in vowels else 0 for c in substr)
        # is it a new maximum count? if so, update our state
        if (num_vowels > vmax):
            vmax = num_vowels
            smax = substr
    # all substrings visited, return the one with the most vowels
    return smax
        
print(max_vowels('sfjfio', 3))
print(max_vowels('ioosdfghjkaeibnffbjfbnfoii', 4))
 

Вывод:

 fio
ioos
 

Ответ №2:

Вот альтернативный подход, который использует collections.Counter , если вам не разрешено использовать библиотечные методы, просто добавьте свою собственную логику для подсчета количества гласных в одной строке num_vowels_in_str ниже:

 from collections import Counter

def num_vowels_in_str(s):
    ch_counts = Counter(s.lower())
    return sum(ch_counts[ch] for ch in "aeiou")

s = input("Please enter s: ")
k = int(input("Please enter k: "))

k_length_substrs = [
    s[i:j]
    for i in range(len(s))
    for j in range(i   1, len(s)   1)
    if j - i == k
]

num_vowels_per_substr = [
    num_vowels_in_str(substring)
    for substring in k_length_substrs
]

max_vowels = max(num_vowels_per_substr)

result_index = next(
    i 
    for i, num_vowels in enumerate(num_vowels_per_substr)
    if num_vowels == max_vowels
)

result = k_length_substrs[result_index]
print(result)
 

Пример использования:

 Please enter s: sfjfio
Please enter k: 3
fio