4
respostas

Exercício 09 o módulo 03 de

Oi gente, tudo bem?

Para o exercício 09 da "hora da prática", eu fui por duas soluções que estão diferentes da resposta que foi sugerida pelo instrutor:

Na primeira, abaixo, deixei o código comentado passo a passo para ilustrar qual foi a minha lista de raciocínio para conseguir vencer o problema, no entanto, a forma como o instrutor propôs como resposta está muito mais enxuta do que a minha. Visto que estou criando contadores e listas adicionais, eu gostaria de saber se a forma como eu fiz está carregando muito o código e se estou seguindo uma eficiência de código aceitável para o problema. Também gostaria de saber se da forma como eu fiz, corro o risco de cair em alguma condição que não atenda ao que foi proposto no exercício.

estados = ['SP', 'ES', 'MG', 'MG', 'SP', 'MG', 'ES', 'ES', 'ES', 'SP', 'SP', 'MG', 'ES', 'SP', 'RJ', 'MG', 'RJ', 'SP', 'MG', 'SP', 'ES', 'SP', 'MG']


#aqui tive que apelar para a consulta na resposta do exercício. não lembrava que o set já fazia filtro :)
estados_unicos = list(set(estados))

#crio a lista de estados_unicos
lista_de_unicos = []
#criando a lista que conta os estados unicos
contador_unicos = []
#fiz um for para passar por todos os estados unicos da lista que tem o "set"
for unicos in estados_unicos:
    #alimento a lista de estados únicos a cada iteração
    lista_de_unicos.append(unicos)
    #inicio um contador para contar o número de estados únicos
    count = 0
    #inicio um indexador para iterar sobre o for da lista de estados
    i = 0
    #for que passa pela lista de cada estados, agora vou começar a comparar essa lista
    #com os estados únicos
    for i in range(len(estados)):
        #condição para iterar o estado unico que está na vez e comparar com o
        #o estado da lista de "estados"
        if unicos == estados[i]:
            #contador vai incrementando a medida em que a condição é atendida
            count += 1
    #incremento uma lista com as contagens obtidas
    contador_unicos.append(count)

#dict comprehension com as chaves e valores pedidos no problema passando por toda a lista de
#estados únicos
dict_cont = {lista_de_unicos[i]: contador_unicos[i] for i in range(len(lista_de_unicos))}
print(dict_cont)
    

Aqui na segunda forma, eu deixei o estado como uma entrada de usuário. O valor digitado será verificado na lista de estados com a função "Counter" e a quantidade de incidências registradas num dict. Não fui por esse caminho, mas eu poderia continuar para que todos os valores digitados saíssem em um dict único contendo todos os valores digitados. Minha dúvida aqui é sobre a função counter. Ela é uma boa opção para o caso proposto mesmo? Em relação à lógica fica evidente que é muito mais simples, mas em relação à utilização de recursos de máquina, existe alguma vantagem em usar uma função já existente em vez de desenvolver os contadores por conta própria?

estados = ['SP', 'ES', 'MG', 'MG', 'SP', 'MG', 'ES', 'ES', 'ES', 'SP', 'SP', 'MG', 'ES', 'SP', 'RJ', 'MG', 'RJ', 'SP', 'MG', 'SP', 'ES', 'SP', 'MG']

entrada = str(input('digite estado:'))
contagem = Counter(estados)
print(contagem[entrada])
consulta = {entrada: contagem[entrada]}
print(consulta)

Obrigado e parabéns pelo curso, estou evoluindo bastante com os conceitos apresentados.

4 respostas

Oi, tudo bem!

Vamos às suas perguntas:

Eficiência do código: A eficiência do código pode ser medida de várias maneiras, incluindo a legibilidade do código, o desempenho em termos de tempo de execução e uso de memória, e a manutenção do código. No seu primeiro exemplo, você optou por uma abordagem passo a passo para resolver o problema, o que é ótimo para a compreensão do que cada parte do código está fazendo. No entanto, como você mencionou, o código pode ser mais enxuto. Em Python, geralmente é preferível escrever código mais conciso e legível, desde que isso não comprometa a compreensão do que o código está fazendo.

