MAC2166 - Introdução à Computação (1º Semestre de 2023)

Grande áreas Civil, Mecânica, Química e Petróleo

Guia de Estudos - Semana 7

Tópicos

Antes de sua aula síncrona desta semana, estude os conteúdos abaixo e os materiais recomendados e tente resolver os exercícios. Os assuntos e exercícios serão discutidos pelo(a) professor(a) na aula.



Lista - estrutura sequencial indexada

Até aqui, trabalhamos com variáveis simples, capazes de armazenar apenas um tipo, como bool, float e int.

Uma lista (tipo list) em Python é uma sequência de valores de qualquer tipo ou classe tais como int, float, bool, str e mesmo list, entre outros.

Existem várias maneiras de criarmos uma lista. A maneira mais simples é envolver os elementos da lista por colchetes ([ e ]). Por exemplo, podemos criar uma lista contendo os anos de obtenção das 5 primeiras conquistas do Brasil em Copas do Mundo de Futebol da seguinte maneira:

>>> anos_conquistas = [1958, 1962, 1970, 1994, 2002]

Observe o uso de colchetes de abertura ([) para marcar o início e o colchetes de fechamento (]) para marcar o final da lista, e os elementos separados por vígula.

Ao contrário do conceito de vetores em linguagem C, que são coleções indexadas homogêneas de dados (todos elementos do vetor são de um mesmo tipo), as listas em Python podem conter vários tipos de dados, sendo, portanto, possível armazenar coleções heterogêneas de dados.

>>> L = [1958, 1962, 1970, 1994, 2002]

Índices

Cada valor na lista é identificado por um índice.

Lista são estruturas sequenciais indexadas pois seus elementos podem ser acessados sequencialmente utilizando índices. Por convenção do Python, o primeiro elemento da lista tem índice 0, o segundo tem índice 1, e assim por diante. Observe que, por começar pelo índice zero, o último elemento da lista anos_conquistas, o ano 2002, tem índice 4, sendo que essa lista tem comprimento 5.

Índices negativos indicarão elementos da direita para a esquerda ao invés de da esquerda para a direita.

Um erro comum em programas é a utilização de índices inválidos.

Comprimento de uma lista

O número de elementos (comprimento) de uma lista pode ser obtido pela função len().

>>> len(anos_conquistas)
5

Laços para percorrer os elementos de uma lista

Repetições com for

Exemplo 1:

Dados n > 0 e uma sequência com n números reais, imprimí-los na ordem inversa a da leitura.

Dica: Criar uma lista vazia (seq = []) e usar append.

Solução 1:

Vamos fazer do modo tradicional, imprimindo dentro de um while.

    n = int(input("Digite n: "))
    seq = []
    i = 0
    # Lê a sequência de números, armazenando-os em uma lista
    while i < n:
        num = float(input("Digite o %do. num: "%(i+1)))
        seq.append(num)
        i += 1

    # Percorre os elementos da lista do último ao primeiro,
    # imprimindo-os um por vez
    i = n-1
    while i >= 0:
        print(seq[i])
        i -= 1
      

Solução 2:

Solução alternativa usando índices negativos.

    n = int(input("Digite n: "))
    seq = []
    i = 0
    while i < n:
        num = float(input("Digite o %do. num: "%(i+1)))
        seq.append(num)
        i += 1

    i = -1
    while i >= -n:
        print(seq[i])
        i -= 1
    

Solução 3:

Solução alternativa usando o comando for.

    n = int(input("Digite n: "))

    seq = []
    for i in range(n):
        num = float(input("Digite o %do. num: "%(i+1)))
        seq.append(num)

    for i in range(n-1, -1, -1):
        print(seq[i])
      

Solução 4:

Outra solução alternativa usando o comando for com índices negativos.

    n = int(input("Digite n: "))

    seq = []
    for i in range(n):
        num = float(input("Digite o %do. num: "%(i+1)))
        seq.append(num)

    for i in range(-1, -n-1, -1):
        print(seq[i])
      

