├── PA1_Aula01.ipynb ├── PA1_Aula02.ipynb ├── PA1_Aula03.ipynb ├── PA1_Aula04.ipynb ├── PA1_Aula05.ipynb ├── PA1_Aula06.ipynb ├── PA1_Aula07.ipynb ├── PA1_Aula08.ipynb ├── PA1_Aula09.ipynb ├── PA1_Aula10.ipynb ├── PA1_Aula11.ipynb ├── PA1_Aula12.ipynb └── README.md /PA1_Aula02.ipynb: -------------------------------------------------------------------------------- 1 | {"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"provenance":[],"collapsed_sections":[],"authorship_tag":"ABX9TyPo7sSiDb8cOX5AkTtJVn89"},"kernelspec":{"name":"python3","display_name":"Python 3"},"language_info":{"name":"python"}},"cells":[{"cell_type":"markdown","source":["##**Programação e Algoritmos I**\n","\n","Prof. Alexandre Levada\n","\n","###**Estruturas sequenciais**\n","\n","Antes de iniciar a programação em si, iremos definir alguns comandos básicos da linguagem Python. Uma das primeiras perguntas que surgem quando vamos construir um programa é: como declarar variáveis? Python é uma linguagem dinâmica e portanto não é necessário declarar variáveis. Basta usá-las conforme a necessidade. Para ilustrar o funcionamento básico da linguagem, iremos introduzir os comandos de entrada e saída:\n","\n","O comando print imprime informações na tela e o comando input lê dados do teclado.\n","\n","Para demonstrar a utilização desses comandos, iremos apresentar um pequeno script ilustrativo."],"metadata":{"id":"8kRZhLuaTzGK"}},{"cell_type":"code","execution_count":null,"metadata":{"id":"Hc7D8I9tTyJX","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1664238163432,"user_tz":180,"elapsed":6931,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"f7bbf823-3762-4c52-9cf7-b494062e406f"},"outputs":[{"output_type":"stream","name":"stdout","text":["Entre com o valor de a: 2\n","Entre com o valor de b: 3\n","\n","O valor de 2.00 + 3.00 é igual a 5.00\n"]}],"source":["# Leitura dos valores de entrada (isso é um comentário)\n","# Por padrão tudo que é lido pelo input é uma cadeia de caracteres\n","a = int(input('Entre com o valor de a: '))\n","b = int(input('Entre com o valor de b: '))\n","\n","print() # Pula linha\n","\n","# Calculo do(s) valor(es) de saída\n","c = a + b\n","\n","# Impressão do(s) resultado(s) na saída\n","print('O valor de %.2f + %.2f é igual a %.2f' %(a,b,c))"]},{"cell_type":"markdown","source":["Note que ao ler um valor digitado pelo teclado com o comando input, utilizamos o comando int() para converter a string de leitura para um dado do tipo inteiro. Por padrão, toda informação lida através do teclado em Python é do tipo string, ou seja, não permite cálculos matemáticos. Para tratar os dados de entrada como números inteiros usamos int() e para tratar como números reais usamos float(). A seguir iremos resolver alguns exercícios básicos que envolvem estruturas sequenciais, isto é, uma sequencia linear de comandos.\n","\n","**Ex 1:** Sabe-se que dado uma temperatura em graus Celsius, o valor na escala Farenheit é dado por:\n","\n","$$\n","F = \\frac{9}{5}C + 32\n","$$\n","\n","Faça um programa que leia uma temperatura em Celsius e imprima na tela o valor em Farenheit."],"metadata":{"id":"r85egq7vbPuC"}},{"cell_type":"code","source":["# celsius para farenheit\n","c = float(input('Entre com a temperatura em Celsius (C): '))\n","f = 9*c/5 + 32\n","print('%.1f graus Celsius equivalem a %.1f graus Farenheit' %(c, f))"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"77SE94G3bepg","executionInfo":{"status":"ok","timestamp":1664273509798,"user_tz":180,"elapsed":7956,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"27de1753-4938-4d3c-a729-789d36073ea8"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Entre com a temperatura em Celsius (C): 30\n","30.0 graus Celsius equivalem a 86.0 graus Farenheit\n"]}]},{"cell_type":"markdown","source":["**Ex 2:** O Movimento Retilíneo Uniformemente Variado (MRUV) é caracterizado pela mesma quantidade de aceleração de um corpo em linha reta. A posição do corpo durante a trajetória pode ser calculada através da seguinte equação: \n","\n","$$\n","s = s_0 + v_0 t + at^2\n","$$\n","\n","Faça um script que leia a posição e a velocidade iniciais, além da aceleração (constante) e o tempo final e imprima na tela a posição final do corpo."],"metadata":{"id":"asEPCJZybn0U"}},{"cell_type":"code","source":["s0 = float(input('Entre com a posição inicial (m): '))\n","v0 = float(input('Entre com a velocidade inicial (m/s): '))\n","a = float(input('Entre com a aceleração constante (m/s^2): '))\n","t = float(input('Entre com o tempo final (s): '))\n","\n","s = s0 + v0*t + a*t**2\n","\n","print('A posição final do corpo é %.2f' %s)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"YLJVW4IxbzMr","executionInfo":{"status":"ok","timestamp":1664273609586,"user_tz":180,"elapsed":36841,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"b89d4b91-ec60-44f4-c7fa-eae8b2918793"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Entre com a posição inicial (m): 0\n","Entre com a velocidade inicial (m/s): 5\n","Entre com a aceleração constante (m/s^2): 2\n","Entre com o tempo final (s): 10\n","A posição final do corpo é 250.00\n"]}]},{"cell_type":"markdown","source":["**Ex 3:** A distância Euclidiana entre 2 pontos $P = (x_1, y_1)$ e $Q = (x_2, y_2)$ é definida por:\n","\n","$$\n","d(P, Q) = \\sqrt{(x_1 - x_2)^2 + (y_1 - y_2)^2}\n","$$\n","\n","Faça um programa que leias as coordenadas $x_1$, $y_1$, $x_2$ e $y_2$ e imprima a distância Euclidiana entre P e Q."],"metadata":{"id":"xPfGPFRbcDUl"}},{"cell_type":"code","source":["x1 = float(input('Entre com a coordenada x do ponto P (x1): '))\n","y1 = float(input('Entre com a coordenada y do ponto P (y1): '))\n","x2 = float(input('Entre com a coordenada x do ponto Q (x2): '))\n","y2 = float(input('Entre com a coordenada y do ponto Q (y2): '))\n","\n","distancia = ((x1 - x2)**2 + (y1 - y2)**2)**0.5\n","print('A distância entre os pontos é %.2f' %distancia)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"DPaR27Hxckpf","executionInfo":{"status":"ok","timestamp":1664273785273,"user_tz":180,"elapsed":15824,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"854a6ca1-b138-4f7b-8765-90947844625f"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Entre com a coordenada x do ponto P (x1): 1\n","Entre com a coordenada y do ponto P (y1): 3\n","Entre com a coordenada x do ponto Q (x2): 5\n","Entre com a coordenada y do ponto Q (y2): 6\n","A distância entre os pontos é 5.00\n"]}]},{"cell_type":"markdown","source":["**Ex 4:** A expressão utilizada para computar juros compostos é dada por:\n","\n","$$\n","M = C\\left(1 + \\frac{J}{100}\\right)^P\n","$$\n","\n","onde C é o capital inicial, J é a taxa de juros mensal (%), e P é o período em meses. Faça um programa que leia os valores de C, J e P e imprima a tela o valor final após a aplicação dos juros."],"metadata":{"id":"-JwmGutKct_l"}},{"cell_type":"code","source":["C = float(input('Entre com o capital inicial (R$): '))\n","J = float(input('Entre com a taxa de juros (% ao mês): '))\n","P = float(input('Entre com o período em meses: '))\n","\n","M = C*(1+J/100)**P\n","print('O montante final será de %.2f reais' %M)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"qpe7ziRCdB7a","executionInfo":{"status":"ok","timestamp":1664273915260,"user_tz":180,"elapsed":27384,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"f2a513b3-c9ac-492d-ebde-57e9a66e565e"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Entre com o capital inicial (R$): 1000\n","Entre com a taxa de juros (% ao mês): 0.85\n","Entre com o período em meses: 12\n","O montante final será de 1106.91 reais\n"]}]},{"cell_type":"markdown","source":["**Ex 5:** Num certo país da América do Sul, a moeda nacional é a Merreca (M\\$). No sistema monetário desse país só existem cédulas de M\\$ 100, M\\$ 50, M\\$ 10, M\\$ 5 e M\\$ 1. Dado um valor em Merrecas, faça um script que retorne a quantidade mínima de cédulas que totalizam o valor especificado. Por exemplo, se o valor for M\\$ 379, devemos ter:\n","\n","3 cédulas de M\\$ 100\n","\n","1 cédula de M\\$ 50\n","\n","2 cédulas de M\\$ 10\n","\n","0 cédulas de M\\$ 5\n","\n","4 cédulas de M\\$ 1"],"metadata":{"id":"uaa15F6-dNed"}},{"cell_type":"code","source":["valor = int(input('Entre com o valor em M$: '))\n","\n","cedulas100 = valor // 100\n","resto = valor % 100\n","cedulas50 = resto // 50\n","resto = resto % 50\n","cedulas10 = resto // 10\n","resto = resto % 10\n","cedulas5 = resto // 5\n","resto = resto % 5\n","\n","print('O valor digitado corresponde a:')\n","print('%d cédulas de M$ 100' %cedulas100)\n","print('%d cédulas de M$ 50' %cedulas50)\n","print('%d cédulas de M$ 10' %cedulas10)\n","print('%d cédulas de M$ 5' %cedulas5)\n","print('%d cédulas de M$ 1' %resto)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"KGqpiH_UddRF","executionInfo":{"status":"ok","timestamp":1664274023473,"user_tz":180,"elapsed":14557,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"af3e8d41-8bf3-420f-f7b2-bdc342856270"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Entre com o valor em M$: 537\n","O valor digitado corresponde a:\n","5 cédulas de M$ 100\n","0 cédulas de M$ 50\n","3 cédulas de M$ 10\n","1 cédulas de M$ 5\n","2 cédulas de M$ 1\n"]}]},{"cell_type":"markdown","source":["Ex6: Faça um Programa que pergunte quanto você ganha por hora e o número de horas trabalhadas no mês. Calcule e mostre o total do seu salário no referido mês, sabendo-se que são descontados 11% para o Imposto de Renda, 8% para o INSS e 5% para o sindicato, faça um programa que dê:\n","\n","a) salário bruto.\n","\n","b) quanto pagou ao INSS.\n","\n","c) quanto pagou ao sindicato.\n","\n","d) o salário líquido.\n","\n","e) calcule os descontos e o salário líquido, conforme a formatação abaixo:\n","\n"," + Salário Bruto : R$\n"," - IR (11%) : R$\n"," - INSS (8%) : R$\n"," - Sindicato ( 5%) : R$\n"," = Salário Liquido : R$"],"metadata":{"id":"K3myvbSTeAWH"}},{"cell_type":"code","source":["ganho_hora = float(input('Ganho por hora: '))\n","horas_mes = int(input('Horas de trabalho por mês: '))\n","\n","salario_bruto = ganho_hora*horas_mes\n","IR = 0.11*salario_bruto\n","INSS = 0.08*salario_bruto\n","sindicato = 0.05*salario_bruto\n","salario_liquido = salario_bruto - IR - INSS - sindicato\n","\n","print('+ Salário bruto: R$ %.2f' %salario_bruto)\n","print('- IR (11%%): R$ %.2f' %INSS)\n","print('- INSS (8%%): R$ %.2f' %IR)\n","print('- Sindicato (5%%): R$ %.2f' %sindicato)\n","print('= Salário líquido: R$ %.2f' %salario_liquido)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"40yDygX0eNTh","executionInfo":{"status":"ok","timestamp":1664274220208,"user_tz":180,"elapsed":12929,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"b49ae4a3-f27b-41da-bc48-3de8dc43d78d"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Ganho por hora: 80\n","Horas de trabalho por mês: 40\n","+ Salário bruto: R$ 3200.00\n","- IR (11%): R$ 256.00\n","- INSS (8%): R$ 352.00\n","- Sindicato (5%): R$ 160.00\n","= Salário líquido: R$ 2432.00\n"]}]},{"cell_type":"markdown","source":["Note que para imprimir o caracter de porcentagem em Python é preciso digitar %%, uma vez que % é reconhecido como um caracter especial da linguagem.\n","\n","Link para ambiente Google Colab: https://colab.research.google.com/drive/11u_lI0YY2Zt9FfqDukO12qeqTcugSmSd?usp=sharing\n","\n","“Aprender é a única coisa de que a mente nunca se cansa, nunca tem medo e nunca se arrepende.” \n","(Leonardo da Vinci)"],"metadata":{"id":"jHaTiv6weXVJ"}}]} -------------------------------------------------------------------------------- /PA1_Aula05.ipynb: -------------------------------------------------------------------------------- 1 | {"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"provenance":[],"collapsed_sections":[],"authorship_tag":"ABX9TyM9lFMnYgrrb6FytnY1K3Ph"},"kernelspec":{"name":"python3","display_name":"Python 3"},"language_info":{"name":"python"}},"cells":[{"cell_type":"markdown","source":["##**Programação e Algoritmos I**\n","\n","Prof Alexandre Levada\n","\n","###**Modularização e funções**\n","\n","Assim como aprendemos a utilizar diversas funções da linguagem Python como print(), input() e range(), iremos aprender a criar nossas próprias funções. A ideia consiste em empacotar um trecho de código para reutilizá-lo sempre que necessário. Em Python criamos uma função com a palavra reservada def. Para indicar o valor de retorno da função utilizamos a palavra-chave return. Por exemplo, suponha que desejamos empacotar numa função o código que computa o fatorial de n."],"metadata":{"id":"s89cc4niCxmQ"}},{"cell_type":"code","execution_count":null,"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"PNBTiVrECvQG","executionInfo":{"status":"ok","timestamp":1664300765811,"user_tz":180,"elapsed":295,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"497f391b-70c5-4430-908c-b4c85d4f84ae"},"outputs":[{"output_type":"stream","name":"stdout","text":["Fat(5) = 120 \n","Fat(6) = 720 \n","Fat(7) = 5040 \n"]}],"source":["def fatorial(n):\n"," fat = 1\n"," while n > 0:\n"," fat = fat*n\n"," n = n - 1\n"," return fat\n","\n","print('Fat(5) = %d ' %fatorial(5))\n","print('Fat(6) = %d ' %fatorial(6))\n","print('Fat(7) = %d ' %fatorial(7))"]},{"cell_type":"markdown","source":["**Variáveis globais e locais**\n","\n","Variáveis declaradas dentro dentro de uma função possuem escopo local, ou seja, não podem ser acessadas fora da função. Ao se usar o mesmo nome para designar variáveis dentro e fora da função, elas são objetos distintos."],"metadata":{"id":"8kjDSCnxM6fG"}},{"cell_type":"code","source":["a = 5\n","\n","def funcaoA():\n"," a = 7\n"," print('Valor de a dentro da função: %d' %a)\n","\n","print('Valor de a antes da função: %d' %a)\n","funcaoA()\n","print('Valor de a depois da função: %d' %a)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"_u1Vk1QiM-bG","executionInfo":{"status":"ok","timestamp":1664303357390,"user_tz":180,"elapsed":290,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"7d1111ef-5b27-473b-c94b-51baf910a98e"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Valor de a antes da função: 5\n","Valor de a dentro da função: 7\n","Valor de a depois da função: 5\n"]}]},{"cell_type":"markdown","source":["Para indicar que as duas variáveis são de fato a mesma, é necessário utilizar a palavra-chave global."],"metadata":{"id":"SbflFtvmNhNE"}},{"cell_type":"code","source":["a = 5\n","\n","def funcaoA():\n"," global a\n"," a = 7\n"," print('Valor de a dentro da função: %d' %a)\n","\n","print('Valor de a antes da função: %d' %a)\n","funcaoA()\n","print('Valor de a depois da função: %d' %a)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"iMpx0eP5Niiq","executionInfo":{"status":"ok","timestamp":1664303402232,"user_tz":180,"elapsed":282,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"8689a72a-56d9-4e81-fe60-47e65f18549e"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Valor de a antes da função: 5\n","Valor de a dentro da função: 7\n","Valor de a depois da função: 7\n"]}]},{"cell_type":"markdown","source":["**Ex 25:** Faça um função que retorne o n-ésimo termo da sequência de Fibonacci"],"metadata":{"id":"KbEoXBocPH5G"}},{"cell_type":"code","source":["# gera o n-ésimo termo da série de Fibonacci\n","def fibonacci(n):\n"," a = 1\n"," b = 1\n","\n"," if n == 1 or n == 2:\n"," nt('F(%d) = %d' %(n, b))\n"," else:\n"," for i in range(3, n+1): \n"," a, b = b, a+b\n","\n"," return b\n","\n","print('Fib(10) = %d' %fibonacci(10))\n","print('Fib(12) = %d' %fibonacci(12))\n","print('Fib(15) = %d' %fibonacci(15))\n"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"JifkVbnCPKbY","executionInfo":{"status":"ok","timestamp":1664303882484,"user_tz":180,"elapsed":303,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"7704b13e-5e1f-4709-dfcd-7b8328f38804"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Fib(10) = 55\n","Fib(12) = 144\n","Fib(15) = 610\n"]}]},{"cell_type":"markdown","source":["**Ex 26:** A função seno pode ser aproximada numericamente pela seguinte série\n","\n","$$\n","sen(x) = \\sum_{n=0}^{\\infty} \\frac{(-1)^n}{(2n+1)!} x^{2n+1} = x - \\frac{x^3}{3!} + \\frac{x^5}{5!} - ... \n","$$\n","\n","Faça um programa que aceite como entrada o valor do ângulo x em radianos e o número de termos n da série e imprima na tela o valor computado de sen(x)."],"metadata":{"id":"Ex7KY4STPicE"}},{"cell_type":"code","source":["import math\n","\n","def fatorial(n):\n","\tfat = 1\n","\tfor i in range(1, n+1):\n","\t\tfat = fat*i\n","\treturn fat\n","\n","def seno(x, n):\n","\tsoma = 0\n","\tfor i in range(0, n+1):\n","\t\tsoma = soma + (-1)**i*x**(2*i+1)/fatorial(2*i+1)\n","\treturn soma\n","\n","x = float(input('Entre com o valor do angulo (radianos) : '))\n","n = int(input('Entre com o número de termos da série (n): '))\n","\n","print('sen(%f) = %.9f' %(x, seno(x, n)))\n","print('Valor exato: %.9f' %(math.sin(x)))"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"7_WI7StAP-7k","executionInfo":{"status":"ok","timestamp":1664304223969,"user_tz":180,"elapsed":6098,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"2c3ef8c3-023e-4bb6-d827-91618f4cfb01"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Entre com o valor do angulo (radianos) : 1.68\n","Entre com o número de termos da série (n): 10\n","sen(1.680000) = 0.994043202\n","Valor exato: 0.994043202\n"]}]},{"cell_type":"markdown","source":["**Ex 27:** A função cosseno pode ser aproximada numericamente pela seguinte série\n","\n","$$\n","cos(x) = \\sum_{n=0}^{\\infty} \\frac{(-1)^n}{(2n)!} x^{2n} = 1 - \\frac{x^2}{2!} + \\frac{x^4}{4!} - ... \n","$$\n","\n","Faça uma função que aceite como entrada o valor do ângulo x em radianos e o número de termos n da série e imprima na tela o valor computado de cos(x)."],"metadata":{"id":"57TlXg8FQ1Q7"}},{"cell_type":"code","source":["def fatorial(n):\n","\tfat = 1\n","\tfor i in range(1, n+1):\n","\t\tfat = fat*i\n","\treturn fat\n","\n","def cosseno(x, n):\n","\tsoma = 0\n","\tfor i in range(0, n+1):\n","\t\tsoma = soma + (-1)**i*x**(2*i)/fatorial(2*i)\n","\treturn soma\n","\n","x = float(input('Entre com o valor do angulo (radianos) : '))\n","n = int(input('Entre com o número de termos da série (n): '))\n","\n","print('cos(%.1f) = %f' %(x, cosseno(x, n)))"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"Gg1kOtJsRJeP","executionInfo":{"status":"ok","timestamp":1664304346761,"user_tz":180,"elapsed":10019,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"c2c63619-1771-4b47-e895-ac47bf2f8e81"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Entre com o valor do angulo (radianos) : 3.1415\n","Entre com o número de termos da série (n): 10\n","cos(3.1) = -1.000000\n"]}]},{"cell_type":"markdown","source":["**Ex 28:** A função exponencial pode ser aproximada numericamente pela seguinte série\n","\n","$$\n","e^x = \\sum_{n=0}^{\\infty} \\frac{x^n}{n!} x^{2n} = 1 + x + \\frac{x^2}{2!} + \\frac{x^3}{3!} + \\frac{x^4}{4!} + ... \n","$$\n","\n","Faça uma função que aceite como entrada o valor do ângulo x em radianos e o número de termos n da série e imprima na tela o valor computado de exp(x)."],"metadata":{"id":"44B8DYsnTPcv"}},{"cell_type":"code","source":["import math\n","\n","def fatorial(n):\n","\tfat = 1\n","\tfor i in range(1, n+1):\n","\t\tfat = fat*i\n","\treturn fat\n","\n","def exponencial(x, n):\n","\tsoma = 0\n","\tfor i in range(0, n+1):\n","\t\tsoma = soma + (x**i)/fatorial(i)\n","\treturn soma\n","\n","x = float(input('Entre com o valor do expoente (x) : '))\n","n = int(input('Entre com o número de termos da série (n): '))\n","\n","print('exp(%.1f) = %.9f' %(x, exponencial(x, n)))\n","print('Valor exato: %.9f' %(math.exp(x)))"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"7GsAg6pjUr-G","executionInfo":{"status":"ok","timestamp":1664305259986,"user_tz":180,"elapsed":5328,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"6cb32314-4712-4ca3-8ec7-b129ff1918f9"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Entre com o valor do expoente (x) : 1\n","Entre com o número de termos da série (n): 10\n","exp(1.0) = 2.718281801\n","Valor exato: 2.718281828\n"]}]},{"cell_type":"markdown","source":["**Ex 29:** Um número de Keith é um inteiro maior que 9, tal que os seus dígitos, ao serem usados para iniciar uma sequencia de Fibonacci, alcançam posteriormente o referido número. Um exemplo é o número 14, pois 1 + 4 = 5, 4 + 5 = 9 e 5 + 9 = 14. Pergunta-se: quantos e quais são os números de Keith menores que 100? Faça um programa para determinar a resposta."],"metadata":{"id":"rXiWrZFvWzHe"}},{"cell_type":"code","source":["# Função que retorna True se a sequencia iniciada com a e b atinge num\n","def fib(a, b, num):\n"," converge = False\n"," while b <= num:\n"," a, b = b, a+b\n"," if b == num:\n"," converge = True\n"," \n"," return converge\n","\n","# Computa quais são os números de Keith de 10 até 99\n","def Keith():\n"," qtde = 0\n"," for num in range(10, 100):\n"," a = num // 10 # pega a dezena\n"," b = num % 10 # pega a unidade\n"," if fib(a, b, num):\n"," qtde += 1\n"," print('Número de Keith %d: %d' %(qtde, num))\n","\n","Keith()"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"pqG3Nt-5W7P2","executionInfo":{"status":"ok","timestamp":1664306142439,"user_tz":180,"elapsed":298,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"ea9e2ae0-832e-43a8-a48c-977e69665801"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Número de Keith 1: 14\n","Número de Keith 2: 19\n","Número de Keith 3: 28\n","Número de Keith 4: 47\n","Número de Keith 5: 61\n","Número de Keith 6: 75\n"]}]},{"cell_type":"markdown","source":["**Ex 30:** Pelo método de Newton, pode-se mostrar que que a seguinte relação de recorrência pode ser utilizada para computar numericamente uma aproximação para a raiz quadrada de a.\n","\n","$$\n","x_{k+1} = \\frac{1}{2}\\left( x_k + \\frac{a}{x_k} \\right)\n","$$\n","\n","onde $x_0 = 1$ e a é o número cuja raiz é desejada. Faça uma função que receba como entrada num número a e retorne como saída sua raiz quadrada."],"metadata":{"id":"kzmwrPqzYMDm"}},{"cell_type":"code","source":["def calcula_raiz(a):\n"," x = 1\n"," \n"," while True:\n"," x_novo = 0.5*(x + a/x)\n"," erro = abs(x - x_novo)\n"," print('x : %.10f ***** Erro: %.10f' %(x_novo, erro))\n"," x = x_novo \n"," if erro < 10**(-8):\n"," break\n"," \n"," return x\n","\n","# Início do script\n","a = float(input('Enter com o valor de a: '))\n","raiz = calcula_raiz(a)\n","print('A raíz quadrada de %.3f é %f' %(a, raiz))"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"rhms7GNCYj0E","executionInfo":{"status":"ok","timestamp":1664306297754,"user_tz":180,"elapsed":15487,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"02afdd66-44e3-4ae1-9589-09036c533254"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Enter com o valor de a: 1234\n","x : 617.5000000000 ***** Erro: 616.5000000000\n","x : 309.7491902834 ***** Erro: 307.7508097166\n","x : 156.8665293238 ***** Erro: 152.8826609596\n","x : 82.3665447737 ***** Erro: 74.4999845501\n","x : 48.6741778473 ***** Erro: 33.6923669265\n","x : 37.0132146907 ***** Erro: 11.6609631566\n","x : 35.1763293664 ***** Erro: 1.8368853243\n","x : 35.1283688806 ***** Erro: 0.0479604859\n","x : 35.1283361405 ***** Erro: 0.0000327400\n","x : 35.1283361405 ***** Erro: 0.0000000000\n","A raíz quadrada de 1234.000 é 35.128336\n"]}]},{"cell_type":"markdown","source":["**Ex 31:** Números primos são muito importantes em diversas aplicações que vão desde fatoração de números inteiros até criptografia de dados. Faça um programa que compute a soma de todos números primos menores que N, onde N é fornecido como entrada. \n","\n","a) Compute o valor da soma e o tempo gasto para computá-la se N=1000\n","\n","b) Compute o valor da soma e o tempo gasto para computá-la se N=10000\n","\n","c) Compute o valor da soma e o tempo gasto para computá-la se N=100000"],"metadata":{"id":"2B_NlxHwaFbt"}},{"cell_type":"code","source":["import time\n","\n","# verifica se inteiro n é primo\n","def verifica_primo(n):\n"," divisor = 2\n"," primo = True \n"," # o número 1 não é primo!\n"," if n == 1:\n"," return False\n"," # // representa a divisão inteira\n"," while (divisor <= n//2 ) and (primo):\n"," if (n % divisor == 0): \n"," primo = False \n"," else:\n"," divisor = divisor + 1 \n"," return primo\n","\n","# Inicio do programa\n","N = int(input('Entre com o valor de N: '))\n","\n","inicio = time.time()\n","soma = 0 \n","for i in range(2, N):\n"," # Só precisa testar se é primo se i for ímpar\n"," if verifica_primo(i):\n"," soma = soma + i\n","\n","print('A soma dos primos menores que %d é %d' %(N,soma))\n","fim = time.time()\n","tempo = fim - inicio\n","print('Tempo: %f segundos' %tempo)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"UE0DdwGzaKXL","executionInfo":{"status":"ok","timestamp":1664306769828,"user_tz":180,"elapsed":31421,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"e7560128-37d1-4541-e69f-5cf3cdb36ffc"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Entre com o valor de N: 100000\n","A soma dos primos menores que 100000 é 454396537\n","Tempo: 26.989085 segundos\n"]}]},{"cell_type":"markdown","source":["**Funções Lambda**\n","\n","Em Python, há uma maneira alternativa de definir funções curtas sem a necessidade de criar uma função com o comando def. São as chamadas funções Lambda. Elas são cohecidas por serem funções anônimas. Em diversas ocasoões, podemos utilizá-las no código no lugar das funções explícitas. Em geral, as funções Lambda são úteis para realizar operações atômicas, ou seja, com complexidade constante. Por essa razão, essas expressões são restritas a uma única linha de código, possuindo uma sintaxe mais curta do que uma função normal em Python. A seguir ilustramos uma simples função Lambda que soma dois números."],"metadata":{"id":"_Q3IDedW_k1E"}},{"cell_type":"code","source":["# Definição da função\n","f = lambda x, y: x + y\n","# Chamando a função\n","f(2, 3)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"ocnFNmc3BI30","executionInfo":{"status":"ok","timestamp":1664367286311,"user_tz":180,"elapsed":18,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"05387461-05a1-4ffc-cd15-a61f120fe136"},"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["5"]},"metadata":{},"execution_count":1}]},{"cell_type":"markdown","source":["Em geral, a metodologia para a definição de uma função lambda segue os seguintes passos:\n","\n","1. Define-se a função com a palavra reservada lambda\n","2. Insere-se os parâmetros\n","3. Adiciona-se o caracter : após os parâmetros para indicar o início da lógica\n","4. Implementa-se a lógica da função (o que ela calcula)\n","5. Opcionalmente, pode-se definir uma variável de retorno para a função (armazenamento)\n","\n","Note que se não utilizarmos o passo 5, a função fica totalmente anônima!"],"metadata":{"id":"LxDhODdbBfSz"}},{"cell_type":"code","source":["(lambda x, y: x + y)(2, 3)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"PiHJrkPICauW","executionInfo":{"status":"ok","timestamp":1664367598435,"user_tz":180,"elapsed":420,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"68b79c10-b002-4f19-edac-a4615b16a195"},"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["5"]},"metadata":{},"execution_count":2}]},{"cell_type":"markdown","source":["As principais diferenças das funções Lambda para as funções tradicionais são:\n","\n","* Não é preciso utilizar a palavra chave do def para definir\n","* Não é preciso utilizar a palavra chave return para retornar o resultado\n","* É possível definir a função e utilizá-la com apenas 1 linha de código\n","\n","As funções Lambda a seguir fazem operações lógicas e aritméticas."],"metadata":{"id":"zRJzXbSNCsRE"}},{"cell_type":"code","source":["# Retorna o maior de 2 números\n","f = lambda x, y: x if x > y else y\n","f(6, 7)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"dfXmDcRXDVUV","executionInfo":{"status":"ok","timestamp":1664368070712,"user_tz":180,"elapsed":372,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"131c29a3-e2c1-4d08-c3b7-f48597095804"},"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["6"]},"metadata":{},"execution_count":5}]},{"cell_type":"code","source":["# Retorna a soma dos 2 primeiros valores se o terceiro é positivo ou a subtração dos 2 primeiros valores se o terceiro é negativo\n","g = lambda x, y, z: x + y if z >= 0 else x - y\n","g(10, 4, 1)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"YVwSRVf1EYkF","executionInfo":{"status":"ok","timestamp":1664368098584,"user_tz":180,"elapsed":438,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"8de4f904-3a50-4030-85ba-d1fc189f7d24"},"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["14"]},"metadata":{},"execution_count":6}]},{"cell_type":"code","source":["# Retorna a soma dos 2 primeiros valores se o terceiro é positivo ou a subtração dos 2 primeiros valores se o terceiro é negativo\n","g = lambda x, y, z: x + y if z >= 0 else x - y\n","g(10, 4, -1)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"_IZ4sO0UEcxu","executionInfo":{"status":"ok","timestamp":1664368111058,"user_tz":180,"elapsed":511,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"ac9a294f-b603-4b09-c371-dbaef295f4a0"},"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["6"]},"metadata":{},"execution_count":7}]},{"cell_type":"markdown","source":["**Ex 32:** O método de Newton é um algoritmo numérico para calcular a raiz (zero) de uma função qualquer. Ele é baseado na seguinte iteração:\n","\n","$$\n","x_{k+1} = x_k - \\frac{f(x_k)}{f'(x_k)}\n","$$\n","\n","onde $x_0$ é um chute inicial (arbitrário) e f'(x) denota a derivada dea função f(x). Após um certo número de passos, a diferença entre $x_k$ e $x_{k+1}$ em módulo tende a zero, o que significa que o algoritmo convergiu para a solução desejada. Implemente o método de Newton para encontrar a raiz da função a seguir:\n","\n","$$\n","f(x) = x^3 - 4x^2 + 7x - 2\n","$$\n","\n","cuja derivada é dada por:\n","\n","$$\n","f'(x) = 3x^2 - 8x + 7\n","$$"],"metadata":{"id":"rbHsTPPDbEu1"}},{"cell_type":"code","source":["from math import exp\t\t# importa a função exponencial do pacote math\n","from math import sin\t\t# importa a função seno do pacote math\n","from math import cos\t\t# importa a função cosseno do pacote math\n","\n","# encontra a raíz da função f usando chute inicial x e derivada df\n","def newton(x, f, df):\n"," while True:\n"," novo_x = x - f(x)/df(x)\n"," erro = abs(x - novo_x)\n"," print('x : %.10f ***** Erro: %.10f' %(novo_x, erro))\n"," x = novo_x\n"," \n"," if erro <= 10**(-8):\n"," break\n"," \n"," return x\n","\n","# Define as funções matemáticas com lambda functions\n","f = lambda x : x**3 - 4*x**2 + 7*x - 2\n","df = lambda x : 3*x**2 - 8*x + 7\n"," \n","x0 = float(input('Entre com o chute inicial (x0): '))\n","raiz = newton(x0, f, df)\n","print('Raiz da função: %f' %raiz)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"q12Fdj9WbQit","executionInfo":{"status":"ok","timestamp":1664307196568,"user_tz":180,"elapsed":2696,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"701d4c75-ff7a-44e6-c833-5c4b6788b81b"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Entre com o chute inicial (x0): 5\n","x : 3.6190476190 ***** Erro: 1.3809523810\n","x : 2.5611662214 ***** Erro: 1.0578813976\n","x : 1.5125924781 ***** Erro: 1.0485737433\n","x : -0.1306327447 ***** Erro: 1.6432252228\n","x : 0.2380460431 ***** Erro: 0.3686787878\n","x : 0.3418992072 ***** Erro: 0.1038531641\n","x : 0.3493349244 ***** Erro: 0.0074357173\n","x : 0.3493708077 ***** Erro: 0.0000358833\n","x : 0.3493708086 ***** Erro: 0.0000000008\n","Raiz da função: 0.349371\n"]}]},{"cell_type":"markdown","source":["####**Aplicação interessante**\n","\n","O número de um CPF tem 9 algarismos e mais dois dígitos verificadores, que são indicados após uma barra. Logo, um CPF tem 11 algarismos. O número do CPF é escrito na forma ABCDEFGHI-JK ou diretamente como ABCDEFGHIJK, onde os algarismos não podem ser todos iguais entre si.\n","\n","O J é chamado 1° dígito verificador do número do CPF.\n","\n","O K é chamado 2° dígito verificador do número do CPF.\n","\n","**Primeiro Dígito**\n","\n","Para obter J multiplicamos A, B, C, D, E, F, G, H e I pelas constantes correspondentes:\n","\n","A x 10, B x 9, C x 8, D x 7, E x 6, F x 5, G x 4, H x 3, I x 2\n","\n","O resultado da soma, S = (10A + 9B + 8C + 7D + 6E + 5F + 4G + 3H + 2I), é dividido por 11. Analisamos então o RESTO dessa divisão:\n","\n","Se for 0 ou 1, o dígito J é 0 (zero). Se for 2, 3, 4, 5, 6, 7, 8, 9 ou 10, o dígito J é (11 - RESTO)\n","\n","**Segundo Dígito**\n","\n","Já temos J. Para obter K multiplicamos A, B, C, D, E, F, G, H, I e J pelas constantes: \n","\n","A x 11, B x 10, C x 9, D x 8, E x 7, F x 6, G x 5, H x 4, I x 3, J x 2\n","\n","O resultado da soma, S = 11A + 10B + 9C + 8D + 7E + 6F + 5G + 4H + 3I + 2J, é dividido por 11. Verificamos então o RESTO dessa divisão: se for 0 ou 1, o dígito K é 0 (zero). Se for 2, 3, 4, 5, 6, 7, 8, 9 ou 10, o dígito K é (11 - RESTO).\n","\n","Faça uma função em Python que recebe os 9 primeiros dígitos de um CPF e gere os 2 dígitos verificadores. Teste com o seu CPF."],"metadata":{"id":"glV1cxlQalWa"}},{"cell_type":"code","source":["# Os dígitos do CPF formam uma string (sequência de caracteres).\n","# É preciso converter cada dígito para inteiro para fazer os cálculos\n","def digito_verificador(cpf):\n"," ############ Cálculo do primeiro dígito\n"," soma = 0\n"," # Nesse laço, o valor de i é o multiplicador do dígito\n"," for i in range(10, 1, -1):\n"," k = 10 - i # índice para os dígitos do CPF\n"," soma = soma + i*int(cpf[k]) \n"," resto = soma % 11\n"," \n"," if resto == 0 or resto == 1:\n"," primeiro_digito = 0\n"," else:\n"," primeiro_digito = 11 - resto\n"," \n"," # Anexa o primeiro dígito no CPF\n"," # Soma de strings = concatenação: ‘ab’ + ‘cd’ = ‘abcd’ \n"," cpf = cpf + str(primeiro_digito)\n"," \n"," ############ Cálculo do segundo dígito\n"," soma = 0 \n"," # Nesse laço, o valor de i é o multiplicador do dígito\n"," for i in range(11, 1, -1):\n"," k = 11 - i # índice para os dígitos do CPF\n"," soma = soma + i*int(cpf[k])\n"," resto = soma % 11\n"," \n"," if resto == 0 or resto == 1:\n"," segundo_digito = 0\n"," else:\n"," segundo_digito = 11 - resto\n"," \n"," # Anexa o segundo dígito no CPF\n"," cpf = cpf + str(segundo_digito)\n"," \n"," return cpf\n","\n","# Início do script\n","numeros = input('Entre com os 9 primeiros dígitos do CPF: ')\n","cpf = digito_verificador(numeros)\n","print('CPF: ', cpf)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"Dp2-vxGjaw4-","executionInfo":{"status":"ok","timestamp":1664306871823,"user_tz":180,"elapsed":11469,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"8c1b6872-591c-42ae-f84b-dc5d9dfdd831"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Entre com os 9 primeiros dígitos do CPF: 123456789\n","CPF: 12345678909\n"]}]},{"cell_type":"markdown","source":["Link para o ambiente Google Colab: https://colab.research.google.com/drive/1Cn3wJvy-rEl9KKY_MDCuJjFhVUR4XUuC?usp=sharing\n","\n","\"Start by doing what's necessary; then do what's possible; and suddenly you're doing the impossible.\" (Francis of Assisi)"],"metadata":{"id":"7Rqr7LTNa6bI"}}]} -------------------------------------------------------------------------------- /PA1_Aula06.ipynb: -------------------------------------------------------------------------------- 1 | {"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"provenance":[],"collapsed_sections":[],"authorship_tag":"ABX9TyOpVP5oNI9CtCbewuS3dljh"},"kernelspec":{"name":"python3","display_name":"Python 3"},"language_info":{"name":"python"}},"cells":[{"cell_type":"markdown","source":["##**Programação e Algoritmos I**\n","\n","Prof Alexandre Levada\n","\n","###**Variáveis compostas unidimensionais: listas, strings e vetores**\n","\n","Variáveis simples nos permitem armazenar apenas uma informação atômica. Por atômica, queremos dizer: um simples número ou um caracter. Porém, em diversos problemas deseja-se armazenar um conjunto de informações, como por exemplo, um vetor de números reais ou uma cadeia de caracteres (string). Para isso, existem as variáveis compostas. Iniciaremos o nosso estudo pelas variáveis compostas unidimensionais, que são aquelas em que basta apenas um índice para localizar cada elemento do conjunto.\n","\n","Em Python, a principal variável composta unidomensional é a Lista. Uma Lista em Python é uma coleção de objetos, que podem ou não ser do mesmo tipo. Por essa razão, dizemos que listas em Python são variáveis compostas heterogêneas. Dizemos que uma lista é uma estrutura de dados estruturas de dados em Python para armazenar uma coletânea de objetos de forma indexada, ou seja, em cada posição da lista temos uma variável. A figura a seguir ilustra essa ideia como um trem de dados.\n","\n","![python-list.png](data:image/png;base64,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)"],"metadata":{"id":"wpavlbbUeyhz"}},{"cell_type":"markdown","source":["Em Python, existem listas e tuplas, que são estruturas muito similares. A única diferença entre uma tupla e uma lista, é que tuplas são objetos imutáveis, ou seja, uma vez criados não podem ser modificados. Em outras palavras, é impossível usar o operador de atribuição com uma tupla. As listas por outro lado podem ser modificadas sempre que necessário e portanto são muito mais utilizadas na prática do que as tuplas. "],"metadata":{"id":"R66HfduI8NTy"}},{"cell_type":"code","execution_count":null,"metadata":{"id":"xlcbMSZ8ext6","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1664315673239,"user_tz":180,"elapsed":8,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"73154ddc-98a1-42e9-8fb7-beaff4397adb"},"outputs":[{"output_type":"stream","name":"stdout","text":["7.5\n"]}],"source":["# cria uma lista vazia\n","lista = []\n","# cria uma lista com 3 notas\n","notas = [7.5, 9, 8.3]\n","# imprime a primeira nota\n","print(notas[0])\n","# mudando a primeira nota\n","notas[0] = 8.7"]},{"cell_type":"markdown","source":["Veremos a seguir uma série de comandos da linguagem Python para minipulação de listas."],"metadata":{"id":"A9cLQfR58nXO"}},{"cell_type":"code","source":["import random\n","\n","# cria uma lista com 5 elementos\n","la = [1,2,3,4,5]\n","print('Lista la possui %d elementos' %len(la))\n","print(la)\n","\n","input('Pressione qualquer tecla para continuar...')\n","\n","lb = []\n","# cria uma lista com 5 números aleatórios entre 0 e 99\n","for i in range(5):\n"," lb.append(random.randint(0, 100))\n","\n","print('Lista lb possui %d elementos aleatórios' %len(lb))\n","print(lb)\n","input('Pressione qualquer tecla para continuar...')\n","\n","# concatena 2 listas e gera uma nova\n","lc = la + lb\n","print('Lista lc = la + lb possui %d elementos' %len(lc))\n","print(lc)\n","\n","input('Pressione qualquer tecla para continuar...')\n","\n","print('Percorre lista incrementando cada elemento')\n","for i in range(len(lc)):\n"," lc[i] += 1\n","print(lc)\n","\n","input('Pressione qualquer tecla para continuar...')\n","\n","# insere elementos no final da lista\n","lc.append(99)\n","lc.append(72)\n","print('Após inserção de 99 e 72 lc tem %d elementos' %len(lc))\n","print(lc)\n","\n","input('Pressione qualquer tecla para continuar...')\n","\n","# ordena a lista \n","print('Lista lc ordenada')\n","lc.sort()\n","print(lc)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"A2nNcdWP8oat","executionInfo":{"status":"ok","timestamp":1664315759887,"user_tz":180,"elapsed":22892,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"3abbdd90-e656-4635-fcc5-755797c3c2d1"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Lista la possui 5 elementos\n","[1, 2, 3, 4, 5]\n","Pressione qualquer tecla para continuar...\n","Lista lb possui 5 elementos aleatórios\n","[57, 29, 1, 55, 53]\n","Pressione qualquer tecla para continuar...\n","Lista lc = la + lb possui 10 elementos\n","[1, 2, 3, 4, 5, 57, 29, 1, 55, 53]\n","Pressione qualquer tecla para continuar...\n","Percorre lista incrementando cada elemento\n","[2, 3, 4, 5, 6, 58, 30, 2, 56, 54]\n","Pressione qualquer tecla para continuar...\n","Após inserção de 99 e 72 lc tem 12 elementos\n","[2, 3, 4, 5, 6, 58, 30, 2, 56, 54, 99, 72]\n","Pressione qualquer tecla para continuar...\n","Menor elemento de lc é 2\n","Maior elemento de lc é 99\n","Lista lc ordenada\n","[2, 2, 3, 4, 5, 6, 30, 54, 56, 58, 72, 99]\n"]}]},{"cell_type":"markdown","source":["**Ex 33:** Faça um programa que leia uma lista de 5 números inteiros e mostre-a na tela."],"metadata":{"id":"tJdN1OI2nkCc"}},{"cell_type":"code","source":["L = []\n","i = 1\n","while i<= 5:\n"," n = int(input('Digite um número: '))\n"," L.append(n)\n"," i = i + 1\n","print('Lista: ', L)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"99d9JzBSnoA_","executionInfo":{"status":"ok","timestamp":1664327178251,"user_tz":180,"elapsed":15691,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"a438f868-8b72-4b5e-d9e9-80f20b5bfcfc"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Digite um número: 4\n","Digite um número: 1\n","Digite um número: 2\n","Digite um número: 7\n","Digite um número: 5\n","Lista: [4, 1, 2, 7, 5]\n"]}]},{"cell_type":"markdown","source":["**Ex 34:** Faça um programa que leia 4 notas, armazene-as em uma lista e mostre-as na tela juntamente com a média."],"metadata":{"id":"g8CarsvRoZQ5"}},{"cell_type":"code","source":["notas = []\n","soma = 0\n","i = 1\n","while i <= 4:\n"," n = float(input('Nota: '))\n"," notas.append(n)\n"," soma += n\n"," i += 1\n","print('Notas: ', notas)\n","print('Média: %.2f' %(soma/4))"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"42_LY4pUocnp","executionInfo":{"status":"ok","timestamp":1664330931965,"user_tz":180,"elapsed":20915,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"6b270dc9-1000-4bf5-ed17-a72bd3913345"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Nota: 9\n","Nota: 7.5\n","Nota: 6\n","Nota: 8\n","Notas: [9.0, 7.5, 6.0, 8.0]\n","Média: 7.62\n"]}]},{"cell_type":"markdown","source":["**Slicing (Fatiamento)**\n","\n","Ao se trabalhar com listas em Python, uma ferramenta bastante poderosa para obter subconjuntos de uma lista é a técnica conhecida como slicing. Perguntas como quais são os elementos das posições pares, ou qual é a sublista obtida entre o terceiro e o sétimo elemento podem ser facilmente respondidas através do fatiamento. Suponha a lista L = [9, 8, 7, 6, 5, 4, 3, 2, 1].\n","\n","L[-1] retorna o último elemento: 1\n","\n","L[-2] retorna o penúltimo elemento: 2\n","\n","L[-3] retorna o antepenúltimo elemento: 3\n","\n","L[:3] retorna: [9, 8, 7] (note que não inclui o limite superior)\n","\n","L[3:] retorna: [6, 5, 4, 3, 2, 1]\n","\n","L[2:5] retorna: [7, 6, 5]\n","\n","L[::2] retorna: [9, 7, 5, 3, 1] (apenas as posições pares)\n","\n","L[::3] retorna: [9, 6, 3]\n","\n","L[::-1] retorna: [1, 2, 3, 4, 5, 6, 7, 8, 9] (lista ao contrário)\n","\n","L[::-2] retorna: [1, 3, 5, 7, 9] \n","\n","**List comprehensions**\n","\n","Suponha agora que desejamos criar uma nova lista L2 que contenha somente os elementos de L que sejam divisíveis por 3. Uma forma rápida de construir L2 é através da técnica list comprehensions."],"metadata":{"id":"aDd_aMDv2wmp"}},{"cell_type":"code","source":["L = [9, 8, 7, 6, 5, 4, 3, 2, 1]\n","\n","L2 = [x for x in L if x % 3 == 0]\n","\n","print(L2)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"AdQ1dOgczXWi","executionInfo":{"status":"ok","timestamp":1664363663857,"user_tz":180,"elapsed":323,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"048105cb-03b5-4ee4-dc38-b548e8e6c6ae"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["[9, 6, 3]\n"]}]},{"cell_type":"markdown","source":["Por exemplo, se desejamos construir L3 com os números pares, teremos:"],"metadata":{"id":"izMux1-kzkiP"}},{"cell_type":"code","source":["L3 = [x for x in L if x % 2 == 0]\n","\n","print(L3)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"mzA_G5y2zl0C","executionInfo":{"status":"ok","timestamp":1664363707965,"user_tz":180,"elapsed":314,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"8f6f7bb2-9c8d-467b-dbb7-d9b9f1e1d174"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["[8, 6, 4, 2]\n"]}]},{"cell_type":"markdown","source":["Suponha agora que desejamos criar L4 com o quadrado dos números ímpares:"],"metadata":{"id":"8gcesyfIzvLW"}},{"cell_type":"code","source":["L4 = [x**2 for x in L if x% 2 == 1]\n","\n","print(L4)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"zMAXyXxdzwPw","executionInfo":{"status":"ok","timestamp":1664363740930,"user_tz":180,"elapsed":267,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"341e09c7-d6d4-4b94-8445-0591c59e9c14"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["[81, 49, 25, 9, 1]\n"]}]},{"cell_type":"markdown","source":["Veremos a seguir problemas e exercícios que utilizam estruturas do tipo lista.\n","\n","**Ex 35:** Supondo que uma lista de n elementos reais represente um vetor no $R^n$, faça uma função para computar o produto escalar entre 2 vetores."],"metadata":{"id":"qezZ2r4fz2l0"}},{"cell_type":"code","source":["# Calcula o produto escalar entre 2 vetores \n","def produto_escalar(u, v): \n","\tsoma = 0 \n","\tfor i in range(len(u)): \n","\t\tsoma = soma + u[i]*v[i] \n","\treturn soma\n","\n","u = [1, 2, 3]\n","v = [4, 5, 6]\n","x = produto_escalar(u, v)\n","print(x)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"54bceMw-z-xa","executionInfo":{"status":"ok","timestamp":1664363831816,"user_tz":180,"elapsed":368,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"16f4ccbf-b5a5-4a0d-ab88-ed06e8a25fe1"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["32\n"]}]},{"cell_type":"markdown","source":["Faça uma função que compute a norma de um vetor: $|| \\vec{v} || = \\sqrt{v_1^2 + v_2^2 + ... + v_n^2}$ \n","\n","**Ex 36:** Faça uma função que encontre o maior elemento de uma lista."],"metadata":{"id":"XL1MfatA0PNY"}},{"cell_type":"code","source":["# Retorna o maior elemento de uma lista de inteiros \n","def maximo(lista): \n","\tmaior = lista[0] \n","\tfor i in range(len(lista)): \n","\t\tif lista[i] > maior: \n","\t\t\tmaior = lista[i] \n","\treturn maior \n","\n","L = [4, 1, 5, 3, 7, 6, 0]\n","\n","m = maximo(L)\n","print('Máximo: ', m)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"qwDItSOe0rzw","executionInfo":{"status":"ok","timestamp":1664364023123,"user_tz":180,"elapsed":271,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"5570c976-0145-440a-fab3-9b3774e0264e"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Máximo: 7\n"]}]},{"cell_type":"markdown","source":["Faça uma função para encontra o mínimo elemento de uma lista L.\n","\n","**Ex 37:** Uma tarefa fundamental na computação consiste em dado uma lista e um valor qualquer, verificar se aquele valor pertence a lista ou não. Essa funcionalidade é usada por exemplo em qualquer sistema que exige o login de um usuário (para verificar se o CPF da pessoa está cadastrada). Faça uma função que, dada uma lista de inteiros L e um número inteiro x, verifique se x está ou não em L. A função deve retornar o índice do elemento (posição) caso ele pertença a ele ou o valor lógico False se ele não pertence a L. (isso equivale ao operador in de Python)"],"metadata":{"id":"iOMvvCXI0679"}},{"cell_type":"code","source":["def busca_sequencial(lista, x): \n","\tachou = False \n","\ti = 0 \n","\twhile i < len(lista) and not achou: \n","\t\tif (lista[i] == x): \n","\t\t\tachou = True \n","\t\t\tpos = i\t \n","\t\telse: \n","\t\t\ti = i + 1\t\t \n","\tif achou: \n","\t\treturn pos \n","\telse: \n","\t\treturn achou \n","\n","L = [4, 1, 5, 3, 7, 6, 0]\n","\n","p = busca_sequencial(L, 7)\n","q = busca_sequencial(L, 99)\n","\n","print('Elemento 7: ', p)\n","print('Elemento 99: ', q)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"YRM6izxG2-KV","executionInfo":{"status":"ok","timestamp":1664364679567,"user_tz":180,"elapsed":411,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"ada45fa6-d01c-4131-d53f-a863747e0250"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Elemento 7: 4\n","Elemento 99: False\n"]}]},{"cell_type":"markdown","source":["**Ex 38:** Deseja-se contar quantos números entre 1000 e 9999 (inclusive) são ímpares, divisíveis por 7 e cujo primeiro algarismo é um número par. Como resolver o problema em Python com listas?"],"metadata":{"id":"T2hFKhVY3gua"}},{"cell_type":"code","source":["def impar(n):\n"," if n % 2 == 1:\n"," return True\n"," \n","def div_por_7(n):\n"," if n % 7 == 0:\n"," return True\n"," \n","def inicia_par(s):\n"," num = int(s[0])\n"," if num % 2 == 0:\n"," return True\n","\n","def armazena_numeros(low, high):\n"," L = []\n"," for i in range(low, high+1):\n"," s = str(i) # converte para string\n"," if impar(i) and div_por_7(i) and inicia_par(s):\n"," L.append(i)\n"," return L\n","\n","lista = armazena_numeros(1000, 10000)\n","\n","print(lista)\n","print('Há %d números satisfazendo as condições.' %(len(lista)))"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"gbwSUK-h3jP-","executionInfo":{"status":"ok","timestamp":1664364765001,"user_tz":180,"elapsed":444,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"cd86b551-f0e5-4142-aa79-071561bb350e"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["[2009, 2023, 2037, 2051, 2065, 2079, 2093, 2107, 2121, 2135, 2149, 2163, 2177, 2191, 2205, 2219, 2233, 2247, 2261, 2275, 2289, 2303, 2317, 2331, 2345, 2359, 2373, 2387, 2401, 2415, 2429, 2443, 2457, 2471, 2485, 2499, 2513, 2527, 2541, 2555, 2569, 2583, 2597, 2611, 2625, 2639, 2653, 2667, 2681, 2695, 2709, 2723, 2737, 2751, 2765, 2779, 2793, 2807, 2821, 2835, 2849, 2863, 2877, 2891, 2905, 2919, 2933, 2947, 2961, 2975, 2989, 4011, 4025, 4039, 4053, 4067, 4081, 4095, 4109, 4123, 4137, 4151, 4165, 4179, 4193, 4207, 4221, 4235, 4249, 4263, 4277, 4291, 4305, 4319, 4333, 4347, 4361, 4375, 4389, 4403, 4417, 4431, 4445, 4459, 4473, 4487, 4501, 4515, 4529, 4543, 4557, 4571, 4585, 4599, 4613, 4627, 4641, 4655, 4669, 4683, 4697, 4711, 4725, 4739, 4753, 4767, 4781, 4795, 4809, 4823, 4837, 4851, 4865, 4879, 4893, 4907, 4921, 4935, 4949, 4963, 4977, 4991, 6013, 6027, 6041, 6055, 6069, 6083, 6097, 6111, 6125, 6139, 6153, 6167, 6181, 6195, 6209, 6223, 6237, 6251, 6265, 6279, 6293, 6307, 6321, 6335, 6349, 6363, 6377, 6391, 6405, 6419, 6433, 6447, 6461, 6475, 6489, 6503, 6517, 6531, 6545, 6559, 6573, 6587, 6601, 6615, 6629, 6643, 6657, 6671, 6685, 6699, 6713, 6727, 6741, 6755, 6769, 6783, 6797, 6811, 6825, 6839, 6853, 6867, 6881, 6895, 6909, 6923, 6937, 6951, 6965, 6979, 6993, 8001, 8015, 8029, 8043, 8057, 8071, 8085, 8099, 8113, 8127, 8141, 8155, 8169, 8183, 8197, 8211, 8225, 8239, 8253, 8267, 8281, 8295, 8309, 8323, 8337, 8351, 8365, 8379, 8393, 8407, 8421, 8435, 8449, 8463, 8477, 8491, 8505, 8519, 8533, 8547, 8561, 8575, 8589, 8603, 8617, 8631, 8645, 8659, 8673, 8687, 8701, 8715, 8729, 8743, 8757, 8771, 8785, 8799, 8813, 8827, 8841, 8855, 8869, 8883, 8897, 8911, 8925, 8939, 8953, 8967, 8981, 8995]\n","Há 285 números satisfazendo as condições.\n"]}]},{"cell_type":"markdown","source":["**Ex 39:** Faça uma função que receba como entrada um número inteiro na base 10 e retorne uma lista contendo sua representação em binário (cada elemento da lista é um bit 0 ou 1)."],"metadata":{"id":"DLTrgXD3HV3U"}},{"cell_type":"code","source":["def decimal_binario(n):\n"," binario = []\n"," while n != 0:\n"," quociente = n // 2\n"," resto = n % 2\n"," binario.append(resto)\n"," n = quociente\n"," return binario[::-1]\n","\n","# Início do script\n","n = int(input('Entre com um número inteiro: '))\n","b = decimal_binario(n)\n","print('O número %d em binário é: ' %n)\n","print(b)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"tOXeCPcKHYWW","executionInfo":{"status":"ok","timestamp":1664368891121,"user_tz":180,"elapsed":4976,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"1e464091-a3b4-473b-edda-74ef41e21179"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Entre com um número inteiro: 53\n","O número 53 em binário é: \n","[1, 1, 0, 1, 0, 1]\n"]}]},{"cell_type":"markdown","source":["**Ex 40:** Dada a seguinte lista de 10 elementos L = [-8, -29, 100, 2, -2, 40, 23, -8, -7, 77] faça funções que recebam L como entrada e retorne:\n","\n","a) o menor número da lista \n","\n","b) o maior número da lista\n","\n","c) a média de todos os elementos da lista\n","\n","d) a lista inversa\n","\n","e) o desvio padrão dos elementos da lista\n","\n","$$d = \\sqrt{\\frac{1}{n}\\sum_{i=1}^{n}(x_i - \\overline x)^2}$$\tonde $\\overline x$ é a média e n é o tamanho da lista.\n","\n","O script a seguir mostra a solução em Python."],"metadata":{"id":"JEckeBHBHkFx"}},{"cell_type":"code","source":["import math\n","\n","def minimo(L):\n"," menor = L[0]\n"," for x in L:\n"," if x < menor:\n"," menor = x\n"," return menor\n","\n","def maximo(L):\n"," maior = L[0]\n"," for x in L:\n"," if x > maior:\n"," maior = x \n"," return maior\n","\n","def media(L):\n"," soma=0\n"," for x in L:\n"," soma = soma + x\n"," media = soma/len(L)\n"," return media\n","\n","def desvio_padrao(L):\n"," m = media(L)\n"," soma = 0\n"," for x in L:\n"," soma = soma + (x - m)**2\n"," desvio = math.sqrt(soma/len(L))\n"," return desvio\n","\n","def inverte(L):\n"," return L[::-1]\n","\n","# Início do script\n","L = [-8, -29, 100, 2, -2, 40, 23, -8, -7, 77]\n","print('Mínimo: %d' %minimo(L))\n","print('Máximo: %d' %maximo(L))\n","print('Média: %f' %media(L))\n","print('Desvio padrão: %f' %desvio_padrao(L))\n","print('Inverso:', inverte(L))"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"H4zLL25GIPn5","executionInfo":{"status":"ok","timestamp":1664369111858,"user_tz":180,"elapsed":282,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"2fb1febd-c988-4a6d-f98b-8e1b8ce7e568"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Mínimo: -29\n","Máximo: 100\n","Média: 18.800000\n","Desvio padrão: 39.432981\n","Inverso: [77, -7, -8, 23, 40, -2, 2, 100, -29, -8]\n"]}]},{"cell_type":"markdown","source":["**Filter, Map e Reduce**\n","\n","As funções filter, map e reduce são ferramentas muito poderosas para se trabalhar com variáveis compostas como listas. A ideia de todas essas funções consiste em combinar listas com funções Lambda. Iremos iniciar com a descrição da função filter. Como o próprio nome diz, a função filter atua filtrando os elementos de uma lista. O exemplo a seguir filtra uma lista mantendo apenas os números pares."],"metadata":{"id":"y_gDlz9eJCZ0"}},{"cell_type":"code","source":["L = list(range(20))\n","print(L)\n","# Filtra lista (retorna apenas números pares)\n","pares = list(filter(lambda x: x % 2 == 0, L))\n","# Filtra lista (retorna apenas números ímpares)\n","impares = list(filter(lambda x: x % 2 == 1, L))\n","print(pares)\n","print(impares)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"QnSQNTdJKNcw","executionInfo":{"status":"ok","timestamp":1664369780253,"user_tz":180,"elapsed":352,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"fdec617b-728a-4f39-98c7-ff35251b083e"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]\n","[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]\n","[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]\n"]}]},{"cell_type":"markdown","source":["O exemplo a seguir filtra uma lista pelos números positivos e negativos."],"metadata":{"id":"AsOb5IxwK-U1"}},{"cell_type":"code","source":["L = [-8, -29, 100, 2, -2, 40, 23, -8, -7, 77, 41, -12]\n","print(L)\n","# Filtra lista (retorna negativos)\n","negativos = list(filter(lambda x: x < 0, L))\n","# Filtra lista (retorna positivos)\n","positivos = list(filter(lambda x: x >= 0, L))\n","print(negativos)\n","print(positivos)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"uxci0iRZLHEA","executionInfo":{"status":"ok","timestamp":1664370001239,"user_tz":180,"elapsed":353,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"6c8d01bd-e595-4861-dd33-ba721866b3d3"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["[-8, -29, 100, 2, -2, 40, 23, -8, -7, 77, 41, -12]\n","[-8, -29, -2, -8, -7, -12]\n","[100, 2, 40, 23, 77, 41]\n"]}]},{"cell_type":"markdown","source":["E se desejarmos substituir todos os valores negativos por zero? Note que nesse caso a ideia seria aplicar uma função a cada elemento da lista. Para isso temos a função map. Iremos iniciar com um exemplo simples. Desejamos elevar ao quadrado todos os elementos da lista."],"metadata":{"id":"ykfObEAyMQW8"}},{"cell_type":"code","source":["L = [1,2, 3, 4, 5]\n","print(L)\n","\n","# Map para aplicar função a cada elemento de L\n","quadrado = list(map(lambda x: x**2, L))\n","print(quadrado)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"qO82U31MMv7x","executionInfo":{"status":"ok","timestamp":1664370355370,"user_tz":180,"elapsed":264,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"bf23d24b-9f4f-4813-a2e9-e62236172727"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["[1, 2, 3, 4, 5]\n","[1, 4, 9, 16, 25]\n"]}]},{"cell_type":"markdown","source":["Então, no caso de zerar os elementos negativos podemos definir o seguinte comando."],"metadata":{"id":"g8NzCvjHNE4g"}},{"cell_type":"code","source":["L = [-8, -29, 100, 2, -2, 40, 23, -8, -7, 77, 41, -12]\n","print(L)\n","# Substitui negativos por zero\n","Lp = list(map(lambda x: x if x >= 0 else 0, L))\n","print(Lp)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"uHam3e1ONMZ2","executionInfo":{"status":"ok","timestamp":1664370477704,"user_tz":180,"elapsed":505,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"ab035855-28e4-4f99-a4cf-33f74301d73e"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["[-8, -29, 100, 2, -2, 40, 23, -8, -7, 77, 41, -12]\n","[0, 0, 100, 2, 0, 40, 23, 0, 0, 77, 41, 0]\n"]}]},{"cell_type":"markdown","source":["Agora, suponha que desejamos aplicar uma função que recebe toda a lista e retorna como saída apenas um único valor: por exemplo, desejamos calcular a soma de todos os elementos da lista. Para esses casos, existe a função reduce. A função reduce saiu do core da linguagem depois do lançamento do Python 3 e por essa razão, para utilizá-la devemos incluí-la a partir do pacote functools."],"metadata":{"id":"z5txczxXOOTI"}},{"cell_type":"code","source":["from functools import reduce\n","\n","L = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n","print(L)\n","# Retorna a soma dos elementos da lista L\n","soma = reduce((lambda x, y: x + y), L)\n","print(soma)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"nPOma_8-O483","executionInfo":{"status":"ok","timestamp":1664370914603,"user_tz":180,"elapsed":329,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"d026a775-de81-44b8-973f-2ca19c35eb58"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n","55\n"]}]},{"cell_type":"markdown","source":["E se desejássemos obter o maior elemento da lista? Simples, bastaria fazer o código a seguir."],"metadata":{"id":"Fj5HEwMcPNYr"}},{"cell_type":"code","source":["from numpy.random import random\n","from functools import reduce\n","\n","L = random(10)\n","print(L)\n","\n","# Retorna o maior elemento da lista L\n","maior = reduce((lambda x, y: x if x > y else y), L)\n","print('Maior: ', maior)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"djXm-5spPUWm","executionInfo":{"status":"ok","timestamp":1664371258458,"user_tz":180,"elapsed":270,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"af926385-2178-475c-fb71-dac6a255c185"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["[0.79462653 0.87703529 0.66859445 0.15559141 0.17322241 0.74405174\n"," 0.49589965 0.50509312 0.63365009 0.49829676]\n","Maior: 0.8770352889452716\n"]}]},{"cell_type":"markdown","source":["Note que com as funções filter, map e reduce evitamos a utilização de estruturas de repetição (loops), o que em Python é benéfico pois torna a execução dos scripts mais rápidas. Em Python, o que mais consome tempo de processamento são os loops criados com comandos while e for.\n","\n","**Strings**\n","\n","Strings são tipos de dados definidos como uma sequência de caracteres. Assemelham-se muito com listas, porém não é possível adicionar novos elementos ao conjunto (não posso fazer append, nem ordenar, nem inserir ou remover elemento). Por outro lado, há uma série de funções que strings possuem mas listas não. Como exemplo, podemos citar upper e lower para mudar os caracteres para maiúsculo ou minúsculo. Mas de longe a função mais conhecida e importante que apenas strings possuem é split (quebra em pedaços baseado num separador e monta uma lista). Como o próprio nome diz, a função split() recebe uma string como entrada e a quebra em diversos pedaços, retornando uma lista em que cada elemento é um pedaço da string original. Isso tudo de acordo com um caracter separador passado como parâmetro (caracteres típicos de separação são : ; , . - _). Se nenhum caracter especial for passado como parâmetro, assume-se que devemos quebrar a string nos espaços em branco. Por exemplo:"],"metadata":{"id":"kuLpOGHfQkx3"}},{"cell_type":"code","source":["digitos = '0,1,2,3,4,5,6,7,8' \n","print(digitos)\n","lista_digitos = digitos.split(',') \n","print(lista_digitos)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"fUWpiIdmZeI9","executionInfo":{"status":"ok","timestamp":1664373673823,"user_tz":180,"elapsed":394,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"0d3e7eaa-acc7-43b9-da13-4ade9c92b1f4"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["0,1,2,3,4,5,6,7,8\n","['0', '1', '2', '3', '4', '5', '6', '7', '8']\n"]}]},{"cell_type":"markdown","source":["O processo inverso, ou seja, pegar um lista de pedaços e juntar numa única string é feito com a função join(). O que essa função join faz nada mais é que pegar uma lista de strings e gerar uma única string."],"metadata":{"id":"tIUg_38WZwnN"}},{"cell_type":"code","source":["numeros = ''.join(lista_digitos) # une sem caracter de separação\n","numeros = ','.join(lista_digitos) # une com , separando elementos\n","print(numeros)\n","numeros = '-'.join(lista_digitos) # une com - separando elementos\n","numeros = ':'.join(lista_digitos) # une com : separando elementos"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"hWAPgbRtaAKK","executionInfo":{"status":"ok","timestamp":1664373813263,"user_tz":180,"elapsed":288,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"4ea5352d-54f9-4713-a642-8f5dc9b41ee8"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["0,1,2,3,4,5,6,7,8\n"]}]},{"cell_type":"markdown","source":["Na prática o que essa função faz é equivalente ao seguinte código:"],"metadata":{"id":"Xjs4-6TAaSVV"}},{"cell_type":"code","source":["lista = ['a','b','c','d','e','f'] \n","print(lista)\n","g = '' \n","for x in lista: \n"," g = g + x\t# concatena caracteres\n","print(g)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"R3UKYRA2aUqo","executionInfo":{"status":"ok","timestamp":1664373855712,"user_tz":180,"elapsed":389,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"2e3e38ed-51db-45ac-8505-43590ad4c859"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["['a', 'b', 'c', 'd', 'e', 'f']\n","abcdef\n"]}]},{"cell_type":"markdown","source":["**Ex 41:** Saber quantas palavras distintas existe em uma frase é uma tarefa que pode ser bastante complicada em determinadas linguagens de programação. Em Python, isso pode ser feito facilmente. Veja o exemplo a seguir."],"metadata":{"id":"T27oBV0w8wwr"}},{"cell_type":"code","source":["import string\n","\n","def lista_palavras(frase):\n"," frase = frase.lower() # tudo em minúscula\n"," # remove pontuação\n"," for c in string.punctuation:\n"," frase = frase.replace(c, '')\n"," # quebra string em lista de palavras\n"," lista = frase.split()\n"," palavras = []\n"," for x in lista:\n"," if x not in palavras:\n"," palavras.append(x)\n"," \n"," return palavras\n","\n","# Início do script\n","sentenca = 'If you have an apple and I have an apple and we exchange these apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas.'\n","print(sentenca)\n","print()\n","\n","L = lista_palavras(sentenca)\n","print('Há %d palavras distintas na sentença!' %len(L))\n","print(L)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"zSILhPyN81f6","executionInfo":{"status":"ok","timestamp":1664382897027,"user_tz":180,"elapsed":265,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"73c1c300-5a88-40cd-ae85-619ea8b1fa79"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["If you have an apple and I have an apple and we exchange these apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas.\n","\n","Há 22 palavras distintas na sentença!\n","['if', 'you', 'have', 'an', 'apple', 'and', 'i', 'we', 'exchange', 'these', 'apples', 'then', 'will', 'still', 'each', 'one', 'but', 'idea', 'ideas', 'of', 'us', 'two']\n"]}]},{"cell_type":"markdown","source":["**Ex 42:** Implemente uma função que recebe uma frase como entrada (string) e retorne quantas vogais ela possui, independente se maiúscula ou minúscula."],"metadata":{"id":"NqzEqvZV8-1p"}},{"cell_type":"code","source":["from unicodedata import normalize\n","\n","def conta_vogais(palavra):\n"," # letras minúsculas\n"," p = palavra.lower()\n"," # remove acentos, til, cedilhas\n"," p = normalize('NFKD', p).encode('ascii', 'ignore').decode('ascii')\n"," vogais = 0\n"," for letra in p:\n"," if letra in 'aeiou':\n"," vogais = vogais + 1\n"," return vogais\n","\n","palavra = input('Entre com uma palavra: ')\n","n = conta_vogais(palavra)\n","print('Há %d vogais na palavra %s' %(n, palavra))\n"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"OEpvGPxJ9Ee1","executionInfo":{"status":"ok","timestamp":1664382957524,"user_tz":180,"elapsed":8630,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"446a2b24-ffa8-45d9-bf43-31f5ca15da48"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Entre com uma palavra: Alexandre\n","Há 4 vogais na palavra Alexandre\n"]}]},{"cell_type":"markdown","source":["**Ex 43:** Implemente uma função que receba 2 palavras como entrada (strings) e retorne se elas são palíndromas, ou seja, se uma é o inverso da outra."],"metadata":{"id":"QY0iYUBr9LRg"}},{"cell_type":"code","source":["def palindroma(p1):\n"," palavra = p1.lower()\n"," if palavra == palavra[::-1]:\n"," return True\n"," else:\n"," return False\n","\n","print(palindroma('arara'))\n","print(palindroma('ovo'))\n","print(palindroma('carro'))"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"5izhgvFq9NYN","executionInfo":{"status":"ok","timestamp":1664383065784,"user_tz":180,"elapsed":544,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"9b5c7c68-422f-4803-ca94-1208776d6958"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["True\n","True\n","False\n"]}]},{"cell_type":"markdown","source":["**Ex 44:** Um histograma é a representação gráfica da distribuição de frequências de uma variável. Trata-se de uma ferramenta visual muito importante para visualizar a distribuição dos valores observados Faça um programa que simule n jogadas de um dado não viciado. Armazene o resultado numa lista e gere um histograma dos valores observados. Encontre a moda, isto é o valor que mais vezes aconteceu nas jogadas."],"metadata":{"id":"ZI8XX9cr9lqU"}},{"cell_type":"code","source":["import numpy as np\n","\n","# joga um dado n vezes\n","def joga_dados(n):\n"," # Gera números aleatórios inteiros de 1 a 6\n"," jogadas = np.random.randint(1, 7, n)\n"," return jogadas\n","\n","# constrói um histograma (distribuição de frequências)\n","def histograma(dados):\n"," h = 6*[0] # cria uma lista com 6 zeros\n"," for x in dados:\n"," h[x-1] = h[x-1] + 1\t# incrementa posição do histograma\n"," return h\n","\n","# Calcula a moda (número que mais aparece)\n","def moda(hist):\n"," maximo = hist[0]\n"," modas = []\n"," # Acha o máximo\n"," for x in hist:\n"," if x > maximo:\n"," maximo = x\n"," # Marca as posições em que o máximo aparece\n"," for i in range(len(hist)):\n"," if hist[i] == maximo:\n"," modas.append(i+1) # pois começa em zero\n"," \n"," return modas\n","\n","# Início do script\n","n = int(input('Quantas vezes você quer jogar o dado? '))\n","resultados = joga_dados(n)\n","hist = histograma(resultados)\n","print('Histograma: ', hist)\n","print('Modas: ', moda(hist))"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"ZTPUWBxc9pJv","executionInfo":{"status":"ok","timestamp":1664383154722,"user_tz":180,"elapsed":4593,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"e28da029-a334-497b-be7c-dd29b9472101"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Quantas vezes você quer jogar o dado? 100\n","Histograma: [18, 15, 13, 20, 16, 18]\n","Modas: [4]\n"]}]},{"cell_type":"markdown","source":["**Ex 45:** Implemente uma função que gere uma aposta válida da Mega Sena. A função deve gerar uma lista contendo 6 números aleatórios entre 1 e 60. Note que não deve haver repetição."],"metadata":{"id":"VtzvdVPA99yl"}},{"cell_type":"code","source":["import numpy as np\n","\n","def mega_sena():\n"," numeros = [] \n"," while len(numeros) < 6:\n"," r = np.random.randint(1, 61)\n"," if r not in numeros:\n"," numeros.append(r)\n"," numeros.sort()\n"," \n"," return numeros \n","\n","print(mega_sena())"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"DIWHwFcw-AgC","executionInfo":{"status":"ok","timestamp":1664383361054,"user_tz":180,"elapsed":518,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"016a5e7b-241f-4c3e-aa1c-26eb2d03b90a"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["[12, 19, 22, 30, 44, 57]\n"]}]},{"cell_type":"markdown","source":["**Ex 46:** A série $1^1 + 2^2 + 3^3 + 4^4 + … + 10^10 = 10405071317$. Faça um programa que retorne os últimos 10 dígitos de $1^1 + 2^2 + 3^3 + 4^4 + … + 1000^{1000}$."],"metadata":{"id":"kdT873X5-voB"}},{"cell_type":"code","source":["lista = list(range(1, 1001)) \t\t# cria lista de 1 a 1000\n","potencias = [x**x for x in lista] \t# cria lista com x elevado a x\n","soma = sum(potencias) \t# soma todos elementos da lista\n","digitos = str(soma)\t\t\t\t# converte resultado para string\n","print(digitos[len(digitos)-10:])\t\t# imprime os 10 últimos caracteres"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"HOSQ4Rea-_Pk","executionInfo":{"status":"ok","timestamp":1664383460391,"user_tz":180,"elapsed":353,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"624fc2ff-8ddc-4440-e9a6-046a8620e858"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["9110846700\n"]}]},{"cell_type":"markdown","source":["O site Project Euler (https://projecteuler.net/archives) contém uma série de problemas matemáticos desafiadores que podem ser resolvidos através da programação de computadores. O exercício anterior é um deles. O exercício a seguir é o problema 14 da lista do Project Euler.\n","\n","**Ex 47:** A maior sequencia de Collatz\n","Esse é um dos problemas matemáticos mais misteriosos do mundo, principalmente porque não existem provas formais da sua solução. Suponha que seja escolhido um número inteiro qualquer n. A sequencia iterativa a seguir é definida para qualquer n positivo:\n","\n","n → n/2 , \tse n é par\n","\n","n → 3n + 1, \tse n é ímpar\n","\n","Por exemplo, usando o número 13 como entrada, iremos produzir a seguinte sequencia:\n","\n","13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1\n","\n","O fato intrigante é que para todo n, cedo ou tarde a sequencia atinge o número 1 (essa é a conjectura de Collatz). A pergunta é: qual é o número n até 1 milhão, que produz a maior sequencia, isto é, que demora mais para atingir o número 1. Sugestão: armazene a sequencia de cada número numa lista e retorne como saída a maior delas."],"metadata":{"id":"UKy09G4W_GJx"}},{"cell_type":"code","source":["import time\n","\n","def collatz(n):\n"," sequencia = [n]\n"," while n > 1:\n"," if n % 2 == 0:\n"," n = n//2\n"," else:\n"," n = 3*n+1\n"," sequencia.append(n)\n"," \n"," return sequencia\n","\n","# Testa as sequencias com todos valores de 1 a 1000000 \n","def maior_seq():\n"," inicio = time.time()\n"," maior = 1\n"," lista = []\n"," for i in range(1, 1000000):\n"," L = collatz(i)\n"," if len(L) > maior:\n"," maior = len(L)\n"," lista = L\n"," print(lista)\n"," print()\n"," print('Tamanho: %d' %maior)\n"," print()\n"," fim = time.time()\n"," print('Tempo: %f' %(fim - inicio))\n","\n","\n","maior_seq()"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"waYlSAkk_Ls5","executionInfo":{"status":"ok","timestamp":1664383771811,"user_tz":180,"elapsed":27782,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"6dc97e29-1f70-4b63-b6e4-60d5658fc26c"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["[837799, 2513398, 1256699, 3770098, 1885049, 5655148, 2827574, 1413787, 4241362, 2120681, 6362044, 3181022, 1590511, 4771534, 2385767, 7157302, 3578651, 10735954, 5367977, 16103932, 8051966, 4025983, 12077950, 6038975, 18116926, 9058463, 27175390, 13587695, 40763086, 20381543, 61144630, 30572315, 91716946, 45858473, 137575420, 68787710, 34393855, 103181566, 51590783, 154772350, 77386175, 232158526, 116079263, 348237790, 174118895, 522356686, 261178343, 783535030, 391767515, 1175302546, 587651273, 1762953820, 881476910, 440738455, 1322215366, 661107683, 1983323050, 991661525, 2974984576, 1487492288, 743746144, 371873072, 185936536, 92968268, 46484134, 23242067, 69726202, 34863101, 104589304, 52294652, 26147326, 13073663, 39220990, 19610495, 58831486, 29415743, 88247230, 44123615, 132370846, 66185423, 198556270, 99278135, 297834406, 148917203, 446751610, 223375805, 670127416, 335063708, 167531854, 83765927, 251297782, 125648891, 376946674, 188473337, 565420012, 282710006, 141355003, 424065010, 212032505, 636097516, 318048758, 159024379, 477073138, 238536569, 715609708, 357804854, 178902427, 536707282, 268353641, 805060924, 402530462, 201265231, 603795694, 301897847, 905693542, 452846771, 1358540314, 679270157, 2037810472, 1018905236, 509452618, 254726309, 764178928, 382089464, 191044732, 95522366, 47761183, 143283550, 71641775, 214925326, 107462663, 322387990, 161193995, 483581986, 241790993, 725372980, 362686490, 181343245, 544029736, 272014868, 136007434, 68003717, 204011152, 102005576, 51002788, 25501394, 12750697, 38252092, 19126046, 9563023, 28689070, 14344535, 43033606, 21516803, 64550410, 32275205, 96825616, 48412808, 24206404, 12103202, 6051601, 18154804, 9077402, 4538701, 13616104, 6808052, 3404026, 1702013, 5106040, 2553020, 1276510, 638255, 1914766, 957383, 2872150, 1436075, 4308226, 2154113, 6462340, 3231170, 1615585, 4846756, 2423378, 1211689, 3635068, 1817534, 908767, 2726302, 1363151, 4089454, 2044727, 6134182, 3067091, 9201274, 4600637, 13801912, 6900956, 3450478, 1725239, 5175718, 2587859, 7763578, 3881789, 11645368, 5822684, 2911342, 1455671, 4367014, 2183507, 6550522, 3275261, 9825784, 4912892, 2456446, 1228223, 3684670, 1842335, 5527006, 2763503, 8290510, 4145255, 12435766, 6217883, 18653650, 9326825, 27980476, 13990238, 6995119, 20985358, 10492679, 31478038, 15739019, 47217058, 23608529, 70825588, 35412794, 17706397, 53119192, 26559596, 13279798, 6639899, 19919698, 9959849, 29879548, 14939774, 7469887, 22409662, 11204831, 33614494, 16807247, 50421742, 25210871, 75632614, 37816307, 113448922, 56724461, 170173384, 85086692, 42543346, 21271673, 63815020, 31907510, 15953755, 47861266, 23930633, 71791900, 35895950, 17947975, 53843926, 26921963, 80765890, 40382945, 121148836, 60574418, 30287209, 90861628, 45430814, 22715407, 68146222, 34073111, 102219334, 51109667, 153329002, 76664501, 229993504, 114996752, 57498376, 28749188, 14374594, 7187297, 21561892, 10780946, 5390473, 16171420, 8085710, 4042855, 12128566, 6064283, 18192850, 9096425, 27289276, 13644638, 6822319, 20466958, 10233479, 30700438, 15350219, 46050658, 23025329, 69075988, 34537994, 17268997, 51806992, 25903496, 12951748, 6475874, 3237937, 9713812, 4856906, 2428453, 7285360, 3642680, 1821340, 910670, 455335, 1366006, 683003, 2049010, 1024505, 3073516, 1536758, 768379, 2305138, 1152569, 3457708, 1728854, 864427, 2593282, 1296641, 3889924, 1944962, 972481, 2917444, 1458722, 729361, 2188084, 1094042, 547021, 1641064, 820532, 410266, 205133, 615400, 307700, 153850, 76925, 230776, 115388, 57694, 28847, 86542, 43271, 129814, 64907, 194722, 97361, 292084, 146042, 73021, 219064, 109532, 54766, 27383, 82150, 41075, 123226, 61613, 184840, 92420, 46210, 23105, 69316, 34658, 17329, 51988, 25994, 12997, 38992, 19496, 9748, 4874, 2437, 7312, 3656, 1828, 914, 457, 1372, 686, 343, 1030, 515, 1546, 773, 2320, 1160, 580, 290, 145, 436, 218, 109, 328, 164, 82, 41, 124, 62, 31, 94, 47, 142, 71, 214, 107, 322, 161, 484, 242, 121, 364, 182, 91, 274, 137, 412, 206, 103, 310, 155, 466, 233, 700, 350, 175, 526, 263, 790, 395, 1186, 593, 1780, 890, 445, 1336, 668, 334, 167, 502, 251, 754, 377, 1132, 566, 283, 850, 425, 1276, 638, 319, 958, 479, 1438, 719, 2158, 1079, 3238, 1619, 4858, 2429, 7288, 3644, 1822, 911, 2734, 1367, 4102, 2051, 6154, 3077, 9232, 4616, 2308, 1154, 577, 1732, 866, 433, 1300, 650, 325, 976, 488, 244, 122, 61, 184, 92, 46, 23, 70, 35, 106, 53, 160, 80, 40, 20, 10, 5, 16, 8, 4, 2, 1]\n","\n","Tamanho: 525\n","\n","Tempo: 27.410883\n"]}]},{"cell_type":"markdown","source":["**Ex 48:** Leia uma lista de n posições com elementos maiores ou iguais a zero e o compacte, ou seja, leve os elementos nulos para o final do vetor. Dessa forma todos os “zeros” devem ficar para as posições finais do vetor.\n","\n","Entrada: \t1 0 2 3 6 0 9 4 0 13 29\n","\n","Saída: \t\t1 2 3 6 9 4 13 29 0 0 0\n","\n","Dica: Crie uma lista vazia e percorra a lista original adicionando um número x apenas se ele for maior que zero. Ao final complete com zeros (o número de zeros a ser adicionado deve ser a diferença entre o tamanho da lista maior e o tamanho da lista menor)."],"metadata":{"id":"NwYtak9RCYsE"}},{"cell_type":"code","source":["# função para compactar a lista L\n","def compacta(L):\n"," lista = []\n"," for x in L:\n"," if x > 0:\n"," lista.append(x)\n"," n = len(L)\n"," m = len(lista)\n"," zeros = (n - m)*[0]\n"," lista = lista + zeros\n"," \n"," return lista\n","\n","L = [1, 0, 2, 3, 6, 0, 9, 4, 0, 13, 29]\n","print(L)\n","print(compacta(L))"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"n9czC1Q8P8dI","executionInfo":{"status":"ok","timestamp":1664387967000,"user_tz":180,"elapsed":294,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"b008c5ed-b252-4370-e372-d6c52358627b"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["[1, 0, 2, 3, 6, 0, 9, 4, 0, 13, 29]\n","[1, 2, 3, 6, 9, 4, 13, 29, 0, 0, 0]\n"]}]},{"cell_type":"markdown","source":["**Ex 49:** Dada uma lista L de inteiros positivos, encontre o comprimento da maior sublista tal que a soma de todos os seus elementos seja igual a k.\n","\n","Exemplo: Para L = [1, 3, 3, 5, 1, 4, 7, 2, 2, 2, 1, 8] e k = 6, existem várias subsequencias que somam 6, por exemplo, as subsequencias [3, 3], [5, 1] e [2, 2, 2]. O programa deve retornar o comprimento da maior delas, ou seja, 3.\n"],"metadata":{"id":"9EbSZjrmQTJz"}},{"cell_type":"code","source":["def max_sequence(L, k):\n"," sequencia = []\n"," max_len = -1 # retorna -1 se não há subsequencia que soma k\n","\n"," for i in L:\n"," sequencia.append(i)\n","\n"," while sum(sequencia) > k: \n"," sequencia = sequencia[1:]\n","\n"," if sum(sequencia) == k:\n"," max_len = max(max_len, len(sequencia))\n","\n"," return max_len\n","\n","L = [1, 3, 3, 5, 1, 4, 7, 2, 2, 2, 1, 8]\n","max_sequence(L, 6)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"wW87VoG1QdsW","executionInfo":{"status":"ok","timestamp":1664388098377,"user_tz":180,"elapsed":281,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"988c03e6-429a-4f44-a16c-032c8f809a58"},"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["3"]},"metadata":{},"execution_count":50}]},{"cell_type":"markdown","source":["**Vetores**\n","\n","Em Python, listas são objetos extremamente genéricos, podendo ser utilizados em uma gama de aplicações. Entretanto, o pacote Numpy (Numerical Python) oferece a definição de um tipo de dados específico para representar vetores: são os chamados arrays. Em resumo, um array é praticamente uma lista de números reais (floats), mas com algumas adicionais que facilitam cálculos matemáticos. A principal diferença é que numpy arrays são variáveis compostas homogêneas, ou seja, todos os elementos são do mesmo tipo de dados (inteiro ou real). Um exemplo é o seguinte: suponha que você tenha uma lista em que cada elemento representa o gasto em reais de uma compra efetuada pelo seu cartão. \n","\n"],"metadata":{"id":"kyoXdTyyRXGZ"}},{"cell_type":"code","source":["L = [13.5, 8.0, 5.99, 27.30, 199.99, 57.21]\n","print(L)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"6ulhVYhxRrBY","executionInfo":{"status":"ok","timestamp":1664388468068,"user_tz":180,"elapsed":270,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"79d1f9ef-88e7-4c94-e62a-00fcd70a850c"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["[13.5, 8.0, 5.99, 27.3, 199.99, 57.21]\n"]}]},{"cell_type":"markdown","source":["Você deseja dividir cada um dos valores pelo gasto total, para descobrir a porcentagem referente a cada compra. Como você tem uma lista, você deve fazer o seguinte:"],"metadata":{"id":"qou9toF8RtpE"}},{"cell_type":"code","source":["lista = []\n","for i in range(len(L)):\n","\tlista.append(L[i]/sum(L))\n","print(lista)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"FWAkvXVgRwvz","executionInfo":{"status":"ok","timestamp":1664388472229,"user_tz":180,"elapsed":460,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"fa6912db-6d8b-4f53-f977-6d5e450411e3"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["[0.04327061764800154, 0.025641847495112023, 0.019199333311965126, 0.08750280457706978, 0.6410141350684317, 0.18337126189941985]\n"]}]},{"cell_type":"markdown","source":["Ou seja, não é permitido fazer \n","\n","lista = L/sum(L) → ERRO (X)\n","\n","Mas se os dados tiverem sido armazenados num vetor, é possível fazer diretamente o comando acima:"],"metadata":{"id":"bjyBSEWmSOUa"}},{"cell_type":"code","source":["import numpy as np\n","\n","# criando um vetor (as duas maneiras são equivalentes)\n","v = np.array([13.5, 8.0, 5.99, 27.30, 199.99, 57.21])\n","v = v/sum(v)\n","print(v)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"2stvCeY1STvt","executionInfo":{"status":"ok","timestamp":1664388544223,"user_tz":180,"elapsed":300,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"97e186db-4f1d-429b-d76c-d48835a902ac"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["[0.04327062 0.02564185 0.01919933 0.0875028 0.64101414 0.18337126]\n"]}]},{"cell_type":"markdown","source":["Algumas funções importantes que todo objeto vetor possui, supondo que nosso vetor chama-se v:\n","\n","v.max() - retorna o maior elemento do vetor\n","\n","v.min() - retorna o menor elemento do vetor\n","\n","v.argmax() - retorna o índice do maior elemento do vetor\n","\n","v.argmin() - retorna o índice do menor elemento do vetor\n","\n","v.sum() - retorna a soma dos elementos do vetor\n","\n","v.mean() - retorna a média dos elementos do vetor\n","\n","v.prod() - retorna o produto dos elementos do vetor\n","\n","v.T – retorna o vetor transposto\n","\n","v.clip(a, b) – o que é menor que a vira a e o que é maior que b vira b\n","\n","v.shape() - retorna as dimensões do vetor/matriz\n","\n","Ou seja, para cálculos númericos com vetores e matrizes, a biblioteca numpy é uma ferramenta que nos auxilia muito.\n","\n","Para a referência completa das funções veja os links:\n","\n","https://docs.scipy.org/doc/numpy-dev/user/quickstart.html\n","\n","https://docs.scipy.org/doc/numpy/reference/arrays.ndarray.html#array-methods"],"metadata":{"id":"kPRN68FBSelV"}},{"cell_type":"markdown","source":["Link para o ambiente Google Colab: https://colab.research.google.com/drive/1WdMYuvhf57rW4N8UuSJbm_VY8Tegxv_j?usp=sharing\n","\n","“As pessoas mais felizes, não tem as melhores coisas... Elas sabem fazer o melhor das oportunidades que aparecem em seus caminhos... Pense nisso! O que você tem, todo mundo pode ter, mas o que você é... Ninguém pode ser...” (Clarice Lispector)"],"metadata":{"id":"PM7P_5q1YDtu"}}]} -------------------------------------------------------------------------------- /PA1_Aula08.ipynb: -------------------------------------------------------------------------------- 1 | {"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"provenance":[],"collapsed_sections":[],"mount_file_id":"1krAF44S_vMl0_llCAblchLrkDtwlF3tA","authorship_tag":"ABX9TyODLyuYq32C4LTVRm6fcVgf"},"kernelspec":{"name":"python3","display_name":"Python 3"},"language_info":{"name":"python"}},"cells":[{"cell_type":"markdown","source":["##**Programação e Algoritmos I**\n","\n","Prof Alexandre Levada\n","\n","###**Arquivos**\n","\n","Até o presente momento, todas as informações processadas pelos nossos scripts Python são voláteis, uma vez que permanecem na memória RAM até o encerramento do programa. Quando o programa encerra sua execução, todas as variáveis alocadas na memória são permanentemente deletadas. A pergunta que surge é: como fazemos para conseguir manter os dados, ou seja, armazená-los em um dispositivo de memória persistente. É aí que entra o conceito de arquivo (file). Ao escrever dados em arquivos, podemos acessar essas informações mesmo depois que a execução do programa tiver encerrado. Há basicamente dois tipos de arquivos para armazenamento de dados:\n","\n","1. Arquivos binários: nesse caso, toda informação gravada no arquivo está codificada em binário, ou seja, em 0’s e 1’s. Dessa forma, para ler o conteúdo do arquivo é preciso decodificar os dados.\n","\n","2. Arquivos texto: nesse caso, toda informação gravada no arquivo será codificada como caracteres, ou seja, letras e números. Assim. A visualização do seu conteúdo pode ser feita utilizando qualquer editor de texto comum.\n","\n","**Abrindo um arquivo**\n","\n","Antes de ler ou escrever dados em um arquivo, é preciso primeiramente abri-lo. Em Python, o comando para isso é o open()\n","\n","file = open(nome_do_arquivo, modo_de_acesso) \n","\n","em que nome_do_arquivo é uma string que armazenará o nome do arquivo no sistema operacional e modo_de_acesso é um string que especifica qual o tipo do arquivo e se desejamos ler ou escrever nele. A tabela a seguir resume dos modos de acessos.\n","\n","![Tabela_Arquivo.png](data:image/png;base64,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)\n"],"metadata":{"id":"yLO1BQqCzfd-"}},{"cell_type":"markdown","source":["**Arquivos binários**\n","\n","O script a seguir ilustra como escrever variáveis em um arquivo binário."],"metadata":{"id":"dv42ouFbCJiH"}},{"cell_type":"code","source":["# Abre arquivo para escrita em binário\n","f = open('binario.bin', 'wb')\n","# Cria um vetor de 5 elementos\n","L = [1, 2, 3, 4, 5]\n","M = [6, 7, 8]\n","# Converte o vetor para bytes (codificação para arquivo binário)\n","dados = bytearray(L)\n","# Escreve no arquivo\n","f.write(dados)\n","dados = bytearray(M)\n","f.write(dados)\n","# Fecha arquivo\n","f.close()"],"metadata":{"id":"SlhVgmIZCL4K"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["Agora, podemos ler o conteúdo do arquivo binario.bin para recuperar a variável L."],"metadata":{"id":"gCPW1yFyCRz6"}},{"cell_type":"code","execution_count":null,"metadata":{"id":"6_dxhHaizde6","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1664401112622,"user_tz":180,"elapsed":304,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"48ef4f0f-b333-4aa1-a029-641c5fa4fd82"},"outputs":[{"output_type":"stream","name":"stdout","text":["[1, 2, 3, 4, 5]\n","[6, 7, 8]\n"]}],"source":["# Abre arquivo para leitura\n","f = open('binario.bin', 'rb')\n","\n","# Lê primeira variáve (primeiros 5 bytes)\n","# Cada inteiro é 1 byte\n","dados = f.read(5)\n","# Converte para lista\n","L = list(dados)\n","# Imprime conteúdo\n","print(L)\n","\n","# Lê segunda variável (próximos 3 bytes)\n","dados = f.read(3)\n","# Converte para lista\n","M = list(dados)\n","# Imprime conteúdo\n","print(M)\n","\n","# Fecha arquivo\n","f.close()"]},{"cell_type":"markdown","source":["Para salvar vetores e matrizes, recomenda-se utilizar a função savez do pacote numpy."],"metadata":{"id":"NpVjJJ3qCbzM"}},{"cell_type":"code","source":["import numpy as np\n","\n","A = np.random.random((5, 5))\n","B = np.random.randint(1, 10, (7, 7))\n","\n","np.savez('numpy.npz', A=A, B=B)"],"metadata":{"id":"dvewp2TZCenk"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["Para recuperar vetores e matrizes de um arquivo, há a função load do pacote numpy."],"metadata":{"id":"IOA6Tr8aChoM"}},{"cell_type":"code","source":["import numpy as np\n","\n","dados = np.load('numpy.npz')\n","\n","A = dados['A']\n","B = dados['B']\n","\n","print(A)\n","print(B)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"I9_3R21xCkFt","executionInfo":{"status":"ok","timestamp":1664401167090,"user_tz":180,"elapsed":321,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"be414151-990a-4766-ab3c-23f8a6547593"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["[[0.71640043 0.87876011 0.9673868 0.47241315 0.31287265]\n"," [0.15345802 0.15820933 0.15166292 0.62407988 0.02077651]\n"," [0.5697471 0.34589978 0.35191372 0.48277075 0.20484939]\n"," [0.3665801 0.72401314 0.54989511 0.06451211 0.23416892]\n"," [0.19305227 0.83634046 0.91576327 0.06585186 0.29555106]]\n","[[8 7 7 8 7 5 4]\n"," [1 3 3 3 3 6 5]\n"," [1 8 3 7 7 9 7]\n"," [3 4 3 7 2 7 9]\n"," [7 3 7 3 5 8 2]\n"," [8 6 5 7 9 5 8]\n"," [3 4 5 6 8 6 6]]\n"]}]},{"cell_type":"markdown","source":["Note que ao utilizar as funções do pacote numpy não é necessário abrir e fechar o arquivo em questão de maneira explícita. Tudo isso já é gerenciado internamente pelos comandos savez e load.\n","\n","**Arquivos texto**\n","\n","Diferentemente dos arquivos binários, os arquivos textos são compostos por caracteres e strings. Sendo assim, para nós humanos é bem mais natural do que o formato binário. \n","\n","**Escrita em arquivo texto**\n","\n","Basicamente, para escrever em um arquivo texto, utilizamos o comando write, passando como parâmetro uma string. "],"metadata":{"id":"BKLOaU3vCobe"}},{"cell_type":"code","source":["# Abre o arquivo\n","f = open(\"texto.txt\", 'w', encoding='utf-8')\n","# Escreve várias linhas no arquivo\n","f.write(\"Primeira linha de texto\\n\")\n","f.write(\"Segunda linha de texto\\n\\n\")\n","f.write(\"Arquivos textos são legais!\")\n","# Fechando o arquivo\n","f.close()"],"metadata":{"id":"AgBv9EpxD2FP"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["Também é possível escrever uma lista de strings no arquivo texto com o comando writelines."],"metadata":{"id":"Zi2bqYiOD5Vg"}},{"cell_type":"code","source":["# Escreve várias linhas de uma só vez\n","lista = ['Olá a todos, sejam bem-vindos!\\n',\\\n"," 'Esse é um exemplo de como escrever em arquivos texto\\n',\\\n"," 'utilizando o comando writelines()']\n","g = open('textfile.txt', 'w')\n","g.writelines(lista)\n","g.close()"],"metadata":{"id":"JD7sge3ED7im"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["Para salvar vetores e matrizes em arquivos texto, recomenda-se utilizar a função savetxt do pacote numpy."],"metadata":{"id":"wlnrBD2kQkmR"}},{"cell_type":"code","source":["import numpy as np\n","\n","# Gera matriz com números aleatórios\n","A = np.random.random((5, 5))\n","# Salva no arquivo texto usando 3 casas decimais\n","np.savetxt('testando.txt', A, fmt='%.3f')"],"metadata":{"id":"F7u1MjzdQnir"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["**Leitura de arquivo texto**\n","\n","Basicamente, a leitura de arquivos texto é realizada pela função read(). Se passarmos um argumento inteiro para a função, ela indica a quantidade de caracteres que serão lidos na sequência a partir do arquivo. Se não for passado parâmetro algum, a função lê todo conteúdo do arquivo texto em uma única string. Posteriormente, podemos utilizar o comando split() da string para separar em palavras. Alternativamente, o comando readline() realiza a leitura de exatamente uma linha do arquivo texto."],"metadata":{"id":"XavEwJSZQq7r"}},{"cell_type":"code","source":["# Abre arquivo\n","f = open('texto.txt', 'r')\n","# Lê uma linha do arquivo\n","linha = f.readline()\n","# Imprime linha na tela\n","print(linha)\n","# Lê 5 caracteres do arquivo\n","caracteres = f.read(5)\n","# Imprime na tela\n","print(caracteres)\n","# Fecha arquivo\n","f.close()"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"lHW16bjqQvx4","executionInfo":{"status":"ok","timestamp":1664404885537,"user_tz":180,"elapsed":306,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"66096bf1-2110-4587-cea4-85eb43c8b232"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Primeira linha de texto\n","\n","Segun\n"]}]},{"cell_type":"markdown","source":["É possível utilizar um loop para ler todas as linhas do arquivo texto sequencialmente."],"metadata":{"id":"tYoncM7dQ0Vm"}},{"cell_type":"code","source":["# Abre arquivo\n","f = open('texto.txt', 'r')\n","# Loop para ler todas as linhas do arquivo\n","for linha in f:\n"," print(linha)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"uDh2sKEUQ1lI","executionInfo":{"status":"ok","timestamp":1664404913456,"user_tz":180,"elapsed":402,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"af38db19-3cf0-4606-9b36-f068c812bd0b"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Primeira linha de texto\n","\n","Segunda linha de texto\n","\n","\n","\n","Arquivos textos são legais!\n"]}]},{"cell_type":"markdown","source":["A seguir veremos alguns exercícios sobre manipulação de arquivos.\n","\n","**Ex 56 (Curso Python para Zumbis):** Na pacata vila campestre de Numberville, todos os telefones tem 6 dígitos. A companhia telefônica estabelece as seguintes regras sobre os números:\n","\n","1. Não pode haver dois dígitos consecutivos idênticos, pois isso é chato;\n","2. A soma dos dígitos tem que ser par, porque isso é legal;\n","3. O último dígito não pode ser igual ao primeiro, porque isso dá azar;\n","\n","Dadas essas regras perfeitamente razoáveis, bem projetadas e maduras, quantos números de telefone na lista abaixo são válidos?\n","\n","213752 216732 221063 221545 225583 229133 230648 233222\n","236043 237330 239636 240138 242123 246224 249183 252936\n","254711 257200 257607 261424 263814 266794 268649 273050\n","275001 277606 278997 283331 287104 287953 289137 291591\n","292559 292946 295180 295566 297529 300400 304707 306931\n","310638 313595 318449 319021 322082 323796 326266 326880\n","327249 329914 334392 334575 336723 336734 338808 343269\n","346040 350113 353631 357154 361633 361891 364889 365746\n","365749 366426 369156 369444 369689 372896 374983 375223\n","379163 380712 385640 386777 388599 389450 390178 392943\n","394742 395921 398644 398832 401149 402219 405364 408088\n","412901 417683 422267 424767 426613 430474 433910 435054\n","440052 444630 447852 449116 453865 457631 461750 462985\n","463328 466458 469601 473108 476773 477956 481991 482422\n","486195 488359 489209 489388 491928 496569 496964 497901\n","500877 502386 502715 507617 512526 512827 513796 518232\n","521455 524277 528496 529345 531231 531766 535067 535183\n","536593 537360 539055 540582 543708 547492 550779 551595\n","556493 558807 559102 562050 564962 569677 570945 575447\n","579937 580112 580680 582458 583012 585395 586244 587393\n","590483 593112 593894 594293 597525 598184 600455 600953\n","601523 605761 608618 609198 610141 610536 612636 615233\n","618314 622752 626345 626632 628889 629457 629643 633673\n","637656 641136 644176 644973 647617 652218 657143 659902\n","662224 666265 668010 672480 672695 676868 677125 678315\n","\n","Obs: Copie e cole o conteúdo acima (números) num arquivo chamado numeros.txt"],"metadata":{"id":"ydNVcl4Yl4I9"}},{"cell_type":"code","source":["# Condição 1: não pode haver 2 dígitos iguais em sequencia\n","def condicao1(digitos):\n"," cond1 = True\n"," for i in range(len(digitos)-1):\n"," if (digitos[i] == digitos[i+1]):\n"," cond1 = False\n"," break\n"," return cond1\n","\n","# Condição 2: soma dos dígitos deve ser par\n","def condicao2(digitos):\n"," lista = list(digitos) # converte para lista\n"," soma = 0\n"," \n"," for x in lista:\n"," soma = soma + int(x) # converte para inteiro!\n"," if soma % 2 == 0:\n"," cond2 = True # soma é par\n"," else:\n"," cond2 = False # soma é ímpar\n"," \n"," return cond2\n","\n","# Condição 3: último dígito não pode ser igual ao primeiro\n","def condicao3(digitos):\n"," if digitos[0] != digitos[-1]:\n"," cond3 = True\n"," else:\n"," cond3 = False\n","\n"," return cond3\n","\n","# Início do script\n","# Abre arquivo para leitura\n","f = open('numeros.txt', 'r')\n","\n","# Lê dados do arquivo numa única string \n","conteudo = f.read()\n","\n","# Quebra string em lista (cada palavra vira um elemento da lista)\n","numeros = conteudo.split()\n","total = 0\n","# Percorre todos os elementos da lista\n","for num in numeros:\n","\n"," if (condicao1(num) and condicao2(num) and condicao3(num)):\n"," total = total + 1\n","\n","print('O total de números telefônicos válidos é %d' %total)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"0XRFf9TVmIWT","executionInfo":{"status":"ok","timestamp":1664411411173,"user_tz":180,"elapsed":350,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"e988ec34-c2ec-4bb3-b286-2e76b058ad0d"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["O total de números telefônicos válidos é 39\n"]}]},{"cell_type":"markdown","source":["**Ex 57:** Contar o número de ocorrências das palavras em um texto é uma tarefa muito importante na internet, uma vez que plataformas como o Google, o Twitter e o Facebook analisam milhares delas por segundo. Um exemplo são os Trending Topics to Twitter que registra os tópicos mais citados na rede. Esse problema visa ilustrar de forma básica como podemos construir um histograma de palavras que compõem um texto. Para isso, iremos utilizar uma cópia do famoso livro “Alice no país das maravilhas”, disponível gratuitamente em formato .txt da seguinte URL \n","https://www.gutenberg.org/files/11/11-0.txt\n","\n","a) Quantas vezes o nome Alice aparece no texto?\n","\n","b) Crie uma lista com todas as palavras iniciadas com a letra a e que tenha pelo menos 7 caracteres."],"metadata":{"id":"c57Af6uJpvnW"}},{"cell_type":"code","source":["import urllib.request\n","import string \n","\n","# Faz o download do livro em formato txt\n","urllib.request.urlretrieve('https://www.gutenberg.org/files/11/11-0.txt', 'alice.txt')\n","\n","arquivo = open('alice.txt', 'r') # abre arquivo para leitura\n","\n","texto = arquivo.read() # copia todo conteúdo do arquivo numa string \n","\n","texto = texto.lower() # converte string para letras minúsculas \n","\n","# Substitui caracteres de pontuação por espaços em branco \n","for c in string.punctuation: \n"," texto = texto.replace(c, ' ') \n","\n","# Converte string para uma lista de palavras (separa por espaços) \n","texto = texto.split() \n","\n","alice = 0\n","L = []\n","for palavra in texto:\n"," if palavra == 'alice':\n"," alice = alice + 1\n"," if palavra[0] == 'a' and len(palavra) > 6 and palavra not in L:\n"," L.append(palavra)\n","\n","# Fecha arquivo \n","arquivo.close() \n","\n","print('O nome Alice aparece %d vezes no texto' %alice)\n","print('Palavras iniciadas com a letra A e com ao menos 7 letras:')\n","print(L)\n","print(len(L))"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"-YD4s1gnp0aS","executionInfo":{"status":"ok","timestamp":1664411472708,"user_tz":180,"elapsed":649,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"8e126555-1a03-4041-87ef-1b983db5d3e6"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["O nome Alice aparece 385 vezes no texto\n","Palavras iniciadas com a letra A e com ao menos 7 letras:\n","['alice’s', 'adventures', 'anywhere', 'afterwards', 'actually', 'another', 'anything', 'antipathies', 'australia', 'altogether', 'against', 'anxiously', 'ashamed', 'animal’s', 'animals', 'assembled', 'argument', 'authority', 'accustomed', 'archbishop', 'advisable—’”', 'advisable', 'atheling', 'adjourn', 'adoption', 'audibly', 'acceptance', 'attending', 'angrily', 'addressing', 'answered', 'attempt', 'along—“catch', 'appeared', 'arranged', 'addressed', 'awfully', 'altered', 'annoyed', 'alternately', 'already', 'advantage', 'appearing', 'answers', 'accounts', 'alarmed', 'appearance', 'account', 'attends', 'appealed', 'arguments', 'anxious', 'affectionately', 'attended', 'absence', 'arithmetic—ambition', 'ancient', 'advance', 'askance—', 'adventures—beginning', 'accounting', 'arrived', 'accusation', 'attempts', 'applause', 'accidentally', 'accident', 'attempted', 'again—‘', 'associated', 'available', 'agreement', 'archive', 'attached', 'addition', 'appears', 'accessed', 'additional', 'alternate', 'applicable', 'address', 'accordance', 'alteration', 'additions', 'assistance', 'accessible', 'accepting', 'approach', 'accepted', 'addresses']\n","90\n"]}]},{"cell_type":"markdown","source":["**Ex 58:** Faça um programa que peça um número de 1 a 9 ao usuário e imprima a tabuada desse número em um arquivo texto."],"metadata":{"id":"R0NgQnlHsUDu"}},{"cell_type":"code","source":["# Abre arquivo\n","f = open('tabuada.txt', 'w')\n","\n","n = int(input('Você quer gerar a tabuada de que número? '))\n","\n","# Cabeçalho\n","s = 'Tabuada do ' + str(n) + '\\n'\n","f.write(s)\n","f.write('--------------\\n')\n","\n","for i in range(1, 11):\n"," x = i*n\n"," s = str(i) + ' x ' + str(n) + ' = ' + str(x) + '\\n'\n"," f.write(s)\n"," \n","f.close()"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"NJSuqWBqsWk3","executionInfo":{"status":"ok","timestamp":1664412133035,"user_tz":180,"elapsed":5260,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"7e372422-80b6-439d-d5d0-b9496a4107d6"},"execution_count":null,"outputs":[{"name":"stdout","output_type":"stream","text":["Você quer gerar a tabuada de que número? 7\n"]}]},{"cell_type":"markdown","source":["**Ex 59:** Dado o arquivo das notas de uma turma de Programação em Python conforme a seguir:\n","\n","Alberto\t8.5\n","\n","Alan\t\t6.5\n","\n","Alex\t\t7.0\n","\n","Augusto\t5.0\n","\n","Beatriz\t\t9.5\n","\n","Carla\t\t9.0\n","\n","Débora\t\t10.0\n","\n","Diego\t\t4.0\n","\n","Eduardo\t6.0\n","\n","Gabriela\t8.5\n","\n","Gustavo\t5.5\n","\n","João\t\t3.5\n","\n","Juliana\t\t7.0\n","\n","Lucas\t\t9.0\n","\n","Marcela\t7.0\n","\n","Marcos\t5.0\n","\n","Osvaldo\t4.5\n","\n","Olívia\t\t7.5\n","\n","Paula\t\t6.5\n","\n","Roberto\t10.0\n","\n","Sílvio\t\t5.5\n","\n","Tatiana\t\t8.0\n","\n","Tiago\t\t8.5\n","\n","Valter\t\t7.5\n","\n","Vanderlei\t3.0\n","\n","OBS: Copie e cole o conteúdo acima para um arquivo chamado notas.txt\n","Leia o arquivo, calcule a média e o desvio padrão das notas. Em seguida produza 3 arquivos de saída: aprovados.txt, recuperacao.txt e reprovados.txt com os nomes e as notas dos alunos nessas condições. Imprima na tela a média da turma, o desvio padrão, a nota mais baixa e a nota mais alta.\n","\n","Critério de avaliação:\n","\n","nota >= 6.0 – Aprovado\n","\n","5.0 <= nota < 6.0 – Recuperação\n","\n","nota < 5.0 - Reprovado"],"metadata":{"id":"IgD2d93OsjH2"}},{"cell_type":"code","source":["import math\n","\n","def media(L):\n"," soma = 0\n"," for x in L:\n"," soma = soma + x\n"," media = soma/len(L)\n"," return media\n","\n","def desvio(L):\n"," soma = 0\n"," for x in L:\n"," soma = soma + (x - media(L))**2\n"," desvio = math.sqrt(soma/len(L))\n"," return desvio\n","\n","def maximo(L):\n"," maior = L[0]\n"," for x in L:\n"," if x > maior:\n"," maior = x\n"," return maior\n","\n","def minimo(L):\n"," menor = L[0]\n"," for x in L:\n"," if x < menor:\n"," menor = x\n"," return menor\n","\n","# Abre arquivos\n","f = open('notas.txt', 'r')\n","aprovados = open('aprovados.txt', 'w')\n","recuperacao = open('recuperacao.txt', 'w')\n","reprovados = open('reprovados.txt', 'w')\n","# Lê as linhas\n","nomes = []\n","notas = []\n","for linha in f:\n"," L = linha.split()\n"," s = L[0]\n"," n = float(L[1])\n"," nomes.append(s)\n"," notas.append(n)\n"," if n >= 6.0:\n"," aprovados.write(linha)\n"," elif n >= 5.0 and n < 6.0:\n"," recuperacao.write(linha)\n"," elif n < 5.0:\n"," reprovados.write(linha)\n"," \n","# Imprime imformaçoes na tela\n","print('A média das notas é %.2f' %media(notas))\n","print('O desvio padrão das notas é %.2f' %desvio(notas))\n","print('A nota mais baixa da turma é %.2f' %minimo(notas))\n","print('A nota mais alta da turma é %.2f' %maximo(notas))\n"," \n","# Fecha os arquivos\n","f.close()\n","aprovados.close()\n","recuperacao.close()\n","reprovados.close()"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"llV2y-qLsyNd","executionInfo":{"status":"ok","timestamp":1664412289941,"user_tz":180,"elapsed":447,"user":{"displayName":"Alexandre Levada","userId":"02637985322644396645"}},"outputId":"28078199-870d-49fc-ccfe-70123dcf98e0"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["A média das notas é 6.80\n","O desvio padrão das notas é 1.89\n","A nota mais baixa da turma é 3.00\n","A nota mais alta da turma é 10.00\n"]}]},{"cell_type":"markdown","source":["Link para o ambiente Google Colab: https://colab.research.google.com/drive/1krAF44S_vMl0_llCAblchLrkDtwlF3tA?usp=sharing\n","\n","\"Enquanto o conhecimento custa o seu tempo no presente, a ignorância custa todo seu futuro.\" (Autor desconhecido)"],"metadata":{"id":"lE6o9trptLSJ"}}]} -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Programacao e Algoritmos 1 2 | 3 | Repositório para as aulas de Programação e Algoritmos I, disciplina ministrada pelo Departamento de Computação da UFSCar. 4 | 5 | ### Ementa 6 | 7 | Aula 01 - Fundamentos básicos de computação 8 | 9 | Aula 02 - Estruturas sequenciais 10 | 11 | Aula 03 - Estruturas de seleção (condicionais) 12 | 13 | Aula 04 - Estruturas de repetição (loops) 14 | 15 | Aula 05 - Modularização e funções 16 | 17 | Aula 06 - Variáveis compostas unidimensionais (listas, strings, vetores) 18 | 19 | Aula 07 - Variáveis compostas bidimensionais (matrizes) 20 | 21 | Aula 08 - Arquivos 22 | 23 | Aula 09 - Dicionários 24 | 25 | Aula 10 - Recursão 26 | 27 | Aula 11 - Recorrência logística 28 | 29 | Aula 12 - Autômatos celulares 30 | 31 | --------------------------------------------------------------------------------