Risco de não atender ao problema proposto: No seu primeiro exemplo, você está contando a ocorrência de cada estado único na lista de estados. Isso parece estar de acordo com o problema proposto. No entanto, sem conhecer os detalhes do problema, é difícil dizer se há alguma condição que não esteja sendo atendida.

Uso da função Counter: A função Counter do módulo collections é uma ferramenta poderosa e eficiente para contar o número de ocorrências de elementos em uma coleção. Ela é implementada de forma eficiente e geralmente é mais rápida do que uma implementação manual de contagem. Além disso, ela produz um código mais limpo e fácil de ler. Portanto, a menos que você tenha requisitos muito específicos que a função Counter não possa atender, geralmente é uma boa ideia usá-la.

Em relação à sua pergunta sobre a função Counter, ela é uma excelente opção para o caso proposto. A função Counter é uma ferramenta poderosa e eficiente para contar o número de ocorrências de elementos em uma coleção. Ela é implementada de forma eficiente e geralmente é mais rápida do que uma implementação manual de contagem.

Além disso, usar funções já existentes como Counter pode tornar seu código mais limpo e fácil de ler, o que é sempre uma vantagem. Em termos de utilização de recursos da máquina, a diferença provavelmente seria mínima para a maioria dos casos de uso, a menos que você esteja trabalhando com conjuntos de dados extremamente grandes.

No entanto, é sempre uma boa prática entender como essas funções funcionam internamente. Isso pode ajudá-lo a tomar decisões mais informadas sobre quando usar essas funções e quando pode ser melhor implementar sua própria lógica.

Espero que isso ajude! Se você tiver mais perguntas, fique à vontade para perguntar.

Primeira abordagem: Você criou uma lista de estados únicos e, em seguida, percorreu essa lista, contando a ocorrência de cada estado na lista original de estados. Isso é eficaz, mas pode ser um pouco mais complexo e demorado do que necessário, pois envolve várias etapas e a criação de várias listas e contadores. Segunda abordagem: Você usou a função Counter do módulo collections para contar a ocorrência de cada estado na lista de estados. Isso é muito mais eficiente e resulta em um código mais limpo e fácil de ler. Aqui está uma versão corrigida e simplificada do seu código usando a função Counter:

from collections import Counter

estados = ['SP', 'ES', 'MG', 'MG', 'SP', 'MG', 'ES', 'ES', 'ES', 'SP', 'SP', 'MG', 'ES', 'SP', 'RJ', 'MG', 'RJ', 'SP', 'MG', 'SP', 'ES', 'SP', 'MG']

# Contar a ocorrência de cada estado
contagem = Counter(estados)

# Imprimir a contagem de cada estado
for estado, count in contagem.items():
    print(f'{estado}: {count}')

# Solicitar ao usuário para digitar um estado
entrada = str(input('Digite um estado:'))

# Verificar se o estado digitado está na contagem
if entrada in contagem:
    print(f'O estado {entrada} aparece {contagem[entrada]} vezes.')
else:
    print('O estado digitado não está na lista.')

Espero que isso ajude! Se você tiver mais perguntas, fique à vontade para perguntar.

Olá Rafael, tudo bem?

Não sou monitor, mas suas perguntas são tão fantásticas que quero tentar responder.

A primeira pergunta que você está fazendo é a mais importante na Programação e Desenvolvimento de Software: "Corro o risco de cair em alguma condição que não atenda ao que foi proposto no exercício?" Em outras palavras, o que você quer saber é que, independentemente da entrada da função, ela sempre retornará a saída correta.