Solução 5:

O tipo list possui o método reverse(), que inverte os elementos da lista.
Usando esse método, a solução do exemplo poderia ser escrita como mostrado a seguir:

    n = int(input("Digite n: "))

    seq = []
    for i in range(n):
        num = float(input("Digite o %do. num: "%(i+1)))
        seq.append(num)

    seq.reverse()
    for x in seq:
        print(x)
      

Funções com listas e fatiamento de listas

Exemplo 2:

Escreva uma função que recebe uma lista de inteiros e devolve o menor e o maior valor da lista.

Solução:

      def menorMaiorLista(lista):
          maior = lista[0]
          menor = lista[0]
          for x in lista:
              if x > maior:
                  maior = x
              elif x < menor:
                  menor = x
          return menor,maior
        
Essa função poderia ser testada no IDLE, por exemplo, com a seguinte chamada:
      m,M = menorMaiorLista([5,-4,18,8,-9,4])
      print("menor =",m,", maior=",M)
        

Referências vs clones

A atribuição de uma lista em uma variável A a uma segunda variável B não cria uma nova lista. As duas variáveis estarão referenciando a mesma lista na memória. Isto significa que alterações na lista A afetam B e vice-versa:

>>> A = ["Bento Gonçalves", "Campos do Jordão", "Gramado"]
>>> B = A
>>> B.append("Ouro Preto")
>>> print(B)
['Bento Gonçalves', 'Campos do Jordão', 'Gramado', 'Ouro Preto']
>>> print(A)
['Bento Gonçalves', 'Campos do Jordão', 'Gramado', 'Ouro Preto']
>>> id(A)
139789181142280
>>> id(B)
139789181142280
>>> id(A) == id(B)
True
>>> A is B
True

Cada objeto em Python, incluindo listas, possui um identificador exclusivo (número inteiro único) que pode ser acessado usando a função id() do Python. Observe que no exemplo acima, as listas A e B possuem o mesmo identificador, confirmando que elas correspondem à mesma lista na memória.
O teste id(A) == id(B) pode ser igualmente obtido através do comando A is B.

Em algumas situações, no entanto, precisamos, de fato, criar uma réplica/clone na memória de uma lista existente.
Para isso podemos usar o comando B = list(A). Note que nesse caso alterações posteriores em uma das listas não afetam a sua cópia.

>>> A = ["Bento Gonçalves", "Campos do Jordão", "Gramado"]
>>> B = list(A)
>>> B.append("Ouro Preto")
>>> print(B)
['Bento Gonçalves', 'Campos do Jordão', 'Gramado', 'Ouro Preto']
>>> print(A)
['Bento Gonçalves', 'Campos do Jordão', 'Gramado']
>>> id(A)
139789180697672
>>> id(B)
139789156561992
>>> id(A) == id(B)
False
>>> A is B
False

Exemplo 3:

Passsagem por referência: Exemplo de função que modifica uma lista e os efeitos persistem fora da função.
  1. Escreva uma função com protótipo

    def insereSeNovo(x, lista):

    que devolve o índice em que o real x ocorre em lista ou, caso x não estiver na lista, insere x no final da lista e devolve o índice dessa posição.


  2. Dados um número inteiro n e uma sequência de n números reais, escreva um programa (usando a função do item anterior) que conta e imprime quantas vezes cada número ocorre na sequência.

Solução 1:

      def insereSeNovo(x, lista):
          i = 0
          achou = False
          while i < len(lista) and not achou:
              if lista[i] == x:
                  achou = True
                  ind = i
              i += 1
          if not achou:
              lista.append(x)
              ind = len(lista)-1
          return ind

      # programa principal:
      def main():
          n = int(input("Digite n: "))
          i = 0
          listaNum  = []
          listaCont = []
          while i < n:
              num = float(input("Digite num: "))
              ind = insereSeNovo(num, listaNum)
              if ind >= len(listaCont):
                  listaCont.append(0)
              listaCont[ind] += 1
              i += 1

          i = 0
          while i < len(listaNum):
              print("%.2f aparece %d vezes"%(listaNum[i],listaCont[i]))
              i += 1

      main()
          

