6
respostas

Escreva um programa que imprima a maior substring de s em que as letras ocorram em ordem alfabética

Seja s uma string com todos os caracteres minúsculos.

Escreva um programa que imprima a maior substring de s em que as letras ocorram em ordem alfabética. Por exemplo:

s = 'azcbobobegghakl'

O programa deve imprimir: beggh

Em caso de haver empates, imprima a primeira substring: Por exemplo: s = 'abcbcd, o programa deve imprimir abc

Eu tentei mas não saiu nada funcional:

#s = 'azcbobobegghakl'
s = "abcdeka"
indice =0
palavra = ""
resposta = ""

while indice < len(s)-1:
    if s[indice] <=s[indice +1] :
        palavra += s[indice]
        indice +=1
    indice +=1
print(palavra)

Poderiam ajudar?

6 respostas

Oi, Edson! Tudo bem? Esse desafio é bem legal! Meu código ficou assim:

s = 'azcbobobegghakl'
sub_lista = []
sub = s[0]

for letra in s[1:]:
    if letra >= sub[-1]:
        sub += letra
    else:
        sub_lista.append(sub)
        sub = letra
sub_lista.append(sub)

maior_sub = max(sub_lista, key=len)
print(maior_sub)

E o resultado fica:

beggh

Basicamente, temos três variáveis: a string original s, a lista de todas as substrings em ordem alfabética sub_lista e a substring temporária sub que conterá cada uma das substrings que irão para a lista sub_lista.

Primeiro, definimos que sub é o primeiro caractere da string original, apenas pra facilitar nosso código. Aí começamos a iterar pela string original, começando do segundo caractere (z). Se o caractere atual da iteração for maior ou igual ao último caractere da subtring temporária, daí adicionamos ele à substring. Se não for, então essa substring acaba aí, o que significa que podemos mandá-la para nossa lista e resetar a substring temporária.

Ao final da iteração, temos uma lista com todas as substrings em ordem alfabética. Para pegarmos a mais longa, usamos a função nativa max, que pode ter um atributo key, em que espeficicamos uma função que definirá qual valor é maior. No nosso caso, especificamos que queremos com base na função len(), que retorna o comprimento da string, e por isso temos o resultado correto.

Espero que tenha ficado claro, abraços e bons estudos! Se achou outra solução mais legal, pode deixar aqui também! Essa foi a minha :)!

@Yan Orestes: Obrigado!

#s = "azcbobobegghakl"
s = "abcbcd"
indice = 0
palavra = ""
resposta = ""

maior_palavra = ""
while indice < len(s) - 1:

    if palavra == "":
        palavra = s[indice]
        if len(palavra) > len(maior_palavra):
            maior_palavra = palavra

    if s[indice] <= s[indice + 1]:
        palavra += s[indice + 1]
        if len(palavra) > len(maior_palavra):
            maior_palavra = palavra

    else:
        palavra = ''
    indice += 1

print(maior_palavra)  # beggh

Este código eu não entendi principalmente a parte de reduce:

from functools import reduce

def achar_maior_sequencia(s):

    maior_sequencia = ''

    def achar_sequencia(sequencia_atual: str, proximo: str):
        nonlocal maior_sequencia

        # Se não for alfanumérico, quebrar a sequencia
        if not proximo.isalnum():
            if len(sequencia_atual) > len(maior_sequencia):
                maior_sequencia = sequencia_atual
            return ''

        # Se não houver sequência, a sequência passa a ser o único caracter
        if sequencia_atual == '':
            return proximo

        # Se a última letra da sequência atual for menor ou igual do que
        # a próxima letra, adicionamos a letra à sequencia atual
        if sequencia_atual[-1] <= proximo:
            if len(sequencia_atual) > len(maior_sequencia):
                maior_sequencia = sequencia_atual
            return sequencia_atual + proximo

        if len(sequencia_atual) > len(maior_sequencia):
            maior_sequencia = sequencia_atual

        return proximo

    reduce(achar_sequencia, s)
    return maior_sequencia

print(achar_maior_sequencia('azcbobobegghakl'))  # beggh

Você poderia tentar explicá-lo?

Vou tentar explicar sim, Edson! Mas me diz, de onde você pegou esse código? Porque, para falar a verdade, ele está bastante confuso e não muito pythônico hehe. O código também tem o problema que, caso haja um empate, ele não vai retornar a primeira substring do empate.

De qualquer jeito, acho que aqui cabe explicar só a função reduce(). Antes, queria avisar que em breve vai sair um post bem legal no blog da Caelum sobre programação funcional em Python, que vai incluir uma explicação dessa função e, ainda, o porquê de seu uso não ser recomendado!

Basicamente, a função reduce() vai reduzir uma lista de valores a um só. Nesse caso, cada valor é um caractere da string original. O que está sendo feito, então, é que, em primeiro lugar, a função achar_maior_sequencia() está sendo rodada com os parâmetros 'a' e 'z'. Em seguida, é rodada de novo com o resultado dessa primeira execução e 'c' como parâmetros, e assim por diante até que só se tenha um resultado final. Repare que isso fica muito confuso, e esse é o principal motivo que essa função é evitada (e inclusive fortemente criticada pelo próprio criador do Python). Pra ficar mais claro, olha esse código de exemplo:

def soma_numeros(a, b)
    return a + b

numeros = [1, 2, 3, 4]
reduce(soma_numeros, numeros)

E olha só como o reduce() vai funcionar:

@Yan Orestes: Eu copiei o código postado no stack overflow!

Hehe, entendi, Edson! Minha recomendação é rejeitar esse tipo de código, mesmo...