A partir disso, você também está fazendo a pergunta mais difícil de ser respondida, e que sempre deve ser feita após sua função satisfazer a condição da pergunta anterior: "Estou seguindo uma eficiência de código aceitável para o problema?" Em outras palavras, o quão eficiente é o meu algoritmo comparado à infinidade (literalmente) de algoritmos existentes que satisfazem a primeira condição?

Entende como a segunda pergunta é mais difícil? É por isso que no desenvolvimento de software sempre trabalhamos com compromissos, e como você mesmo disse muito bem, a eficiência aceitável é sempre determinada por você. Por exemplo: essa função pode demorar no máximo 0.1s para rodar no sistema da minha empresa.

Sobre sua primeira pergunta: Sim, seu algoritmo satisfaz a primeira condição, e existem várias formas de avaliar isso através de testes de software (recomendo olhar os cursos da Alura no futuro).

Sobre a sua segunda pergunta: Para responder a essa pergunta, existe um campo de estudo inteiramente dedicado que se chama complexidade de algoritmos, geralmente abordado em livros de Matemática Discreta e Estruturas de Dados em C na graduação. A noção intuitiva que quero te passar aqui é que, para responder a essa pergunta, você pode simplesmente rodar os dois algoritmos no seu computador para uma lista com 1 bilhão de valores e observar qual deles demora menos. Outra opção é calcular matematicamente, definindo um objetivo, e essa é claramente mais difícil.

A título de ilustração, vou dizer que o algoritmo que itera mais vezes sobre a lista de estados é o pior, beleza?

No exemplo, os únicos estados únicos são ES, SP, MG e RJ. Observe que seu código vai iterar sobre a lista estados 4 vezes. Isso acontece porque você o escreveu assim: para cada estado único, você vai iterar sobre a lista e verificar qual elemento é igual a esse estado, e então realizar a contagem.

Isso também significa que, caso uma lista de estados contenha 2000 elementos e todos os 26 estados brasileiros, seu programa vai iterar 26 vezes uma lista de 2000 elementos, realizando 52000 operações de comparação.

Abaixo, deixo uma solução que eu acabei de escrever para o problema:

estados = ['SP', 'ES', 'MG', 'MG', 'SP', 'MG', 'ES', 'ES', 'ES', 'SP', 'SP', 'MG', 'ES', 'SP', 'RJ', 'MG', 'RJ', 'SP', 'MG', 'SP', 'ES', 'SP', 'MG']

dicionario_contagem = {estado: 0 for estado in set(estados)}
for estado in estados:
    dicionario_contagem[estado] += 1
dicionario_contagem

Observe que, nesse caso, o programa sempre vai iterar somente uma vez sobre a lista de estados, e para a condição que eu estabeleci, ele é melhor.

Por fim, você também quer saber se existe alguma vantagem em utilizar as funções das bibliotecas. De maneira geral, a resposta é sim! Normalmente, as bibliotecas são constantemente atualizadas com os melhores algoritmos da atualidade para resolver determinado problema, mas é importante que você, como programador, tenha uma ideia de como esses algoritmos funcionam por trás dos panos para fazer melhor uso desses recursos.

Minha dica é que você sempre se preocupe em responder à primeira pergunta, pelo menos por enquanto. Se você quer que seu algoritmo funcione em menos de 0.1s, e ele funciona, excelente! Normalmente, tentar responder à segunda pergunta pode te deixar meio maluco e não vale a pena ficar quebrando tanto a cabeça com isso quando você está iniciando.

Espero que isso te ajude!! Valeu.

Amigo é que voce fez uma pergunta, aqui é forum de perguntam calmaria......

em teu texto anterior, sim é um texto, voce citou se era possível fazer uma melhoria...

Se esta usando FORUM DE PERGUNTAS, para divulgar seus ganhos, acrecente a tag [ solucionado ] + estudo. OU Concluído, pergunta, duvida..... (sem as tags entra automaticamente no forum perguntas.....

Insira aqui a descrição dessa imagem para ajudar na acessibilidadeMas acredito que a evolução vem com o tempo, inclusive educação.

SUCESSO!