Solução 2:

Uma solução mais compacta para a função insereSeNovo:

      def insereSeNovo(x, lista):
          i = 0
          while i < len(lista):
              if lista[i] == x:
                  return i
              i += 1
          lista.append(x)
          return len(lista)-1
        

Solução 3:

Uma solução alternativa para a função insereSeNovo que utiliza o comando if x not in lista:

      def insereSeNovo(x, lista):
          if x not in lista:
              lista.append(x)
              ind = len(lista)-1
          else: # eu sei que x está na lista
              ind = 0
              while lista[ind] != x:
                  ind += 1
          return ind
        

Concatenação de listas usando +

Um Python, podemos gerar uma nova lista a partir da concatenação de duas listas existentes usando o operador de adição +. Note que as listas originais são preservadas e uma nova lista é criada com um total de elementos igual a soma dos comprimentos das duas primeiras. Veja os exemplos abaixo digitados no Python Shell:

>>> A = ["Bento Gonçalves", "Campos do Jordão", "Gramado"]
>>> B = ["Ouro Preto", "Fortaleza", "Maceió", "Rio de Janeiro"]
>>> C = A + B
>>> print(A)
['Bento Gonçalves', 'Campos do Jordão', 'Gramado']
>>> print(B)
['Ouro Preto', 'Fortaleza', 'Maceió', 'Rio de Janeiro']
>>> print(C)
['Bento Gonçalves', 'Campos do Jordão', 'Gramado', 'Ouro Preto', 'Fortaleza', 'Maceió', 'Rio de Janeiro']
>>> len(C) == len(A) + len(B)     #7 == 3 + 4
True

Note que a concatenação não possui propriedade comutativa, pois a ordem dos elementos na lista de saída depende da ordem dos operandos.

>>> sabores = ["baunilha", "chocolate", "morango"] + ["napolitano", "flocos"]
>>> print(sabores)
['baunilha', 'chocolate', 'morango', 'napolitano', 'flocos']
>>> sabores = ["napolitano", "flocos"] + ["baunilha", "chocolate", "morango"]
>>> print(sabores)
['napolitano', 'flocos', 'baunilha', 'chocolate', 'morango']

Se as duas listas A e B possuem elementos em comum, após a concatenação, estes serão repetidos na lista produzida (veja o caso dos elementos 3, 5 e 7 no exemplo abaixo).

>>> impares = [1, 3, 5, 7, 9]    #cinco primeiros números ímpares
>>> primos = [2, 3, 5, 7, 11]    #cinco primeiros números primos
>>> uniao = impares + primos
>>> print(uniao)
[1, 3, 5, 7, 9, 2, 3, 5, 7, 11]

Método append X concatenação de listas

Observe que os seguintes três trechos de código produzem o mesmo efeito:

>>> sabores = ["baunilha", "chocolate", "morango"]
>>> sabores = sabores + ["flocos"]
>>> print(sabores)
['baunilha', 'chocolate', 'morango', 'flocos']

>>> sabores = ["baunilha", "chocolate", "morango"]
>>> sabores += ["flocos"]
>>> print(sabores)
['baunilha', 'chocolate', 'morango', 'flocos']

>>> sabores = ["baunilha", "chocolate", "morango"]
>>> sabores.append("flocos")
>>> print(sabores)
['baunilha', 'chocolate', 'morango', 'flocos']

Apesar deles produzirem o mesmo resultado, nesse caso é preferível utilizar o método append(), pois a concatenação gera uma cópia da lista toda e a variável sabores passa a referenciar essa nova lista criada, sendo, portanto, uma operação mais custosa.

Repetição de listas usando *

Em Python podemos multiplicar uma lista por um número inteiro. O efeito é a criação de uma nova lista contendo a repetição dos elementos da primeira pelo número de vezes indicado. Veja o exemplo abaixo:

>>> [0, 1]*3        #O mesmo que: [0, 1] + [0, 1] + [0, 1]
[0, 1, 0, 1, 0, 1]

Veja o vídeo abaixo sobre manipulação de listas em Python:

Fatias de listas

Para uma dada lista, podemos criar uma sublista formada por uma cópia de um trecho de elementos consecutivos da primeira através do recurso de fatiamento de listas. Para isso, usamos a seguinte sintaxe: lista[início:fim]

Caso omitido, o parâmetro início é assumido como sendo 0 (zero) e o fim, quando omitido, é assumido como sendo len(lista).

Veja os exemplos abaixo digitados no Python Shell:

>>> cidades = ['Bento Gonçalves', 'Campos do Jordão', 'Gramado', 'Ouro Preto', 'Fortaleza', 'Maceió', 'Rio de Janeiro']
>>> cidades[2:6]
['Gramado', 'Ouro Preto', 'Fortaleza', 'Maceió']
>>> cidades[1:3]
['Campos do Jordão', 'Gramado']
>>> cidades[:4]
['Bento Gonçalves', 'Campos do Jordão', 'Gramado', 'Ouro Preto']
>>> cidades[3:]
['Ouro Preto', 'Fortaleza', 'Maceió', 'Rio de Janeiro']

Por convenção do Python, o início indica o índice do primeiro elemento que será incluído no trecho copiado, mas o último elemento incluído no trecho é dado por fim-1. Ou seja, o elemento cujo índice é dado por fim nunca é incluído no trecho copiado.

Em especial, o comando lista[:] (ou lista[0:len(lista)]) gera uma cópia da lista toda, podendo ser usado em operações de clonagem de uma lista, no lugar do comando list(lista) visto anteriormente:

>>> cidades = ["Bento Gonçalves", "Campos do Jordão", "Gramado"]
>>> B = cidades[:]
>>> id(cidades) == id(B)
False
>>> B.append("Ouro Preto")
>>> print(B)
['Bento Gonçalves', 'Campos do Jordão', 'Gramado', 'Ouro Preto']
>>> print(cidades)
['Bento Gonçalves', 'Campos do Jordão', 'Gramado']

Remoção em listas

Remoções em listas podem ser feitas usando o comando del ou o método pop.
A sintaxe do del é del lista[índice].

>>> cidades = ["Bento Gonçalves", "Campos do Jordão", "Gramado", "Ouro Preto"]
>>> i = 1 #índice a ser removido
>>> del cidades[i]
>>> print(cidades)
['Bento Gonçalves', 'Gramado', 'Ouro Preto']

A sintaxe do pop é lista.pop(índice).
A diferença é que o pop devolve o valor removido da lista, que pode, por exemplo, ser atribuído a uma variável.
Caso omitido o índice, o último elemento é removido.

>>> cidades = ["Bento Gonçalves", "Campos do Jordão", "Gramado", "Ouro Preto"]
>>> i = 1 #índice a ser removido
>>> c = cidades.pop(i)
>>> print(cidades)
['Bento Gonçalves', 'Gramado', 'Ouro Preto']
>>> print(c)
Campos do Jordão
>>> c = cidades.pop()
>>> print(cidades)
['Bento Gonçalves', 'Gramado']
>>> print(c)
Ouro Preto

O efeito da remoção pode também ser obtido construindo uma nova lista sem o elemento indesejado, usando fatiamento mais concatenação.

>>> cidades = ["Bento Gonçalves", "Campos do Jordão", "Gramado", "Ouro Preto"]
>>> i = 1 #índice a ser removido
>>> cidades = cidades[:i] + cidades[i+1:]
>>> print(cidades)
['Bento Gonçalves', 'Gramado', 'Ouro Preto']

Note, porém, que essa última solução é mais custosa, por envolver a criação de uma cópia da lista toda, sendo que a variável cidades passará a referenciar a nova lista gerada.

Assista o vídeo abaixo, que fala sobre como os objetos são armazenados na memória e o que são as variáveis em relação a isso.

Problema 1:

Dados n > 0 lançamentos de uma roleta (números entre 0 e 36), calcular a frequência de cada número.

Dica: Criar uma lista com 37 zeros.

Solução 1:

Solução usando o comando while.

          n = int(input("Digite n: "))

          freq = []
          i = 0
          while i < 37:
              freq.append(0)
              i += 1

          i = 0
          while i < n:
              num = int(input("roleta: "))
              freq[num] += 1
              i += 1

          i = 0
          while i < 37:
              print("freq.rel.(%d): %f"%(i,freq[i]/n))
              i += 1
      

Solução 2:

Solução mais compacta usando freq = [0]*37 para a criação da lista com 37 zeros.

          n = int(input("Digite n: "))

          freq = [0]*37
          i = 0
          while i < n:
              num = int(input("roleta: "))
              freq[num] += 1
              i += 1

          i = 0
          while i < 37:
              print("freq.rel.(%d): %f"%(i,freq[i]/n))
              i += 1
        

Solução 3:

Solução alternativa usando o comando for.

      n = int(input("Digite n: "))

      freq = [0]*37

      for i in range(n):
          num = int(input("roleta: "))
          freq[num] += 1

      i = 0
      for x in freq:
          print("freq.rel.(%d): %f"%(i,x/n))
          i += 1
        

Solução 4:

Solução alternativa que simula a roleta usando o gerador de números pseudo-aleatórios do módulo random do Python, ao invés de solicitar a entrada manual dos n lançamentos.

      import random
      n = int(input("Digite n: "))

      freq = [0]*37

      for i in range(n):
          num = random.randrange(0, 37)
          freq[num] += 1

      i = 0
      for x in freq:
          print("freq.rel.(%d): %f"%(i,x/n))
          i += 1
        


Problema 2:

Dada uma sequência de n > 0 números reais, imprimi-los eliminando as repetições.

Solução 1:

Solução usando while.

      n = int(input("Digite n: "))

      seq = []
      for i in range(n):
          num = float(input("Digite o %do. num: "%(i+1)))
          rep = False
          j = 0
          while j < len(seq) and rep == False:
              if seq[j] == num:
                  rep = True
              j += 1
          if rep == False: # if not rep:
              seq.append(num)

      print(seq)
        

Solução 2:

Solução usando for.

      n = int(input("Digite n: "))

      seq = []
      for i in range(n):
          num = float(input("Digite o %do. num: "%(i+1)))
          rep = False
          for x in seq:
              if x == num:
                  rep = True
          if rep == False: # if not rep:
              seq.append(num)

      print(seq)
        

Solução 3:

Solução compacta, aproveitando o fato de que o Python permite testar diretamente se um elemento não faz parte de uma lista,
através do comando if num not in seq:

      n = int(input("Digite n: "))

      seq = []
      for i in range(n):
          num = float(input("Digite o %do. num: "%(i+1)))
          if num not in seq:
              seq.append(num)

      print(seq)
        


Problema 3:

Dados dois números naturais n e m e duas sequências ordenadas com n > 0 e m > 0 números inteiros, criar uma lista contendo a sequência ordenada com todos os elementos das duas sequências originais sem repetição.

Sugestão: Imagine uma situação real, por exemplo, dois fichários de uma biblioteca.

Solução 1:

Cada sequência ordenada fornecida é lida em uma lista correspondente já eliminando possíveis elementos repetidos, usando a solução empregada no problema anterior. As duas listas resultantes seq1 e seq2 são então percorridas, usando as variáveis i e j como seus respectivos índices, copiando de modo intercalado para uma lista de saída seq3 sempre o menor valor entre seq1[i] e seq2[j].

      n = int(input("Digite n: "))
      seq1 = []
      for i in range(n):
          num = int(input("Digite o %do. num: "%(i+1)))
          if num not in seq1:
              seq1.append(num)

      m = int(input("Digite m: "))
      seq2 = []
      for i in range(m):
          num = int(input("Digite o %do. num: "%(i+1)))
          if num not in seq2:
              seq2.append(num)

      seq3 = []
      i,j = 0,0
      while i < len(seq1) and j < len(seq2):
          if seq1[i] < seq2[j]:
              seq3.append(seq1[i])
              i += 1
          elif seq2[j] < seq1[i]:
              seq3.append(seq2[j])
              j += 1
          else:   # seq1[i] == seq2[j]
              seq3.append(seq1[i])
              i += 1
              j += 1

      while i < len(seq1):
          seq3.append(seq1[i])
          i += 1

      while j < len(seq2):
          seq3.append(seq2[j])
          j += 1

      print(seq3)
        

Solução 2:

Solução similar à anterior, porém durante o processo de intercalação, os casos em que i ou j excedem o último índice válido de suas respectivas listas é tratado diretamente dentro do mesmo laço que trata os demais casos em que os dois índices são válidos.

      n = int(input("Digite n: "))
      seq1 = []
      for i in range(n):
          num = int(input("Digite o %do. num: "%(i+1)))
          if num not in seq1:
              seq1.append(num)

      m = int(input("Digite m: "))
      seq2 = []
      for i in range(m):
          num = int(input("Digite o %do. num: "%(i+1)))
          if num not in seq2:
              seq2.append(num)

      seq3 = []
      i,j = 0,0
      while i < len(seq1) or j < len(seq2):
          if i == len(seq1):
              seq3.append(seq2[j])
              j += 1
          elif j == len(seq2):
              seq3.append(seq1[i])
              i += 1
          elif seq1[i] < seq2[j]:
              seq3.append(seq1[i])
              i += 1
          elif seq2[j] < seq1[i]:
              seq3.append(seq2[j])
              j += 1
          else:   # seq1[i] == seq2[j]
              seq3.append(seq1[i])
              i += 1
              j += 1

      print(seq3)
        

Solução 3:

Idêntica à solução anterior, exceto que exploramos o fato de que as duas sequências fornecidas estão ordenadas, de modo que para eliminar seus elementos repetidos durante o laço de leitura, basta comparar com o último valor já lido na lista.

      n = int(input("Digite n: "))
      num = int(input("Digite o 1o. num: "))
      seq1 = [num]
      for i in range(1,n):
          num = int(input("Digite o %do. num: "%(i+1)))
          if num != seq1[len(seq1)-1]:  #compara com o último valor inserido em seq1.
              seq1.append(num)

      m = int(input("Digite m: "))
      num = int(input("Digite o 1o. num: "))
      seq2 = [num]
      for i in range(1,m):
          num = int(input("Digite o %do. num: "%(i+1)))
          if num != seq2[len(seq2)-1]:  #compara com o último valor inserido em seq2.
              seq2.append(num)

      seq3 = []
      i,j = 0,0
      while i < len(seq1) or j < len(seq2):
          if i == len(seq1):
              seq3.append(seq2[j])
              j += 1
          elif j == len(seq2):
              seq3.append(seq1[i])
              i += 1
          elif seq1[i] < seq2[j]:
              seq3.append(seq1[i])
              i += 1
          elif seq2[j] < seq1[i]:
              seq3.append(seq2[j])
              j += 1
          else:   # seq1[i] == seq2[j]
              seq3.append(seq1[i])
              i += 1
              j += 1

      print(seq3)
        


Problema 4:

  1. Escreva uma função que recebe um número inteiro e retorna uma lista contendo os seus dígitos. Os dígitos podem estar em ordem reversa.

  2. Escreva uma função que recebe uma lista e retorna uma lista contendo os seus elementos em ordem reversa.

  3. Escreva uma função que recebe 2 listas (l1 e l2) e devolve True caso:

    • l1 e l2 tem o mesmo tamanho e
    • os elementos de l1 e l2 são todos iguais e na mesma ordem.

    Caso contrário, a função deve devolver False.

  4. Escreva um programa que leia um número inteiro n > 0 e determina se ele é ou não palíndromo usando as funções anteriores. Um número inteiro é palíndromo se ele possui a mesma sequência de dígitos quando lido tanto da direita para a esquerda como da esquerda para a direita.

Solução 1:

      def listaDeDigitos(n):
          lista = []
          while n > 0:
              dig = n%10
              lista.append(dig)
              n = n//10
          return lista


      def ordemReversa(lista):
          inv = []
          i = len(lista)-1
          while i >= 0:
              inv.append(lista[i])
              i -= 1
          return inv


      def iguais(l1, l2):
          if len(l1) != len(l2):
              return False
          i = 0
          while i < len(l1):
              if l1[i] != l2[i]:
                  return False
              i += 1
          return True

      # programa principal:
      def main():
          n = int(input("Digite n: "))

          lista = listaDeDigitos(n)
          inv = ordemReversa(lista)

          if iguais(lista, inv):
              print(n,"é palíndromo")
          else:
              print(n,"não é palíndromo")

      main()
          

Soluções alternativas:

Uma implementação alternativa para a função ordemReversa. Nessa versão usamos, no início do código, o comando [0]*n que gera uma lista com n elementos nulos.

      def ordemReversa(lista):
          n = len(lista)
          inv = [0]*n
          i = 0
          while i < n:
              inv[i] = lista[n-1-i]
              i += 1
          return inv
        
Python permite a comparação de listas (ex: if l1 == l2:).
Logo, a função iguais poderia se resumir simplesmente a:
      def iguais(l1, l2):
          return l1 == l2
        

Observações:

Python permite inverter listas (in place) usando lista.reverse(). Para criar uma cópia de uma lista a podemos usar b = list(a), ou usar b = a[:]
Logo, uma solução para o programa principal usando esses recursos disponíveis na linguagem poderia ser:

      def main():
          n = int(input("Digite n: "))
          lista = listaDeDigitos(n)
          inv = list(lista)
          inv.reverse()

          if inv == lista:
              print(n,"é palíndromo")
          else:
              print(n,"não é palíndromo")

      main()
        


Problema 5:

  1. Escreva uma função que recebe 2 inteiros ini e fim, e uma lista L, tal que 0 <= ini < fim <= len(L) e calcula a soma dos elementos L[i], para ini <= i < fim.

  2. Usando a função anterior, escreva um programa que leia um número inteiro n > 0 e uma sequência com n números reais, e determina um segmento de soma máxima. Um segmento é uma subsequência de números consecutivos, com pelo menos um elemento.

    Exemplo: Na sequência abaixo com n = 12
    5, 2, -2, -7, 3, 14, 10, -3, 9, -6, 4, 1,
    a soma do segmento de soma máxima é 3+14+10-3+9 = 33.

Solução 1:

      def somasegmento(ini,fim,L):
          soma = 0.0
          i = ini
          while i < fim:
              soma += L[i]
              i += 1
          return soma

      def main():
          n = int(input("Digite n: "))
          lista = []
          for i in range(n):
              num = float(input("Digite num: "))
              lista.append(num)

          smax = lista[0]
          imax,fmax = 0,1
          for i in range(n):
              for f in range(i+1,n+1):
                  s = somasegmento(i,f,lista)
                  if s > smax:
                      smax = s
                      imax = i
                      fmax = f

          print("Soma máxima =",lista[imax],end=" ")
          for i in range(imax+1,fmax):
              if(lista[i] < 0.0):
                  print(lista[i],end=" ")
              else:
                  print("+",lista[i],end=" ")
          print("=",smax)

      main()
        

Solução 2:

Solução alternativa da função somasegmento usando o laço for.

      def somasegmento(ini,fim,L):
          soma = 0.0
          for i in range(ini, fim):
              soma += L[i]
          return soma
        

Solução 3:

Solução compacta, aproveitando os recursos já existentes do Python de fatiamento de listas e soma dos valores de uma lista usando a função sum (exemplo, sum([3,-2,7]) gera o valor 8).

      def somasegmento(ini,fim,L):
          return sum(L[ini:fim])