Data da última actualização: 09 de Fevereiro de 2010

Introdução à Programação

Departamento de Ciência de Computadores, Faculdade de Ciências da Universidade do Porto
Armando Matos


Classificações dos alunos que compareceram ao exame final da época de recurso.
Nota 1. No caso de "melhoria" o sistema de informação Sigarra deverá considerar apenas a melhor das classificações.
Nota 2. Só poderá ser lançada a classificação se o nome do aluno existir na pauta.
Nota 3. Em "folhas P e TP" existe uma versão da segunda parte da prova de recurso com uma resolução.

Classificações dos alunos que compareceram ao exame final da primeira época e que constam na pauta do Sigarra. Deve confirmar o seu resultado na página oficial da UP. Se algum aluno pretender ver o seu exame, pode fazê-lo na 4ª feira, dia 3 de Fevereiro entre as 9:00 e as 11:00.

- Alunos sem frequencia à disciplina (não deve ser considerada a exclusão dos alunos com estatuto "TE" ou "DA"):

- A tabela de folhas P e TP contém também enunciados de exames (da época normal e da época de recurso) com resoluções.



----Objectivos e programa

----Avaliação ----Sumários das aulas teóricas ----Bibliografia
----Folhas P e TP ----Elementos de estudo ----Funcionamento das aulas ----Complementos
----Provas ----Classificações ----Docentes ----














































TOP

Objectivos

Pretende-se que o aluno


Programa previsto

  1. Introdução aos algoritmos e às linguagens de programação
    1. Linguagem máquina; assembler; linguagens de alto nível
    2. Compiladores e interpretadores
    3. Processos; sistemas operativos
    4. Lógica e linguagem
    5. Breve introdução ao Linux e ao Emacs. Uso do Emacs em modo Python
  2. Introdução à linguagem python
    1. O interpretador de comandos
    2. Variáveis e expressões. Atribuição
    3. Listas
    4. Módulos e sua importação
    5. Instruções "if", "while", "for" e "return"
    6. Definição de funções
    7. Recursão
    8. Tipos de dados: tipos elementares, listas e "tuplos"
    9. Classes e objectos
    10. Utilização de ficheiros
    11. Teste de programas
  3. Alguns algoritmos importantes (listam-se possíveis exemplos)
    1. Pesquisa sequencial
    2. Pesquisa binária
    3. Métodos elementares de ordenação
    4. "Merge" de 2 listas
    5. Alguns algoritmos numéricos como, por exemplo, algoritmos de determinação de raízes de equações quadráticas, método da bissecção para a determinação da raíz aproximada de uma equação não negativa, o eixo dos x-x, e 2 rectas y=a e y=b.
    6. Utilização de pseuso-aleatórios. Exemplos: experiências estatísticas, cálculo de integrais definidos.
    7. Implementação de um algoritmo de pesquisa de soluções (por exemplo, para um jogo)
    8. Referência à eficiência de alguns dos algoritmos (pesquisa, ordenação...) estudados
  4. Princípios da boa programação - algumas observações

TOP












































TOP

Avaliação
  1. Há uma prova prática (exercícios práticos de programação) com a valorização de 5 valores (em 20) nos dias 26 e 27 de Novembro.
  2. Alunos inscritos em 2009 (números mecanográficos começados com "c09"):
    A admissão a qualquer das épocas de exame final ("frequência") requer que o aluno:
    1. não exceda nas aulas práticas o número de faltas permitido por lei e
    2. tenha uma classificação não inferior a 1.8 valores (em 5) na prova prática referida.

    A valorização do exame é de 15 valores.

  3. Alunos com anos de inscrição anteriores a 2009 (números mecanográficos começados com "c08", "c07"...) e trabalhadores estudantes:
    estes alunos podem optar por faltar à prova prática.
    1. Se faltarem à prova, são admitidos a exame final, tendo este a valorização de 20 valores.
    2. Se comparecerem à prova, só são admitidos a (qualquer das épocas de) exame final se obtiverem uma classificação não inferior a 1.8 valores (em 5), tendo o exame a valorização de 15 valores.

TOP












































TOP

Funcionamento das aulas

Aulas práticas
Em princípio todas as semanas é fornecida uma folha de exercícios. O aluno deverá tentar resolver os exercícios da folha antes da aula prática respectiva.

Aulas teórico-práticas
Nas aulas teórico-práticas serão aprofundadas diversas questões abordadas nas aulas teóricas, propondo-se exercícios complementares; poderão ainda ser colocadas questões relacionadas com os problemas das folhas práticas e fornecidas folhas complementares de exercícios.

TOP












































TOP

Sumários das aulas teóricas

Aula 01

   A disciplina de Introdução à Programação: objectivos, programa,
   bibliografia, funcionamento das aulas.
   Evolução dos computadores ao longo da história.

Aula 02

   Evolução das linguagens de programação. A linguagem máquina, a
   linguagem "assembler". Paradigmas de programação.
   Sobre o python: constantes (int, float, bool...), variáveis
     expressões. Instruções: atribuição, 'while'; definição de
     funções: "instruções" 'def' e 'return'.

Aula 03

   Análise de um programa específico em linguagem python.
   Instruções da linguagem python: atribuição, condicionais,
   de ciclo ('while').
   Definição de funções ('def' e 'return')
   Expressões.

Aula 04

   Versão iterativa e recursiva de uma função.
   ^Ambito ('scope') das variáveis: variáveis locais. 
   Divisibilidade.
   Exemplos.

Aula 05

   Divisibilidade e primalidade. 
   Exemplos e exercícios diversos.

Aula 06

   As listas. Funções 'len', 'append', 'range'.
   A instrução 'for'.
   Exercícios de aplicação.

Aula 07

    Dígitos de um inteiro numa base de numeração.
    Conversão entre bases
    Diversos exemplos sobre listas

Aula 08

    "Strings".
    Caracteres e suas codificações. Funções "ord" e "chr".
    Alguns exercícios sobre "strings".

Aula 09

    "Tuplos"; operações com tuplos; comparação com "strings" e listas.
    Exemplos diversos de implementação de funções que processam "strings".

Aula 10

    Introdução às listas em compreensão.
    Uso em programas simples para contar o número de divisores
    e testar a primalidade.
    Introdução aos módulos "rand" e "turtle".

Aula 11

    Mais um exemplo de aplicação do módulo "turtle".
    Forma mais geral da instrução "for".
    Definição indutiva de listas de inteiros de profundidade
      arbitrária.
    Exemplos de programas: soma de todos os inteiros,
    profundidade máxima de um inteiro.

Aula 12

    Entrada de dados com "prompt"
    Operador de formatação "%".
    Formatação de dados. Exemplos.

Aula 13

    Números pseudo-aleatórios:
    Lançamento de n dados m vezes: estimativa da média.
    Cálculo aproximado de um integral definido.

Aula 14

    Pesquisa sequêncial. Eficiência em termos do 
    número de comparações.

Aula 15

    Pesquisa binária numa lista ordenada.
    Pesquisa sequêncial e binária: comparação da eficiência.

Aula 16

    - Determinação da raíz aproximada de uma equação f(x)=0
      pelo método das bissecções sucessivas.
    - Uso do módulo "turtle" para desenhar o gráfico de uma função
      arbitrária.

Aula 17

    Método de ordenação por selecção do mínimo".
    Determinação da eficiência do método com base no número 
     de comparações efectuadas.
    Notas sobre a correcção do algoritmo.

Aula 18

    Método de ordenação "quicksort": algoritmo recursivo 
      utilizando listas em compreensão.por selecção do mínimo".
    Determinação da eficiência do método com base no número 
     de comparações efectuadas no caso médio.

Aula 19

    Erros na programação: erros sintácticos, de execução e semanticos;
    Correcção de erros e técnicas de boa programação.
    Confirmando predicados no programa: a instrução 'asssert'. 
    Testes. O módulo 'doctest'.

Aula 20

    Contagem de frequências ('bit counting') aplicação a uma função
    para detecção de anagramas.
    Método de ordenação "bucket-sort". Eficiência, limitações e
    comparação com outros métodos.

Aula 21

    - Criar e inicializar listas.
    - Representação de pontos a 2 dimensões; função de rotação
      de um ponto.
    - Função que determina a tabela de verdade de uma função 
      proposicional dada.
    - Sufixos de strings.

Aula 22

    Representações e operações com conjuntos.
    Teste de associatividade de uma operação binária

Aula 23

   - Várias soluções do problema: determinar o número de ocorrências
     do máximo numa lista. Comparação das eficiências.
   - Determinação da raíz quadrada inteira utilizando um método
     análogo à pesquisa binária. A eficiência é O(log n)
   - Determinação do determinante de uma matriz quadrada através
     da sua triangulação.

Aula 24

   Fundamentos da utilização do módulo 'Tkinter'
   Aplicação à construção de um programa de vizualização
   (a preto e branco e a cores) de imagens bi-dimensionais. 
   Exemplo de processamento de imagens - redução de contraste.

TOP












































TOP

Elementos de estudo; notas das aulas teóricas

Ir para:


  1. Capítulos do livro recomendado, em especial: capítulos 2 a 11 de How to Think like a Computer Scientist





    TOP

  2. Slides de aulas teóricas, alguns apontamentos (em parte da autoria de Pedro Vasconcelos); '*' significa que ainda não está disponível.
    - A disciplina. Breve história dos computadores e sistemas de operação.
    - Linguagens de programação
    - Expressões, tipos, variáveis; atribuição
    - Instrução 'if'; definição de funções
    - Expressões booleanas. Recursão e iteração
    - Definições indutivas e recursão; factorial e combinações
    - Listas, strings. Instrução 'for'
    - Método das bissecções; transformação de programas
    - Caracteres e códigos. Operador % de formatação
    - "Strings"; processamento de "strings"
    - Listas e tuplos
    - Listas em compreensão
    - Introdução aos algoritmos de pesquisa (slides)
    Algoritmos elementares de ordenação (slides)
    Ficheiros e excepções As 'excepções' não foram dadas no ano 2009/2010.
    Detecção e correcção de erros, ver também o problema
    Operações com fracções
    Uso de números pseudo-aleatórios em programação
    Implementação de programas para: (i)obter endereços de email num ficheiro, (ii) jogar o jogo do "master mind"
    Módulos gráficos "turtle" e "Tkinter". Nota sobre o "Tkinter". Módulo "copy"; redução do contraste.
    Exemplo de uma imagem aleatória a cores. Imagem com o contraste reduzido. Encontra mais informação sobre o "Tkinter" no Capítulo 19 do livro
    Funções que testam as propriedades das operações binárias: associatividade, existência de elemento neutro...
    (ver também)
    Exercícios: simulação de acontecimentos com uso de números aleatórios, separação de uma 'string' em palavras







    TOP

  3. Aulas teóricas - inclui muitos exemplos e exercícios.

    Ir directamente para: 1 5 10 15 20 25 30 35 fim


    Incluímos, de uma forma esquemática e não revista, o seguinte:

    • Alguns problemas propostos e resolvidos nas aulas teóricas.
    • Alguns exemplos apresentados nas aulas teóricas
    • Alguns problemas e explicações adicionais

    Pode haver omissões ou repetições...(






    [prev] [top] [next]

  1. Variáveis, expressões, tipos, operadores...
        x=11
        type(x)
          --> int
        x=11.1
        type(x)
          --> float
        y="Ai Ai"
        type(y)
          --> str
        >>> y[1]
        'i'
        >>> y[0]
        'A'
    
        ---------------------------
    
        print x
    
        >>> x=5
        >>> z=2
        >>> x/z
        2
        >>> x=5.0
        >>> z=2
        >>> x/5
        1.0
        >>> x/z
        2.5
    
        "overloading" de operadores
    
        

    [prev] [top] [next]

  2. Funções. Importando módulos
        O que faz a seguinte função (o que calcula?)?
    
          def f(n):
            prod=1
            i=2
            while i<n:
              prod = prod*i
            return prod
    
    
    
        O que faz a seguinte função (o que calcula?)?
    
          def f(n):
            prod=1
            i=2
            while i<n:
              prod = prod*i
              i = i+1
            return prod
    
        >>> sin(1)
    
        NameError: name 'sin' is not defined
        >>> import math
        >>> math.sin(1)
        0.8414709848078965
        >>> sin(1)
        NameError: name 'sin' is not defined
        >>> 
        from math import sin
        >>> sin(1)
        0.8414709848078965
    
        -----------------------------
    
        precedência (parcial) dos operadores binários
    
          primeiro ** 
          depois   *  /  %
          depois   +  -
          depois   <  <=  !=  ==  >=  >
          depois   and 
          depois   or
    
        Na dúvida: use parêntesis!
     
        -------------------------------
        #------------------ Ãútima aula -----------------------------------
        def f(n):
            prod=1
            i=2
            while i<n:
                prod=prod*i
                i=i+1
            return prod
        
        i=1
        while i<=5:
            print i, f(i)
            i = i+1
        
        #  1*2*...*(i-1) =  (i-1)!   excepto se i=0
        
        
        # --------------------------------------------------------
        #  atribuição    <var> =  <expressão>
        #       exemplos sintaticamenre correctos
        #       exemplos sintaticamenre errados
        
        # --------------------------------------------------------
        #  if <condição>:
        #     .....
        #     .....
        #  <...continuação...>
        #
        #       exemplos sintaticamenre correcto
        #       exemplos sintaticamenre errado
        
        
        # --------------------------------------------------------
        #  if <condição>:
        #     .....
        #     .....
        #  else:
        #     .....
        #     .....
        #     .....
        #  <...>
        #
        #       exemplos sintaticamenre correcto
        #       exemplos sintaticamenre errado
        
        # --------------------------------------------------------
        #  if ... elif ... elif ... else
        
        # --------------------------------------------------------
        #  while <condição>:
        #     .....
        #     .....
        #  <...>
        #
        #       exemplos sintaticamenre correctos
        #       exemplos sintaticamenre errados
        
        
        # --------------------------------------------------------
        #  while condição>:
        #     .....
        #     .....
        #  <...>
        #
        #       exemplos sintaticamenre correctos
        #       exemplos sintaticamenre errados
        
        
        def jogo():
            print "Vamos jogar"
            n = input("Diz um número ")
            print n+1, ", ganhei!!!"
        
        #  if, while, 
        def jogo1():
            print "Vamos jogar"
            n = input("Diz um número ")
            if n<10:
                print n+1, ", ganhei!!!"
            else:
                print n-1, ", perdi!!!"
        
        def jogo2():
            print "Vamos jogar"
            while 2==2:
                n = input("Diz um número ")
                print n+1, ", ganhei!!!"
                print "Vamos jogar outra vez"
        
        #  Note: tipicamente as funcoes não são assim!
        #  Em princípio as funções devem ser "puras":
        #      - não contém print's nem input's
        #      - fornecem um resultado (com 'return')
        #      - nã têm efeitos laterais (como mudar vars...)
        
        
        # Escreva uma função f: R -> R
        #   x<1 ou x>2 -> 0
        #   senão      -> 1
        
        # Escreva uma função f: R -> R
        #   derivada(f,x)
        #   
        #   com lambda
        
        print (lambda x: x**2+1)(2)!
        
        def deriv(f):
          delta = 0.01
          return lambda x: (f(x+delta)-f(x-delta))/(2.0*delta)
    
        
        print "derivadas de x^2"
        x=0
        while x<=10:
            print x, deriv(g)(x)
            x = x+1
    
        

    [prev] [top] [next]

  3. Funções...
     Função que converte segundos -> horas, min, segundos
    
    def dhms(segs):
        s=segs%60
        mins=segs/60
        m=mins%60
        horas=mins/60
        h=horas%24
        d=horas/24
        return [d,h,m,s]
    
    
    Tornando um programa executável
    
    

    [prev] [top] [next]

  4. Factorial...
    Versão de uma função que calcula r! (factorial de r) com um ciclo
    
       def fact(r):
           p=1
           k=2
           while k<=r:
               p=p*k
               k=k+1
           return p
    
    Versão de uma função que calcula r! (factorial de r) sem ciclos
    
       def fact1(r):
           if r<=1:
               return 1
           return r*fact1(r-1)
    
    
    

    [prev] [top] [next]

  5. Divisibilidade...
    Divisibilidade de a por b,  a|b (a divide b)
      a%b==0  ou então  (a/b)*b==a
    
    ---------------------------------------------
    
    Escreva uma função "div" que testa se a divisível por b
    
      div: N*N -> Bool
    
      muito simples
    
        return a%b==0
    
     mais complicado:
    
        if a%b==0
          return True
        else
          return False
    
    #  Escreva uma função que determina os inteiros 
    #  até n com mais divisores
    
    #    1) Função 'maxndiv(n)' que determina o maior número 
    #    de divisores de x, com   1 <= x <= n, 
    
    #    2) (Programa)
    #       Percorre-se x de 1 a n e, sempre que ndiv(x) = maxndiv(n)
    #       imprime-se x
    
    #  Contagem dos divisoes, melhorias do programa:
    
    #  Exercício
    
    #    d*d>x  -> pára
    #    d*d==x -> conta 1 divisor
    #    d*d<x  -> conta 2 divisores
    
    
    # --------------------------------------------
    #    Dígitos...
    
    #    qual o o último dígito de n (inteiro positivo)?
    
    #      R: n % 10
    
    #    E o penútimo, supondo que n>=10?
    
    #      R: (n/10)# 10
    
    
    # --------------------------------------------
    #   Soma dos dígitos
    
    #    Escreva uma função "sdig(n)" que escreve a soma dos dígitos de um
    #    inteiro positivo n dado. 
    
    #    a) Escrever a função de forma iterativa 
    #       (envolverá um ciclo "while")
    
    #    b) Escrever a função de forma recursiva 
    #       (não envolve ciclos, mas uma chamada à própria função).
    
    # --------------------------------------------
    #    Dígitos `ào contrário''
    
    #    Escreva uma função "digs_inv(n)" que imprime, por ordem inversa, os
    #    dígitos de um inteiro positivo n dado. 
    
    # --------------------------------------------
    #    Escreva uma função "digsb(n,b)" que escreve, <por ordem>, os
    #    dígitos de um inteiro positivo n dado. A base de numeração é 
    #    b, 2<=b<=10.
    
    #    Usar um método recursivo:
    #      se n<b: escrever n
    #      senão:
    #        digsb(???,b)
    #        escrever n# b
    
    

    [prev] [top] [next]

  6. Número de divisores...
      Escreva uma função que calcula o número de divisores de a
      ndiv N -> N
    
      c=0
      para cada d, 1<=d<=a
        se a divisível por d:
           c=c+1
      return c
    
    

    [prev] [top] [next]

  7. Primalidade...
    Exercício:
       Escreva uma função que determina se a é primo
       primo   N -> Bool
       A função deve ser baseada na condição de primalidade
                      ndiv(a)==2
    
    Melhore a eficiência da função de teste de primalidade, usando
    a seguinte propriedade que deve demonstrar!
      se o inteiro positivo a tem um divisor d com 2<= d <a,
      então tem um divisor d' com 2 <= d' <= sqrt(a)
    
    

    [prev] [top] [next]

  8. Listas, instrução 'for'...
    #--------------------------------------------------------------------
    #   Soma dos dígitos
    
    #    Exercício: Escreva uma função "sdíg(n)" que escreve a soma dos
    #    dígitos de um inteiro positivo n dado. 
    
    #    a) Escrever a função de forma iterativa 
    #       (envolver so' ciclos "while")
    def sdig(n):
        s=0
        while n>0:
            s = s+n%10
            n=n/10
        return s
    
    #for i in range(100,120):
    #    print i, sdig(i)
    
    
    #    b) Escrever a função de forma recursiva 
    #       (nao envolve ciclos, mas uma chamada à propria função).
    
    def sdigr(n):
        if n<10:
            return n
        return n%10 + sdig(n/10)
    
    for i in range(100,120):
        print i, sdigr(i)
    
    # --------------------------------------------
    #    Dígitos `ào contrario''
    
    #    Exercício: Escreva uma função "digs_inv(n)" que imprime, 
    #    por ordem inversa, os dígitos de um inteiro positivo n dado. 
    
    
    # --------------------------------------------
    #    Exercício:
    #    Escreva uma função "digsb(n,b)" que escreve, <por ordem>, os
    #    dígitos da representação na base 'b' de um inteiro positivo 'n'
    #    dado . A base de numeração é 'b', 2<=b<=10.
    
    #    Usar um metodo recursivo:
    #      se n<b: escrever n
    #      senão:
    #        digsb(???,b)
    #        escrever n%b
    
    def digsb(n,b):
        if n>=b:
            digsb(n/b,b)
        print n%b,
        
    
    
    for i in range(10):
        print i,
        digsb(i,2)
        print
    
    #----------------------------------------------------------------------------
    #  Uma estrutura de informação "composta": a lista
    #----------------------------------------------------------
    #  lista: sequência de 0 ou mais expressões
    #         em particular, uma expressão pode ser uma lista
    #
    #  indexação      li[i]: elemento i da lista (comeca em 0)
    #  comprimento:   len(li)
    #  concatenação:  lista1 + lista2
    #  função append: li.append(e): elemento e no fim da lista
    #  multiplicação por inteiro
    #  função range(n)   -> [0,1,...,n-1]
    #         range(a,n) -> [a,a+1,...,n-1]
    #
    #  colocar elemento 'e' no fim da lista 'li': append(li,e)
    #----------------------------------------------------------
    #  instrução for:   for <var> in <lista>:
    #
    #  imprimir os inteiros 0, 1,..., 100 e seus quadrados
    #
    
    
    for i in range(101):
        print i,i**2
    
    
    
    
    
    #----------------------------------------------------
    #    Exercício:
    # função soma(n) que determina a soma 1+2+...+n
    def soma(n):
        s=0
        for i in range(1,n+1):
            s=s+i
        return s
    # Melhor solução: retornar a expressão dessa soma! Qual é?
    #----------------------------------------------------
    # Exercício:
    #   função dup(li) que recebe uma lista li e
    #   duplica todos os elementos
    def dup(li):
        r=[]
        for elem in li:
            r = r + [elem] + [elem]
        return r
    #----------------------------------------------------
    # Utilizaremos muitas vezes
    #   - instrução for
    #   - listas e indexação
    #   - + (concatenação de listas)
    #   - função range
    
    
    #----------------------------------------------------
    # Exercício:
    # Bem  ou mal?
    #      Se 'mal' porquê?
    #      Se 'bem', qual o valor?
    #---------------------------------------
    #   [2,[5,4],6][1][1]
    #---------------------------------------
    #   li = [2,[5,4],6][1][1]     for i in 10:
    #   li[2][1]                     print i
    #---------------------------------------
    #   range(3)+range(3)          len(range(3))
    #   len(3)                     li.append([])
    #   li.append(29)
    #---------------------------------------
    # Exercício: Como criar uma lista a com 100 0's: [0,0,...,0]?
    #---------------------------------------
    # Exercício: função quadrado(n) que retorna a lista
    #     [[0,  1,...,...n],     (linha 0)
    #      [n+1,n+2,...,2n],     (linha 1)
    #         .......
    #      [..........,n*n-1]]   (linha n-1)
    #   a) Usando só a instrução de ciclo 'for'
    #      (uma ou mais vezes!)
    #   a) Usando só a instrução de ciclo 'while'
    #      (uma ou mais vezes!)
    
    def quadrado(n):
        r=[]      # lista global a retornar
        a=0       # número actual a colocar
        for i in range(n):
            li=[] # lista linha a formar
            for j in range(n):
                li=li+[a]
                a = a+1
            r = r + li
        return r
    
    #---------------------------------------
    # Exercício: Mostre que se não existisse a instrução 'for'
    #  o 'python' não perdia potencialidades.
    #
    #  Nota. Na verdade, nem do 'while' precisamos. basta a
    #  recursividade.
    # Exercício: função soma(n) que determina a soma 1+2+...+n
    #  sem usar 'for' nem 'while'.
    # --------------------------------------------
    
    
    
    #--- Uma nota sobre a instrução 'for'
    li=[1,2,3]
    for i in li:
        li=[]
        print i
    print li
    
    
    
    

    [prev] [top] [next]

  9. Mais exercícios com listas...
    # coding: utf-8
    
    #------------------------------------------------------------
    #  Escrever uma função soma(n) que calcula a soma 1+2+...+n
    #    a) Usando um ciclo while
    #    b) Usando uma instrução 'for'
    #    c) Sem qualquer instrução de ciclo (nem 'for' nem 'while')
    #------------------------------------------------------------
    
    # a)
    def soma1(n):
        s=0
        i=1
        while i<=n:
            s = s + i
            i = i+1
        return s
    
    print "soma1(5)", soma1(5)
    
    # b)
    def soma2(n):
        s=0
        for i in range(1,n+1):
            s = s + i
        return s
    
    print "soma2(5)", soma2(5)
    
    # c)
    def soma3(n):
        if n<=0:
            return 0
        return n + soma3(n-1)
    
    print "soma3(5)", soma3(5)
    
    # c)
    def soma4(n):
        return n*(n+1)/2
    
    print "soma4(5)", soma4(5)
    
    #------------------------------------------------------------
    #  Escreva uma função arit(a,b) onde 'a' e 'b' são inteiros
    #  que calcula a lista [a,a+1,...,b]. Não pode usar a função
    #  'range', podendo manipular as listas apenas com 'append'  
    #  (e indexação)
    #  Exemplos: arit(5,9) -> [5,6,7,8,9]
    #            arit(5,4) -> 
    #------------------------------------------------------------
    
    def arit(a,b):
        r=[]     # a ser retornada pela função
        for i in range(a,b+1):
            r=r+[i]
        return r
    
    print arit(2,5)
    
    #------------------------------------------------------------
    #  Mostre que qualquer instrução 'for' pode ser substituída
    #  por uma instrução 'while'
    #  Relembra-se a forma da instrução 'for'
    #
    #     for <var> in <lista>:
    #         ...
    #         ...
    #     <continuação>
    #
    #  Solução
    #     n=len(lista)   # nova variável
    #     i=0            # nova variável
    #     while i<n:
    #         ...
    #         ...
    #         i=i+1
    #     <continuação>
    #------------------------------------------------------------
    
    #------------------------------------------------------------
    #  Escrever uma função listas(n) que a partir de n calcula uma
    #  lista [[...[]...]] em que o número de '[' é n.
    #  Exemplo: listas(3)-> [[[]]]
    #------------------------------------------------------------
    
    # assume-se n>=1
    def listas(n):
        if n==1:
            return []
        return [listas(n-1)]
    
    print
    print listas(3)
    
    #------------------------------------------------------------
    #  Escreva uma função base(n,b) que converte o inteiro n para a
    #  base 'b', ficando os dígitos (inteiros entre 0 e n-1)
    #  no resultado
    #  Exemplos:  base(123,10) -> [1,2,3]
    #             base(16,2)   -> [1,0,0,0,0
    #  tipo: int x int -> [int]
    #------------------------------------------------------------
    
    # assume-se n>0
    # Vamos retirando o último dígito a n, n%b
    # Esse dígito é colocado à cabeca de r
    def base(n,b):
        r=[]
        while n>0:
            dig = n%b
            r = [dig]+r
            n=n/b
        return r
    
    print
    for (n,b) in [(123,10),(15,2),(29,3)]:
        print n,b,base(n,b)
    
    #------------------------------------------------------------
    #  Escreva uma função valor(li,b) que a partir de uma lista 'li'
    #  e de uma base 'b', determina o inteiro cuja representação
    #  na base 'b' é a sequência de dígitos contida na lista li
    #  Exemplos:  base([1,5,9],10)      -> 159
    #             base([1,1,1,0,1],2)   ->  29
    #  tipo: [int] x int -> int
    #------------------------------------------------------------
    
    #  o valor retornado é obtido olhando para a lista da esquerda
    #  para a direita...
    #   li: [4,5,6], dig     s    de cada vez: s=s*b+dig
    #                 4      4
    #                 5     45
    #                 6    456
    
    def valor(li,b):
        s=0
        for dig in li:
            s= s*b+dig
        return s
    
    print
    for (li,b) in [([4,5,6],10), ([1,0,0,1],2), ([2,0,1],3)]:
        print li,b,valor(li,b)
    
    #------------------------------------------------------------
    #  Strings:  "..."  ou '...'
    #  Funções:  indexação, 
    #            len, 
    #            + (dá uma nova 'string'),
    #            in
    #            ord, 
    #            chr
    #  as strings são imutáveis
    #  Caracteres: strings com comprimento 1
    #  Códigos dos caracteres, ord e chr
    #------------------------------------------------------------
    

    [prev] [top] [next]

  10. Exemplos com "strings". Módulo gráfico "turtle"...
    #------------------------------------------------------------
    #  Strings:  "..."  ou '...'
    #  Funções: indexação, len, + (dá uma nova 'string'), 
    #           in ord, chr
    #  São imutáveis
    #  Caracteres: strings com comprimento 1
    #  Códigos dos caracteres, ord e chr
    #  
    #  Tuplos tu = (1,(2,3),[4,5])
    #  Iguais às listas, mas imutáveis!
    #  imutáveis em que sentido?
    #  tu[0]=2
    #  tu[2][1] = "ui"
    #
    #  Listas, strings, tuplos: 
    #      indexação, + (concatenação), len, in
    #  Listas: append, modificação (atribuição a elementos da lista)
    #  Strings: ord, chr
    #------------------------------------------------------------
    
    #------------------------------------------------------------
    #  Escreva uma funçao repete(s,n): repete s n vezes
    #  repete("abc",3) -> "abcabcabc"
    #    Escrever função sem usar *
    #------------------------------------------------------------
    def repete(s,n):
        r=""
        for i in range(n):
            r=r+s          # r = r+r
        return r
    
    print repete("abc",3)
    
    #  return s*n
    
    #------------------------------------------------------------
    #  Escreva uma função vogaisu(s) todas as vogais -> u
    #------------------------------------------------------------
    
    
    #------------------------------------------------------------
    #  mima(s)
    #    mima("Batatas!") -> "BATATAS!"
    #  Transforma as minúsculas em maiúsculas
    #  Use minu="abcdefghijklmnoprstuvwxyz"
    #      maiu="ABCDEFGHIJKLMNOPRSTUVWXYZ"
    #  e a função axiliar procura(c,s): (primeiro) índice ou -1
    #  Não pode importar módulos
    #------------------------------------------------------------
    
    def mima(s):
        minu="abcdefghijklmnoprstuvwxyz"
        maiu="ABCDEFGHIJKLMNOPRSTUVWXYZ"
        r=""
        for c in s:
            if c in minu:
                ind=localiza(c,minu)
                a = maiu[ind]
            else:        # tirando o else?
                a=c
            r=r+a
        return r
    
    def localiza(a,s):
        for i in range(len(s)):
            if a==s[i]:
                return i
        return -1
    
    print mima("Batatas!!")
    
    #------------------------------------------------------------
    #  Lista das letras
    #  
    #  
    #------------------------------------------------------------
    from string import *
    
    def letras(s):
        r=[]
        for x in letters:
            if x in s:
                r.append(x)
        return r
    
    print letras("As batatas ")
    
    #------------------------------------------------------------
    #  Substitui cada letra pela letra a seguir
    #    seguir("Aiz!") -> "Bja!"
    #  
    #------------------------------------------------------------
    
    def seguir(s):
        r=""
        minus = "abcdefghijklmnopqrstuvwxyz"
        maius = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        for c in s:
            if c in minus:          # c é minúscula?
                ind=ord(c)-ord("a") # posição de c na lista "minus"
                ind1 = (ind+1)%26   # posiçao seguinte
                cn = minus[ind1]    # a minúscula correspondente
            elif c in maius:        # c é minúscula?
                ind=ord(c)-ord("A") # ...
                ind1 = (ind+1)%26
                cn = maius[ind1]
            else:
                cn = c              # fica o mesmo caracter
            r = r+cn
        return r
    
    s = "Arroz ZIT!"
    print s, seguir(s)
    
    # Exercício: Usar uma função auxiliar
    #   procura(c,str) -> índice de "c" em "str", ou -1 se não existe
                
    
    #------------------------------------------------------------
    #  Lista ordenada das letras, usa lista de presenças
    #  Converte representação decimal para inteiro
    #     inteiro("1234") -> 1234; deve indicar erro se for caso disso...
    #  
    #------------------------------------------------------------
    def inteiro(s):
        digitos="0123456789"
        soma = 0
        for c in s:
            if c in digitos:
                v = ord(c)-ord("0")
                soma = soma*10 + v
            else:
                print "Formato de string errado"
                return
        return soma
    
    for s in ["123","99888","12a3"]:
        print s, inteiro(s)
    
    
    #------------------------------------------------------------
    #--- tuplos, troca de valores "for (a,b)..." BD alunos 
    #------------------------------------------------------------
    #    surpresas...
    #  a = [1,2,3,4,5]
    #  b=a
    #  a[3] = "batatas"
    # 
    #  Como copiar listas?
    
    #============================================================
    # Módulo turtle
    #  - seth(ang)
    #  - left(ang)
    #  - right(ang)
    #  - forward(comp)
    #  - backward(comp)
    #  - pendown()
    #  - penup()         size, color,...
    #  - speed(n)        1 a 10, 0 é o mais rápido
    
    #============================================================
    # Módulo random
    #  
    #  - rand(1,5): inteiro aleatório uniforme entre 1 e 5
    #
    
    #------------------------------------------------------------
    # Exercício: simule o passeio aleatório de uma pessoa
    #    (movimento browniano) durante n passos;
    #    Em cada passo, escolhe aleatoriamente uma das 4 direcções
    #    (E, N, W, ou S) e move-se nessa direcção o comprimento
    #    "comp".
    #    função a escrever; "def passeio(n,comp)"
    #------------------------------------------------------------
    
    
    from turtle import *
    from random import *
    from math import *
    radians()
    
    def passeio(n,comp):
        pendown()
        speed("fastest")
        for i in range(n):
            ang=randint(0,3)*(pi/2.0)
            seth(ang)
            forward(comp)
    
    passeio (100,10)
    
    
    

    [prev] [top] [next]

  11. Estrelas com o "turtle". Funções recursivas em listas de (listas de...) inteiros
    #------------------------------------------------------------
    # Exercício: desenhe uma estrela de n lados conforme se explica na aula...
    #    estrela(n,comp)
    #------------------------------------------------------------
    
    def estrela(n,comp):
        backward(comp/2.0)
        for i in range(n):
            forward(comp)
            right(180-180.0/n)
    
    estrela(5,100)
    
    #------------------------------------------------------------
    #  Outras formas da instrução for
    #    for <var> in <lista>:
    #      ....
    #
    #    for <var> in <string>:
    #      ....
    #
    #    (ou expressão com valor <lista> / <string>!)
    #    for [a,b] in ([1,2],[3,4],[4,4]):
    #      print (a+b)/2.0 
    
    for [a,b] in ([1,2],[3,4],[4,4]):
        print (a+b)/2.0 
    
    # lado esquerdo: lista ou tuplo de variáveis, ex (a,b)
    # lado direito:  lista de elementos da mesma forma, ex (..,..)
    #  
    #------------------------------------------------------------
    
    
    
    #------------------------------------------------------------
    #  Outro exercício com o turtle
    #  
    # Exercício: desenhe uma estrela de n lados conforme se explica na aula...
    #    estrela(n,comp)
    #------------------------------------------------------------
    
    #from turtle import *
    #from math import *
    
    #def estrela(n,comp):
    #    backward(comp/2.0)
    #    for i in range(n):
    #        forward(comp)
    #        right(180-180.0/n)
    #
    #estrela(5,100)
    
    
    #=================================================================
    #=================================================================
    #  teste de tipos
    #  "função" "tipe"  - teste com int, float, str, list,
    #       type((2,)) == tuple   type((2)) == tuple
    
    #---------------------------------------------
    #  Uma estrutura E pode ser
    #    - um inteiro
    #    - uma lista de 0 ou mais elementos do tipo E
    #  
    #  Exemplos:   0 
    #              [[]] 
    #              [[1], 4, [[1,6]], [[[]]] ]
    #  Problema: escrever uma função 
    #               soma(e) -> int       (onde "e" tem a forma E)
    #            que determina a soma de todos os inteiros na estrutura "e"
    
    
    def soma(e):
        if type(e)==int:
            return e
        s=0
        for a in e:
            s=s+soma(a)
        return s
    
    print
    print "--------------------------------"
    li = [[1], 4, [[1,6]], [[[]]] ]
    print li, soma(li)
    
    #-----------------------------------------------
    #  Exercício:
    #      Escreva a função profu(e) onde "e" é uma estrutura
    #      do tipo E, que calcula a profundidade máxima das listas em e
    #      listas em e.
    #      Exemplo:
    #          profu(5)            ->  0
    #          profu([])           ->  1
    #          profu([5,[[2]],3])  ->  3
    
    def profu(e):
        # caso base
        if type(e)==int:
            return 0
        # máxima prof elementos da lista...
        m=0
        for x in e:
            p=profu(x)
            if p>m:
                m=p
        return m+1
    
    print
    print "--------------------------------"
    for x in (5,[],[5,[[2]],3]):
        print x,profu(x)
    
    #-----------------------------------------------
    #  Exercício:
    #      Escreva a função copia(e) onde "e" é uma estrutura
    #      do tipo E, que fornece uma cópia da estrutura e.
    #  Exemplo:
    #    >>> a=[1,2,3]
    #    >>> b=copia(a)
    #    >>> a[1] = "uuu"
    #    >>> a
    #        [1,"uuu",3]
    #    >>> b
    #        [1,2,3]
    
    

    [prev] [top] [next]

  12. Saída formatada de dados
    #=================================================================
    #  Instruções de entrada de dados  (input())
    def teste():
        a = input()
        print a+1
        a = input("Diz um número: ")
        print a+1
    
    #----------------------------------------------------------
    #  Saída formatada de dados:
    #        formato     %  elementos    ->   string
    #        string     opr  tuplo       ->   string
    #        a=10
    #        s = "a=%4d" %  (a+1,)       -> "a=  11"
    #  ... tuplos com 1 elemento
    #  por vezes podem-se omitir os "(", ")" dos tuplos...
    
    
    # teste()
    
    from math import *
    
    def teste1():
        s = "ai%3dui" % (4,)
        print s
        x=1.1
        s = "x=%5.1f  log(x)=%10.6f" % (x,log(x))
        print s
        s = "x=%5.1f  log(x)=%-10.6f" % (x,log(x))
        print s
    
    teste1()
    
    #   Exercício: escreva uma função "logs(n)" que imprime
    #   a tabela dos logaritmos na base 2 dos inteiros 1, 2, ..., n
    #   Formato pretendido
    #
    #       x    log(x)
    #    --------------
    #       1    0.0000
    #       2    1.0000
    #    ----**********
    #    12345678901234
    
    print
    
    def logs(n):
        print "   x    log(x)"
        print "--------------"
        for x in range(1,n+1):
            log2x = log(x)/log(2)
            s = "%4d%10.4f" % (x,log2x)
            print s
    
    logs(10)
    
    
    #-------------------------------------------
    #   Exercício: escreva uma função 'codigos(m,n)' que imprime
    #   a tabela dos inteiros m, m+1, ..., n nas bases
    #      decimal, octal e hexadecimal
    #   bem como os caracteres com esses códigos. Tipicamente
    #   é 32 <= m<n <=127.
    #   Formato pretendido
    #  
    #    1234567890123456789
    #    --------------------
    #      33    41   21    !
    #      33    41   21    "
    #      33    41   21    #
    #     ...   ...  ...  ...
    
    print
    def codigos(m,n):
        for i in range(m,n+1):
               print "%4d%6o%5x%4s" % (i,i,i,chr(i))
    
    codigos(33,50)
    

    [prev] [top] [next]

  13. Aplicações dos números (pseudo) aleatórios; outros assuntos
    #   Exercício de códigos
    #   teste de minúscula
    #   teste de acentos?
    #   Valores de ("%d" % 3)*5   ("%d" % 3)+"ai"
    #   Formatado:  print <string>     (só uma <string>)
    #
    #   Programa com erros
    #
    #   Random:
    #     dado atirado n vezes: média, variância
    #     área de uma zona
    #
    #   Ordenação:
    #     importância, slides, 3 métodos (selecção, bs, qs)
    
    #-------------------------------------------
    #   Exercício: escreva uma função 'codigos(m,n)' que imprime
    #   a tabela dos inteiros m, m+1, ..., n nas bases
    #      decimal, octal e hexadecimal
    #   bem como os caracteres com esses códigos. Tipicamente
    #   é 32 <= m<n <=127.
    #   Formato pretendido
    #  
    #    1234567890123456789
    #    --------------------
    #      33    41   21    !
    #      33    41   21    "
    #      33    41   21    #
    #     ...   ...  ...  ...
    #----------------------------------------------------  
    #  Note que a instrução de impressão formatada é da forma
    #     print <string>
    #  onde <string> é uma expressão cujo valor é uma string
    #----------------------------------------------------  
    
    
    print
    def codigos(m,n):
        for i in range(m,n+1):
               print "%4d%6o%5x%4s" % (i,i,i,chr(i))
    
    codigos(33,50)
    
    
    #----------------------------------------------------
    #   Exercício: Letra minúscula?
    #   Escreva uma função minus(a) cujo parâmetro a
    #   é um caracter e que tem o resultado 
    #         True se a é uma letra minúscula
    #         False caso contrário.
    #   Deve haver uma só instrução (para além do "def")
    #   da forma 
    #      return <expr>
    #   A expressão <expr> deve ser tão curta quanto possível;
    #   pode supor que os códigos de "a", "b",... são
    #   consecutivos.
    #   Não pode usar o módulo string (letters,
    #   lowercase...)
    #----------------------------------------------------
    
    for a in "aABc23e":
        print a, ord(a)>=ord("a") and ord(a)<=ord("z")
    
    #----------------------------------------------------
    # Indique os valores e tipos de:
    #   ("%d" % 3)*5                 ________
    #   ("%2s %3d" % ("ui",3)) + "ai" _______
    #  len("%1000d" % 1)*1000
    #
    # Atribua a "a" uma expressão curta cujo valor é a lista
    # [[1,1,...,1], [3,3,...,3],..., [99,99,...,9] ]
    # tendo cada lista interna 10 elementos
    #
    #   a = ???
    #----------------------------------------------------
    a =  [[n]*10 for n in range(1,101,2)]
    
    
    #----------------------------------------------------
    # Aleatórios
    #   from random import *
    #   randint(a,b) -> aleatório uniforme em {a,a+1,...,b}
    #   random()     -> real aleatório em [0,1)
    #-------------------------------------------
    
    #-------------------------------------------
    # Exercício: escreva expressões aleatórias que correspondam a
    #   lançamento de um dado (resultado 1 ou 2 ou ... ou 6)
    #   lançamento de um par de dados (resultado 1 ou 2 ou ... ou 12)
    #-------------------------------------------
    from random import *
    
    print randint(1,6)
    print randint(1,6) + randint(1,6)
    
    #-------------------------------------------
    # Exercício
    #  Escreva uma função 
    #     dados(m,n)
    #  que "lança" m dados n vezes e determina a média dos
    #  valores obtidos; por exemplo, para
    #     dados(3,2)
    #  se os resultados foram: 11,4,6, (m=2, n=3) a média é 10.5
    #-------------------------------------------
    def dados(m,n):
        s=0.0
        for i in range(n):
            r = 0
            for d in range(m):
                r = r + randint(1,6)
            s = s+r
        return s/n
    
    
    #-------------------------------------------
    # Exercício
    # Determine a área aproximada entre
    #   - a recta vertical   x=0
    #   - a recta vertical   x=2
    #   - a recta horizontal x=0
    #   - o gráfico da função y=sin(x)  (x em radianos)
    #
    # Método: 
    #  c=0
    #  Fazer n vezes
    #     1) gerar um par: 
    #          x aleatório em [0,2], 
    #          y aleatório em [0,1] 
    #     2) se y<sin(x):
    #          c = c+1
    #  o resultado é (1*2)*(c/n)   (divisão "float")
    #
    #-------------------------------------------
    #  Generalize com a função area(f,x1,x2,ymax,n)
    #  onde se admite que 
    #     - x=x1, xy=x2: rectas verticais
    #     - f: função não negativa em [x1,x2]
    #     - ymax: majorante de f(x) em [x1,x2]
    #     - n: número de pares (x,y) gerados
    #-------------------------------------------
    
    from math import *
    def area(f,x1,x2,ymax,n):
        c=0.0
        for i in range(n):
            x = x1 + (x2-x1)*random()
            y = ymax*random()
            if y < sin(x):
                c=c+1
        return ymax*(x2-x1)*(c/n)
    
    
    #  http://docs.python.org/index.html
    

    [prev] [top] [next]

  14. Pesquisa sequencial e pesquisa binária; ordenação (texto longo...)
    #=====================================================================
    #  Pesquisa e ordenação
    #  Nas folhas P & TP:
    #       método de ordenação por selecção do mínimo
    #       método de ordenação "bubblesort"  (bolha")
    #  -------------------------------------------------------------------
    #  Pesquisa:
    #     Dados: x, lista v
    #     Resultado: determinar i tal que x==v[i]
    #                           ou -1 se x não está em v
    #  ---------
    #  Notação: v[a..b]: v[a,a+1,...,b]
    #           (se a>b é a lista vazia)
    #  
    #  Uma implementação da pesquisa (pesquisa sequencial)
    #    - x é comparado com v[0], v[1],... até ser x==v[i]
    #      para algum i<len(v)
    #    - se x não está em v[] é retornado -1
    #  
    #  Possíveis aplicações...:
    #  v: [("rui",(12,8,16,9)),("ana",(11,20)),("maria",())]
    #  determinar a média das classificações obtidas por "ana"
    #  
    #  
    
    print "--- procura sequencial -----"
    
    def procura(x,v):
        """pesquisa sequencial"""
        for i in range(len(v)):
            if x==v[i]:
                return i
        return -1
    
    a=[2,9,8,11,3,2,4]
    for x in [2,7,11,9,6]:
        print x, procura(x,a)
    
    
    
    def procura2(x,v):
        """pesquisa sequencial; x colocado no fim
           (conhecido por `método da sentinela` """
        n=len(v)
        v.append(x)
        i=0
        while x!=v[i]:
            i=i+1
        if i<n:
            return i
        return -1
    
    print
    a=[2,9,8,11,3,2,4]
    for x in [2,7,11,9,6]:
        print x, procura2(x,a)
    
     #--------------------------
     #   Pesquisa binária
     #   Se v[] está ordenado (suponhamos por ordem crescente)
     #   podemos procurar x muito mais rapidamente
     #   -----------
     #   v[a...b]
     #   determina-se m=(a+b)/2  (divisão inteira), é a<=m<=b
     #   se x==v[m]:  retorna m
     #   se x<v[m]:   retorna o resultado da procura em v[a..m-1]
     #   se x>v[m]:   retorna o resultado da procura em v[m+1..b]
     #   ------
     #   função pesquisab(x,v,a,b):
     #      if a>b:  # intervalo vazio
     #         return -1
     #      m=(a+b)/2
     #      if x==v[m]:
     #         return m
     #      elif x<v[m]:
     #         return procura(x,v,a,m-1)
     #      return procura(x,v,m+1,b)
     #   -------
     #
     #        a               m               b      x=11
     #       <-- --- --- --- --- --- --- --- -->
     #                        9
     #
     #                            a   m       b      x=11
     #       --- --- --- --- --- <-- --- --- -->
     #                                12
     # 
     #                          a=b=m                x=11
     #       --- --- --- --- --- <-> --- --- ---
     #                           10
     #
     #                            b   a              x=11
     #       --- --- --- --- --- --> <-- --- ---
     #                           10
     #       Intervalo vazio: único local onde x pode estar ==>
     #        x não está  ==> retorna -1
     #
     #   Mostrar que está correcto:
     #   Por indução em b-a+1 (comprimento do intervalo)
     #
     #      1) Termina sempre: b-a reduz-se sempre
     #         (nunca fica igual) e se nunca acontecer x==v[m]
     #         acaba por ser a>b e acaba (também) a execução
     #      2) Quando é chamada   pesquisab(x,v,a,b)
     #         - se x está em v[] (todo), está em v[a..b]
     #         Prova por indução em b-a+1 (tamanho do intervalo)
     #           - caso base: a>b (=b+1)
     #           - caso geral: 
     #               ou é calculado um valor correcto de m,
     #                  quando x==v[m] - resposta correcta
     #               ou b-a diminui de tamanho e usamos a hipótese indutiva
    
    
    def pesquisab(x,v,a,b):
        if a>b:  # intervalo vazio
           return -1
        m=(a+b)/2
        if x==v[m]:
           return m
        if x<v[m]:
           return pesquisab(x,v,a,m-1)
        return pesquisab(x,v,m+1,b)
    
    print
    a=[2,2,3,4,8,9,11]
    for x in [2,7,11,9,6]:
        print x, pesquisab(x,a,0,len(a)-1)
    
    
    def pesquisab2(x,v):
         """versão iterativa"""
         a=0
         b=len(v)-1
         while a<=b:
             m=(a+b)/2
             if x==v[m]:
                 return m
             if x<v[m]:
                 b=m-1
             else:
                 a=m+1
         return -1
    
    # teste:
     print
     a=[2,2,3,4,8,9,11]
     for x in [2,7,11,9,6]:
         print x, pesquisab2(x,a)
    
    #==================================================
    #   Ordenação
    #==================================================
    
    #------------------------------------------
    # Ordenar uma lista; na saída:
    #    mesmos elementos,
    #    mesma mutiplicidade
    #    por ordem
    # 
    # Métodos:
    #    muitos: bubble sort, selecção do mínimo, 
    #            heap sort, quicksort, merge sort...
    # 
    #    Ver: Knuth, The Art of Computer Programming
    #                Vol III: sorting and searching
    #------------------------------------------
    
    #------------------------------------------------
    #  Selecção do mínimo, v[0..n-1]
    #------------------------------------------------
    #    - determinar o menor dos v[0..n-1] trocar com v[0]
    #    - determinar o menor dos v[1..n-1] trocar com v[1]
    #    - ...
    #    - determinar o menor dos v[0..n-1] trocar com v[n-1]
    #
    #  Exemplo: [8,3,2,9,4]  -> [2,3,8,9,4]  -> [2,3,8,9,4]  -> 
    #            ---------         -------           -----
    #        -> [2,3,4,9,8]  ->  -> [2,3,4,8,9]
    #                  ---                   -
    
    def sm(v):
        n=len(v)
        for i in range(n-1):
            min=i
            for j in range(i+1,n):
                if v[j] < v[min]:    # (*)
                    min=j
            v[i],v[min] = v[min],v[i]
        return a
    
    print "---------- sm"
    a=[8,3,2,9,4]
    print a,sm(a)
    
    a=[2,1,2,1,2,1,1]
    print a,sm(a)
    
    #------------------------------------------------
    #  Quicksort
    #------------------------------------------------
    #  qs
    #  Fixar um índice, por exemplo v[0]
    #     dividir v em
    #       - l1 = lista dos menores que v[0]
    #       - l1 = lista dos menores que v[0]
    #       - [v[0]]
    #     Resultado: qs(l1)+[v[0]]+l2
    
    #--- funciona se todos distintos...
    def qs(v):
        if len(v)<=1:
            return v
        return qs([x for x in v if x<v[0]]) + [v[0]] +\     # (*)
               qs([x for x in v if x>v[0]])                 # (*)
    
    print "---------- qs"
    a=[8,3,2,9,4]
    print a,qs(a)
    
    a=[2,1,2,1,2,1,1]
    print a,qs(a)
    
    #--- funciona no caso geral
    def qs1(v):
        n=len(v)
        if len(v)<=1:
            return v
        return qs1([v[i] for i in range(1,n) if v[i]<=v[0]]) +\     # (*)
               [v[0]] +\
               qs1([v[i] for i in range(1,n) if v[i]>v[0]])         # (*)
    
    print "---------- qs1"
    a=[8,3,2,9,4]
    print a,qs1(a)
    
    a=[2,1,2,1,2,1,1]
    print a,qs1(a)
    
    #-----------------------------------
    # Agora um método muito eficiente só aplicável
    # em casos especiais:
    #   - todos os valores são inteiros distintos 
    #     compreendidos entre 0 e m-1 (m não muito grande)
    
    def bs(v):
        m=20 # tipicamente poderia ser m=1000 
        r=[]
        c=[0]*m    # c[i] vai ser 1 sse i existe em v
        for x in v:
            c[x]=1
        print c    # instrução a retirar!
        return [i for i in range(m) if c[i]==1]
    
    print "---------- bs"
    a=[8,3,2,9,4]
    print a,bs(a)
    
    a=[2,1,2,1,2,1,1]
    print a,bs(a)
    
    # Exercício: altere a implementação da função 'bs' 
    #    por forma a ordenar listas com elementos repetidos.
    #    Sugestão: use c[i] para contar o número de
    #    ocorrências de i em v;
    #    exemplo v=[2,1,2,1,2,1,1], c=[0,4,3,0,0,...]
    
    #------------------------------------------------
    # Eficiência
    #   Contar o número de comparações envolvendo elementos
    #   do vector a ordenar   linha (*)
    # 
    # Selecção do mínimo: n(n-1)/2
    # Quicksort: ~n*log(n) no caso médio
    #            ~n*n      no pior caso
    #------------------------------------------------
    
    
    
    
    

    [prev] [top] [next]

  15. Solução aproximada de f(x)=0: método da bissecção
    Escreva uma função "zero(a,b,erro)" tal que, dado:
       - um intervalo [a,b]  com a<b
       - um valor erro>0
       - uma função f (fixa) contínua em [a,b], com sinais contrários nos
         extremos do intervalo e com um só zero no intervalo,
    a função retorna x em [a,b] com f(x) aproximadamente igual a zero,
    isto é, f(x-erro) e f(x+erro) devem ter sinais contrários.
    
    Observações:
      - Pode assumir que nunca acontece (nunca vai calhar exactamente)
        f(x)=0.
    
      - Pode testar que os sinais de x e y são diferentes com a condição
        f(x)*f(y)<0.
    
      - O intervalo [a,b] deve ser sucessivamente partido a meio, até que
        b-a<erro. Haverá pois algures uma condição "while b-a >= erro".
        Quando se verificar b-a<erro, a solução aproximada com um erro (no
        eixo dos xx) não superior e erro, é a (ou b ou (a+b)/2).
    
     -----------------------------------------------------------
    
    Introduzir uma função no argumento de "zero", ficando pois a função 
    
           "zero(f,a,b,erro)".
    
    Método das bissecções sucessivas para calcular
    (aproximadamente) a raíz f(x)=0:
    
    def zero(f,a,b,erro):
        while b-a>=erro:
            x=(a+b)/2.0
            if f(x)*f(a)>0:
               # mesmo sinal de x e a -> fica [x,b]
                a=x    
            else:
               # mesmo sinal de x e b -> fica [a,x]
                b=x    
        return (a+b)/2.0  # 
    
    Nota. também poderia ser "return a" ou "return a" - a condição de
          erro ficava satisfeita
    
    Exercício:
    ----------
    Por hipótese, no início os sinais de a e b são diferentes,
    mas... se o metodo for aplicado aos casos seguintes o que acontece?
    
        a) Função constante igual a 1, a=0, b=10
    
        b) Função com mais que uma raíz 
    
    Exercício:
    ----------
    Implemente a função "zero" de forma recursiva; a implementação deve ser
    análoga à anterior, mas
    
      - não deve haver qualquer ciclo ("for" ou "while")
      - devem existir chamadas à própria função que se está a 
        definir (recursividade).
    

    [prev] [top] [next]

  16. Aleatórios e estimativas de probabilidades
          Vamos usar aleatórios para calcular a probabilidade (aproximada)
          de um acontecimento       
    
          Atira-se 5 vezes uma moeda ao ar; qual a probabilidade de sairem
          4 ou cinco "coroas"?
    
          a) Mais geralmente, escreva a função 
    
                coroas(n,c)
    
          que retorna | True se sairam c ou mais coroas
                      | False caso contrario
    
          b) Escreva a função 
    
                probab(n,c,exp) 
    
          que chama exp vezes "coroas(n,c)" e retorna a probabilidade
          (aproximada) de sairem c ou mais coroas
    
               (aproximadamente) 
             = (Num. de vezes em coroas(n,c)==True) / exp
    
           c) Calcule a probabilidade exacta do caso n=5, c=4 e
              compare com probab(5,4,10000)
    
              (6/32)
    

    [prev] [top] [next]

  17. Área debaixo da função
          Pretende-se calcular a área aproximada de uma região...
      
              h |...................
                |    /\    |
                |   /--\f(x)
                |  /----\  |  
                | /------\ |
                |/--------\
                -------------------------
                a          b            x
      
             At = área a tracejado (entre f(x) e o eixo xx)
             A  = área rectângulo = h(b-a)
      
             Gerando um ponto aleatório no rectangulo:
          
                  x = ...
                  y = ...
      
             n = num. pontos total
             s = num de pontos que satisfaz y < sin(x)
      
             At              s
             --  =  (aprox.) -
             A               n
      
             a) Escreva uma função 
      
                       area(f,a,b,h,n)
      
                onde -  f(x)>0 para a<=x<=b
                     - h e' um majorante de f(x) para a<=x<=b
      
    

    [prev] [top] [next]

  18. Erros. Instrução assert. Módulo doctest
    # 1) Esquecer de incrementar o i, ciclo infinito
    # 2) Confundir índices com valores
    
    def somapares(li):
        """ soma os elementos pares da lista de inteiros li"""
        s=0
        i=0
        while i<len(li):
            if i%2==0:
    #           print i,li[i]
    #           assert li[i]%2==0, "Elemento nao e' par!"
                s=s+li[i]
            i=i+1
        return s
    
    
    lista=[5,6,7,8]
    print lista, somapares(lista)
    
    #--------------
    
    def somapares1(li):
        """ soma os elementos pares da lista de inteiros li
        >>> [somapares1(a) for a in [[5,1,3],[2],[1,2,3,6]] ]
        [0, 2, 8]
        """
        s=0
        i=0
        while i<len(li):
            if i%2==0:
                print i,li[i]
                assert li[i]%2==0, "Elemento nao e' par!"
                s=s+li[i]
            i=i+1
        return s
    
    def _test(): 
        import doctest
        doctest.testmod()
    
    if __name__ == "__main__": _test()
    
    
    # lista=[5,6,7,8]
    # print lista, somapares(lista)
    

    [prev] [top] [next]

  19. Anagramas. "Bucket-sort"
    # Um anagrama de uma string s á uma string t que
    #    tem exactamente as mesmas letras com as mesmas multiplicidades
    # Exemplos
    #     s: "banana"  t: "anaban"  -> True
    #     s: "banana"  t: "anabab"  -> False
    #     s: "marcelo sousa" t: "salmão escuro"
    #     s: "anibal cavaco" t: "cabala nociva" 
    
    # Escreva ums função
    #     anagrama(s,t) que testa se t é um anagrama de s
    #     ("ser anagrama de" é uma relação R, S, T)
    #     O resultado é True ou False
    #     Apenas se consideram as letras minúsculas não acentuadas
    #     (ignoram-se espaços, sinais de pontuação, letras maíusculas...)
    
    def anagrama(s,t):
        return contaletras(s)==contaletras(t)
        
    
    def contaletras(s):
        """ retorna uma lista c[], onde c[0] é o número de a´s de s, 
            c[1] é o número de b´s de s, etc.
            Exemplo: contaletras("banana") -> [3,1,0,0,...,1,0,...]
        """
        letras="abcdefghijklmnopqrstuvwxyz"
        c=[0]*26
        for x in s:
            if x in letras:
                cod = ord(x)-ord("a")
                c[cod] = c[cod]+1
        return c
    
    for (s,t) in [("banana","anaban"),\
                  ("banana","anabab"),\
                  ("marcelo sousa","salmao escuro"),\
                  ("anibal cavaco","cabala nociva")]:
        print s, t, anagrama(s,t)
    
    # Outra solução para anagrama(s,t):
    #   "limpar" s
    #   "limpar" t
    #   Ordenar as 2 strings e comparar
    #      return sorted(s1)==sorted(t1)
    
    #--------------------------------------------
    # Um exercício de ordenação com contagem de frequências
    #    li: [8,5,3,9,1,2,9,3]             (elementos entre 0 e m)
    #    c:  [0,0,0,0,0,0,0,0,0,0,0,0]     (m=11)
    #    c:  [0,1,1,2,0,1,0,0,1,2,0,0]   
    #
    #    ordena(li):
    #       constrói c
    #       percorre i:0, 1, ..., m:
    #          repetir c[i] vezes
    #               append de i a r
    
    def ordena(li):
        m=12
        c = [0]*(m+1)
        r=[]
        for x in li:
            c[x] = c[x]+1
        print c
        for i in range(1,m):
            for k in range(c[i]):
                r.append(i)
        return r
    
    li=[8,5,3,9,1,2,9,3]
    print li, ordena(li)
    
    #  Uma nova técnica de ordenação, "bucket sort"
    #  Vantagem: muito rápido, se m não muito grande, 
    #       O(m+n) onde n=len(li)
    #  Limitação: valores a ordenar inteiros e não
    #     muito grandes: os valores são índices!
    

    [prev] [top] [next]

  20. Inicializar listas; rodar pontos; tabelas de verdade; sufixos de strings; teste de associatividade
    #------------------------------------------------------------
    #   1. Criar uma nova lista li com [1,2,3,1,2,3,...] (300 elementos)
    #      a) usando append
    #      b) usando lista*inteiro
    #      c) usando uma lista em compreensão
    #------------------------------------------------------------
    
    li1=[]
    for i in range(10):
        li1.append(1)
        li1.append(2)
        li1.append(3)
    
    print
    print "1a"
    print len(li1),li1
    
    li2=[1,2,3]*10
    print
    print "1b"
    print len(li2),li2
    
    li3=[i%3+1 for i in range(30)]
    print "1c"
    print len(li3),li3
    
    
    #------------------------------------------------------------
    #   2. Como é que uma função retorna 2 valores?
    #      Com um tuplo.
    #      Exemplo: Escreva uma função 'roda(p,a)' onde
    #            - p é um tuplo (x,y) que representa um ponto do plano
    #            - a é um ângulo
    #        que retorna o ponto (x1,y1) que resulta da rotação
    #        do ponto (x,y) de 'a' graus no sentido directo.
    #
    #        |
    #        |                       | x1 = x*cos(a) - y*sin(a)
    #        |                       | y1 = x*sin(a) + y*cos(a)
    #       y|       o
    #        -----------------
    #                x
    #------------------------------------------------------------
    
    from math import *
    def roda(p,a):
        x=p[0]
        y=p[1]
        x1 = x*cos(a) - y*sin(a)
        y1 = x*sin(a) + y*cos(a)
        return (x1,y1)
    
    print
    print "1b"
    for (p,a) in [((1,0),pi/4), ((0,1),2*pi),((1,1),0),((-1,-1),pi/2)]:
        print p,a,roda(p,a)
    
    #------------------------------------------------------
    #   3. a) Escreva uma função (sem parametros)
    #
    #               tab_verd()
    #
    #      que imprima a tabela de verdade de
    #
    #               a and (b or not c)
    #
    #      Nota: pode fazer com que "i" tome sucessivamente os valores de uma
    #      lista "lista" com uma instrução do tipo "for i in lista:".
    #      Por exemplo:  
    #
    #      for i in [False,True]:
    #          print i
    #
    #      Note que a, b, c devem tomar todos as combinações de valores
    #      booleanos. 
    #------------------------------------------------------------
    
    def tab_verd():
        logs = [False,True]
        print
        print "a and (b or not c)"
        print
        print "a     b     c     valor"
        print "-----------------------"
        for a in logs:
            for b in logs:    
                for c in logs:
                    print conv(a),conv(b),conv(c),a and (b or not c)
    
    def conv(log):
        if log:
            return "True "
        return     "False"
    
    tab_verd()
    
    #---------------------------------------------
    # 4. Considere a função
    def f(n):
        if n==1:
            return 1
        if n%2==0:
            return f(n//2)
        return f(3*n+1)
    
    # a) Determine "com papel e lális" f(3), f(5) e f(7)
    # b) Confirme
    # c) Mostre que, qualquer que seja o inteiro n>=1,
    #    a computação de f(n) termina
    #------------------------------------------------------------
    
    
    #------------------------------------------------------------
    #   5. a) Escreva uma função
    #            sufixo(s,t)
    #      que retorna True se s é sufixo de t e False caso contrário.
    #      Exemplos:
    #         sufixo("","")      -> True
    #         sufixo("ab","cab") -> True
    #         sufixo("ab","abc") -> False
    #         sufixo("ab","ab")  -> True
    #      
    #      b) Escreva uma função
    #            sufixos(s)
    #      que retorna a lista dos sufixos de s. Pode apenas usar 
    #      as funções/métodos ensinados nas aulas.
    #      Exemplos:
    #         sufixos("xbca") -> ["xbca","bca","ca","a",""]
    #------------------------------------------------------------
    
    # usando slides... suf=s[i:] era mais fácil
    def sufixo(s,t):  # s sufixo de t
        m=len(s)    #  s:           0     1   .... m-1
        n=len(t)    #  t:  0 1 ... n-m  n-m+1 .... n-1
        if m>n: 
            return False
        for i in range(m):
            if s[i]!=t[n-m+i]:
                return False
        return True
    
    print 
    print "5a"
    for (s,t) in [("",""),("ab","cab"),("ab","abc"),("ab","ab")]:
        print "s=",s,"t=",t,sufixo(s,t)
    
    # usando slides... suf=s[i:] era mais fácil
    def sufixos(s):
        n=len(s)
        suf=""
        r=[suf]
        for i in range(n-1,-1,-1):  # sufixo s[i]s[i+1]...s[n-1]
            suf = s[i]+suf
            r.append(suf)
        return r
    
    print 
    print "5b"
    s="xbca"
    print s, sufixos("xbca")
    #  -> ["xbca","bca","ca","a",""]
    
    #------------------------------------------------------------
    #   6. Uma operação binária definida no conjunto A={0,1,...,n} 
    #      é descrita por uma lista de listas, conforme se 
    #      exemplica para o caso n=3.
    #      
    #      t: [[0,1,2],\
    #          [1,2,0],\
    #          [2,0,1]]
    #      Escreva uma função
    #          associativo(t)
    #      que retorna 'True' se a operação representada por 't' for
    #      associativa e 'False' caso contrário.
    #------------------------------------------------------------
    
    def associativo(t):
        n=len(t) # lista de listas...
        for a in range(n):
            for b in range(n):
                for c in range(n):
                    ab = t[a][b]
                    r1 = t[ab][c]
                    bc = t[b][c]
                    r2 = t[a][bc]
                    if r1!=r2:
                        return False
        return True
    
    print
    print "6"
    t1= [[0,1,2],\
         [1,2,0],\
         [2,0,1]]
    
    t2= [[0,2,2],\
         [1,1,0],\
         [2,0,1]]
    
    print t1,associativo(t1)
    print t2,associativo(t2)
    

    [prev] [top] [next]

  21. Representações e operações com conjuntos. Teste de associatividade de uma operação binária
    #------------------------------------------------------------
    #    Conjuntos: representações:
    #        - Listas (sem ordem)
    #        - Listas ordenadas
    #   	- Vectores de bits (indicativos de presença)
    #	- Usar uma estrutura de dicionário já existente
    #       - usar estruturas conhecidas por árvores....
    #------------------------------------------------------------
    
    
    #------------------------------------------------------------
    #   1. Suponha que um conjunto é representado por uma lista
    #      (não necessariamente ordenada)
    #
    #           {2,3,5,9}    <->   [2,9,3,5]   (ordem sem importância)
    #
    #      a) implemente a operação de reunião, uniao(a,b)
    #         Exemplo: uniao([2,4,5],[1,4,9]) -> [1,2,4,5,9]
    #
    #      b) outras operações:
    #             intersecçao(a,b)
    #             pertence(x,a)
    #
    #------------------------------------------------------------
    def uniao(a,b):
        r=[]
        for x in a:
            r.append(x)
        for x in b:
            if not x in r:
                r.append(x)
        return r
    
    print
    print "1"
    print uniao([2,4,5],[1,4,9])
    
    #------------------------------------------------------------
    #   2. Suponha que um conjunto é representado por um
    #      "lista de presenças" (bit array,...)
    #
    #           {2,3,5,9}    <->   [0,0,1,1,0,1,0,0,0,1]   (máximo 9)
    #
    #      a) implemente a operação de reunião, uniao(a,b)
    #
    #      b) outras operações:
    #             intersecçao(a,b)
    #             pertence(x,a)
    #
    #      
    #   
    #------------------------------------------------------------
    def uniao2(a,b):
        m=10 # elementos entre 0 e 9
        r=[0]*m
        for x in range(m):
            if a[x]==1 or b[x]==1:
                r[x]=1
        return r
    
    a=[0,0,1,1,0,1,0,0,0,1]
    b=[0,1,1,0,0,1,1,0,0,0]
    print a,b,uniao2(a,b)
    
    
    #------------------------------------------------------------
    #   3. Suponha que um conjunto é representado por uma lista
    #      ordenada.
    #
    #           {2,3,5,9}    <->   [2,3,5,9]   (ordem sem importância)
    #
    #     a) Usando o algoritmo de pesquisa binária, implemente
    #     eficientemente a operação 
    #            interseccao(a,b)
    #
    #     Nota: para a 'união' usa-se o algoritmo de 'merge'
    #
    #     b) Porque é que o resultado fica ordenado (mesma representação)?
    #
    #     c) Determine a ordem de grandeza da eficiência do algoritmo.
    #       |b| * log(|a|)
    #------------------------------------------------------------
    
    def pb(x,v):
        a=0
        b=len(v)-1
        while a<=b:
            m=(a+b)/2
            if x==v[m]:
                return True
            if x<v[m]:
                b=m-1
            else:
                a=m+1
        return False
    
    def interseccao(a,b):
        r=[]
        for x in a:
            if pb(x,b):
                r.append(x)
        return r
    
    print
    print "3"
    a=[2,3,5,8,9,11,18]
    b=[1,3,9,11,33]
    print a, b, interseccao(a,b)
    
    #------------------------------------------------------------
    #  Escreva uma função converte(li,m)
    #  que converte a lista li para o bit array barray
    #  num universo de m elementos {0,1,...,m-1}
    #    ex: converte([4,2,1],10) -> [0,1,1,0,1,0,0,0,0,0]
    #------------------------------------------------------------
    
    def converte(li,m):
        r=[0]*m
        for x in li:
            r[x]=1
        return r
    
    print converte([4,2,1],10)
    
    #------------------------------------------------------------
    #   6. Uma operação binária definida no conjunto A={0,1,...,n} 
    #      é descrita por uma lista de listas, conforme se 
    #      exemplica para o caso n=3.
    #      
    #      t: [[0,1,2],\
    #          [1,2,0],\
    #          [2,0,1]]
    #      Escreva uma função
    #          associativo(t)
    #      que retorna 'True' se a operação representada por 't' for
    #      associativa e 'False' caso contrário.
    #------------------------------------------------------------
    
    def associativo(t):
        n=len(t) # lista de listas...
        for a in range(n):
            for b in range(n):
                for c in range(n):
                    ab = t[a][b]
                    r1 = t[ab][c]
                    bc = t[b][c]
                    r2 = t[a][bc]
                    if r1!=r2:
                        return False
        return True
    
    print
    print "6"
    t1= [[0,1,2],\
         [1,2,0],\
         [2,0,1]]
    
    t2= [[0,2,2],\
         [1,1,0],\
         [2,0,1]]
    
    print t1,associativo(t1)
    print t2,associativo(t2)
    

    [prev] [top] [next]

  22. Ocorrências do máximo. Raíz quadrada. Determinante de uma matriz
    
    #-------------------------------------------------------
    #  Escreva uma funcao nmaximos(li) 
    #     onde li é uma lista de inteiros
    #  e que retorna o número de elementos de li
    #  que são iguais ao maior valor na lista.
    #  Exemplo:
    #     nmaximos([2,1,5,9,3,9,4,2]) -> 2
    #
    #  1) Percorrer a lista 1 vez para determinar o máximo
    #     função maximo(li)
    #  2) Percorrer a lista, e cada vez que li[i]==maximo,
    #     contar mais 1
    #-------------------------------------------------------
    
    def nmaximos(li):
        n=len(li)
        mx=maximo(li)
        c=0
        for i in range(n):
            if li[i]==mx:
                c=c+1
        return c
    
    def maximo(li):
        mx=li[0]
        for i in range(2,len(li)):
            if li[i]>mx:
                mx=li[i]
        return mx
    
    
    #-------------------------------------------------------
    #  Escreva uma funcao nmaximos2(li) 
    #     efectuando apenas 1 passagem (com 1 ciclo 'for')
    #     pela lista li
    #-------------------------------------------------------
    #  mx:  maior elemento já encontrado
    #  num: número de elementos com valor mx
    
    def nmaximos2(li):
        n=len(li)
        mx  = li[0]
        num = 0
        for x in li:
            if x>mx:
                mx=x
                num=1
            elif x==mx:
                num=num+1
        return num
    
    for li in ([2,1,5,9,3,9,4,2],[1,1,1],[1,1,2]):
        print li,nmaximos(li),nmaximos2(li)
    
    
    #-------------------------------------------------------
    #  Escreva uma funcao nmaximos3(li) 
    #     com apenas 1 instrução (de 'return')
    #  Nota: pode usar a função 'max'
    #-------------------------------------------------------
    
    def nmaximos3(li):
        return len([x for x in li if x==max(li)])
    
    for li in ([2,1,5,9,3,9,4,2],[1,1,1],[1,1,2]):
        print li,nmaximos(li),nmaximos2(li),nmaximos3(li)
    
    
    #--------------------------------------------------------------
    # Escreva uma função 
    #    perfeito(n)
    # que retorna True se n é um quadrado perfeito 
    # e False caso contrário
    #   Exemplo: perfeito(16) -> True
    #
    # A função deve ser eficiente (tempo proporcional a log(n))
    # e basear-se no método da pesquisa binária. 
    # Inicialmente sabe-se que o resultado está entre 0 e n...
    #--------------------------------------------------------------
    
    def perfeito(n):
        min=0
        max=n
        # se n tem raiz exacta m (n=m*m), então min <= m <= max
        while min<=max:
            m=(min+max)/2
            m2=m*m
            if m2==n:
                return True  # raíz encontrada!
            elif m2<n:
                min=m+1
            else:
                max=m-1
        return False         # não existe raíz
    
    for i in range(20):
        print i, perfeito(i)
    
    #--------------------------------------------------------------
    #   Uma matriz quadrada é representada por uma lista de listas
    #
    #   [[1,3,4],
    #    [2,1,5],
    #    [4,0,6]
    #   ]
    #  Calcular o determinante
    #  1.     "Triangularizar" a matriz
    #         -------------------------
    #     determinante = produto dos elementos da diagonal principal
    #
    #  - Somar uma linha multiplicada por uma constante a outra
    #    não altera o determinante
    #  - Assume-se que nunca vai ser a[i][i]==0
    #
    #     i=0, j=1,2
    #  1. Somar a 1a linha multiplicada por (-2) à 2a linha
    #     Somar a 1a linha multiplicada por (-4) à 3a linha
    #   [[1,  3,  4],
    #    [0, -5, -3],
    #    [0,-12,-10]
    #   ]
    #
    #     i=1, j=2
    #  1. Somar à 3a linha a 2a linha multiplicada por (-12/5=-2.4)
    #   [[1,  3,  4  ],
    #    [0, -5, -3  ],
    #    [0,  0, -2.8]
    #   ]
    #  
    #  2. Determinante = produto dos elementos da diagonal principal
    #     Neste caso: 1*(-5)*(-2.8) = 14
    #--------------------------------------------------------------
    
    def determinante(mat):
        n=len(mat)
        for i in range(n):
            for j in range(i+1,n):
                fac=-mat[j][i]/(mat[i][i]+0.0)
                mult(mat,i,j,fac)
                display(mat)
        prod=1
        for i in range(n):
            prod=prod*mat[i][i]
        return prod
    
    def mult(mat,i,j,f):
        n=len(mat)
        for k in range(n):
            mat[j][k] = mat[j][k] + f*mat[i][k]
    
    def display(mat):
        n=len(mat)
        print
        print
        for i in range(n):
            for j in range(n):
                print ("%6.2f" % (mat[i][j])),
            print
        print
    
    mat = [[1,3,4],\
           [2,1,5],\
           [4,0,6]]
    
    display(mat)
    print determinante(mat)
    

    [prev] [top] [next]

  23. O módulo 'Tkinter'
    Nota.
    O seguinte 'site' contém lições sobre o Tkinter (e sobre aspectos
    gerais do pyton) que podem ser interessantes...
    
    http://wiki.python.org/moin/Intro%20to%20programming%20with%20Python%20and%20Tkinter
    
    ------------------------------------------------------------------------
    Primeiro exemplo: desenho de um rectângulo e de uma 
    linha num 'canvas'
    ------------------------------------------------------------------------
    
    from Tkinter import *
    # objecto Tk... janela:
    main=Tk()                
    # canvas, chamado 'w':
    w=Canvas(main,width=200,height=100,bg="#444444")
    # colocá-lo na janela:
    w.pack()
    # rectângulo no canvas 'w'
    w.create_rectangle(50,50,80,80,fill="#ff0000")
    # linha (0,20)-(10,90)-(20.90)-(100,10)  no canvas 'w'
    w.create_line(0,20,10,90,20,90,100,10)
    mainloop()
    
    ------------------------------------------------------------------------
    Segundo exemplo: texto e botão (carregando nele, destrói-se a janela...)
    ------------------------------------------------------------------------
    
    from Tkinter     import *
    from Tkconstants import *
    tk = Tk()
    frame = Frame(tk, relief=RIDGE, borderwidth=20)
    frame.pack(fill=BOTH,expand=1)
    label = Label(frame, text="Que lindo!",background="#a000a0")
    label.pack(fill=X, expand=1)
    button = Button(frame,text="Embora!",command=tk.destroy)
    button.pack(side=BOTTOM)
    tk.mainloop()
    
    ------------------------------------------------------------------------
    Desenho de imagens...
    ------------------------------------------------------------------------
    # =====================================================
    # Desenho de imagens a preto e branco com o 'Tkinter' -- 
    #    Reducao de contraste
    # =====================================================
    #
    # Possivel representacao de uma imagem
    #  ---------------------------------------------------------------
    #   - Uma "imagem" a preto e branco (PB) e' uma lista de linhas,
    #     cada linha e' uma lista de valores entre 0 (preto)
    #     e 255(branco)
    #    
    #     Uma "imagem" a cores e' um tuplo
    #                     (r,g,b) 
    #     onde r,g,b sao imagens a preto e branco
    #        ... claro que outras representações (organizações da
                 informação) seriam possíveis...
    #  ---------------------------------------------------------------
    #   Funcoes usadas:
    #   redc:      reduz o contraste de uma imagem a preto e branco
    #   pbimagem:  mostra uma imagem a preto e branco
    #   cimagem  - mostra uma imagem a cores
    #   grey, dig16, color: funcoes auxiliares
    #  ---------------------------------------------------------------
    #
    from Tkinter import *   # modulo grafico
    from random import *
    from copy import *
    
    
    #  -----------------------------------------------
    #     converter inteiro para string - digito hexadecimal
    #  -----------------------------------------------
    def dig16(n):
        "n de 0 a 15  ->  digito hexadecimal"
        return "%x"%(n)
    
    #  ----------------------------------------------
    #    gerar uma "imagem" aleatoria
    #  ----------------------------------------------
    # #--- -> imagem aleatoria lado * lado
    def lrand(lado):
        return [[randint(0,255) for a in range(0,lado)]\
                    for b in range(0,lado)]
    
    
    #  ------------------------------------------------
    #   reduz o contraste de uma 'imag' quadrada
    #  ------------------------------------------------
    def redc(im):
        n=len(im)
        c=deepcopy(im)
        for y in range(1,n-1):     # 1 a n-2
            for x in range(1,n-1): # 1 a n-2
                c[x][y]=(im[x][y]+im[x-1][y]+im[x+1][y]+im[x][y-1]+im[x][y+1])/5
        return c
    
    #  --------------------------------------------------------
    #           desenha uma imagem a preto e branco            
    #   list: [[linha 0],[linha 1],...,[linha n]]
    #   ps: pixel size, cada ponto e' representado por um quadrado
    #   de dimensoes ps*ps
    #   Nota: O valor de y cresce quando se desce na janela 
    #   (convenção contrária à usual...)
    #  --------------------------------------------------------
    
    def pbimagem(lista,ps=30):
        """ desenha o rectangulo composto de quadrados, 'lista';
            cada quadrado tem 'ps' de lado
        """
        nx=len(lista[0])      # n. de colunas
        ny=len(lista)         # n. de linhas
        dx=nx*ps              # lado horizontal (total dos quadrados)
        dy=ny*ps              # lado vertical (total dos quadrados)
        main=Tk()
        w=Canvas(main,width=dx,height=dy)
        w.pack()
        for y in range(ny):   # desenhar os quadrados
            y0=dy-y*ps-ps
            for x in range(nx):
                col=grey(lista[y][x])
                x0=x*ps
                w.create_rectangle(x0,y0,x0+ps,y0+ps,fill=col)
        mainloop()
    
    #-- define string de cor cinzenta
    def grey(x):
        """ cor cinzenta
            ex, x=160  ->  "#a0a0a0"  (cinzento)
        """
        r=dig16(x/16)+dig16(x%16)
        g=r
        b=r
        return "#"+r+g+b
    
    
    # Pequeno teste sem usar o Tkinter:
    #a=lrand(3)
    #print a
    #a=[[6,0,3],[8,0,8],[6,1,5]]
    #print a
    #print redc(a)
    
    
    # teste do desenho da imagem a pb e da redução de contraste:
    #a=lrand(50)
    #pbimagem(a,20)
    #pbimagem(redc(a),20)
    
    
    
    # =====================================================
    # Desenho de imagens a cores com o 'Tkinter'
    # =====================================================
    #
    # Lembrando...
    #  ---------------------------------------------------------------
    #   - Uma "imagem" a cores e' formada por 3 listas de linhas,
    #     3 imagens,
    #     como nas imagens a preto e branco
    #     --- e' da forma (r,g,b) onde r,g,b sao imagens a preto e branco
    #  ---------------------------------------------------------------
    
    
    
    
    # -----------------------------------------------
    #     converter inteiro para string - digito hexadecimal
    #      <Igual ao programa "preto e branco">
    #
    #----------------------------------------------
    #    gerar uma "imagem" aleatoria 
    #      <Igual ao programa "preto e branco">
    #
    #------------------------------------------------
    #   --- exercicio das aulas
    #   reduz contraste, imag tem que ser quadrada
    #      <Igual ao programa "preto e branco">
    #
    #  -----------------------------------------------
    #   (r,g,b): R, g b - mesmo formato que a preto e branco
    #      podiamos ter usado uma lista de lista de trios...
    #  -----------------------------------------------
    def cimagem((r,g,b),ps):
        nx=len(r[0])      # n. de colunas
        ny=len(r)         # n. de linhas
        dx=nx*ps          # lado horizontal
        dy=ny*ps          # lado vertical
        main=Tk()
        w=Canvas(main,width=dx,height=dy)
        w.pack()
        for y in range(ny):
            y0=dy-y*ps-ps
            for x in range(nx):
                col=color(r[y][x],g[y][x],b[y][x])
                x0=x*ps
                w.create_rectangle(x0,y0,x0+ps,y0+ps,fill=col)
        mainloop()
    
    def color(r,g,b):
        """ r,g,b: entre 0 e 255
            retorna string com r, g, b em hexadecimal
            RRGGBB
            Exemplo, vermelho escuro: 880000
        """
        red  =dig16(r/16)+dig16(r%16)
        green=dig16(g/16)+dig16(g%16)
        blue =dig16(b/16)+dig16(b%16)
        return "#"+red+green+blue
    
    
    #=====================================================
    #  --- teste a cores
    #=====================================================
    
    
    # teste do desenho da imagem a cores e da redução de contraste:
    #lado=32
    #r=lrand(lado)        # vermelhos: lado*lado aleatório, cada de 0 a 255
    #g=lrand(lado)        # verdes: lado*lado aleatório, cada de 0 a 255
    #b=lrand(lado)        # azuis: lado*lado aleatório, cada de 0 a 255
    
    #imag = (r,g,b)       # tuplo rgb
    #cimagem(imag,30)
    #x=raw_input()
    
    #rimag = (redc(r),redc(g),redc(b))  
    #cimagem(rimag,30)    # imagem com o contraste reduzido
    
    

    [prev] [top] [next]

  24. Exercícios simples
    
    # 1)
    # Descrever por palavras (ou através de uma expressão matemática)
    # o valor calculado (no caso geral) por cada uma das seguintes funções
    # Admite-se que os parâmetros a, b são inteiros não negativos.
    
    # a)
    def fx(a,b):
        x=a
        for i in range(b):
            x=x*a
        return x
    
    
    # b)
    def fy(a,b):
        x=a
        for i in range(b):
            x=x*x
        return x
    
    # c)
    def fz(a,b):
        x=a
        for i in range(b):
            x=x*x
            return x
        return x
    
    # 2)
    #  Escrever uma função equivalente à função 'fz' sem usar qualquer
    #  ciclo (while ou for)
    
    #----------------------------------------
    # 3)
    #  Reescrever a função 'fy' substituindo o ciclo 'for' por
    #  um ciclo 'while'
    
    #----------------------------------------
    # 4)
    #  A seguinte função é equivalente a uma das funões 'fx, 'fy' ou 'fz'.
    #  Diga a qual e porquê.
    
    def g(a,b):
        if b==0:
            return a
        return g(a,b-1)*a
    
    # teste
    for (a,b) in [(2,3),(3,0),(3,1),(3,4)]:
        print "a=",  a,       "b=",  b,       "fx=", fx(a,b),\
              "fy=", fy(a,b), "fz=", fz(a,b), "g=",  g(a,b)
    
    #----------------------------------------
    # 5)
    #  Seja 'a' uma lista de valores 'int' ou 'float'. Escreva uma função
    #           retira(a)
    #  que determina a lista que se obtém de 'a' retirando todos os 
    #  valores iguais ao máximo e todos os valores iguais ao mínimo.
    #     Exemplo retira([8,9,1,9,2,7,9]) -> [8,2,7]
    #  Admite-se que 'a' tem pelo menos um elemento.
    #  Notas:
    #    Pode usar as funções 'max' e 'min'. A utilização de listas em
    #    compreensão facilita a solução deste problema,
    
    def retira(a):
        ...
    
    
    # teste
    li=[8,9,1,9,2,7,9]
    print li, retira(li)
    li=[5]
    print li, retira(li)
    

    [prev] [top] [next]

  25. (vazio)

    [prev] [top] [next]

  26. Pesquisa, ver - Slides sobre algoritmos de pesquisa (introdução)

    [prev] [top] [next]

  27. Ordenação, ver - Slides sobre algoritmos elementares de ordenação

    [prev] [top] [next]

  28. Formatação de 'strings'
    Ver Cap. 7 (strings) e Sec. 11.2 (formatos) de "How to think..."

    [prev] [top] [next]

  29. Problemas diversos
    
     Estruturas de dados
    
       Básicas: int, float, bool
    
       Objectos
    
           listas    (list)             [...,...,...]
           tuplos    (tuple)            (...,...,...)
           strings e caracteres (str)   "...."
    
    
       Funções
    
           bissexto:  int       --> bool
           >:         int * int --> bool
           divisivel: int * int --> bool
           sort:      list      --> list
           divisores: int       --> list
           newton:    function * function * float * float --> float
    
     --------------------------------------------------------
    
     Exercícios com strings
    
     1) contar vogais
    
          cvog(s)    str  ->  int
    
          percorrendo os caracteres de uma string
          teste "c é vogal"?
             -> incrementa s
    
    
                   def cvog(s):
                       n=len(s)
                       nv=0
                       for i in range(n):
                           if s[i] in "aeiou":
                               nv=nv+1
                       return nv
    
     2) diminuitivos (o programa nao vai ser perfeito)
    
         dim(s)     str  -->  str
    
          Formar novo string até ao penútimo caracter (usar +)
          se o último caracter = a  ==> nao o incluir e concatenar ...
          se o último caracter = o  ==> nao o incluir e concatenar ...
          outros casos            ==> juntar ...
    
          Melhorar: casario -> casariozinho
    
                   def dim(s):
                       n=len(s)
                       r=""
                       for i in range(n-1):
                           r=r+s[i]
                       if s[n-1]=="a":
                           return r+"inha"
                       if s[n-1]=="o":
                           return r+"inho"
                       return r+s[n-1]+"inho"
    
    
     3) Concatenação
    
          concat(a,b)   str*str  --> str
    
          Formar novo string para o qual se copia a e depois b
          (r = r + c)
    
    
                   def concat(a,b):
                       na=len(a)
                       nb=len(b)
                       r=""
                       for i in range(na):
                           r=r+a[i]
                       for i in range(nb):
                           r=r+b[i]
                       return r
    
    
    
     4) Ordenar: escrever uma função de comparação comp(a,b) que compara
        palavras que (só) podem ter letras maiúsculas ou minúsculas ou
        dígitos. 
          - Não há diferenca entre letras maiúsculas ou minúsculas
          - Os dígitos são ignorados
          - resultado: -1,0,1 conforme a<b, a=b, a>b
    
        Exemplos:
            compara("Ai50","a9i")  -> 0
            compara("","a")        -> -1
    
    

    [prev] [top] [next]

  30. (vazio)

    [prev] [top] [next]

  31. (vazio)

    [prev] [top] [next]

  32. (vazio)
    Ver 12.8 (módulo "copy") de "How to think..."

    [prev] [top] [next]

  33. (vazio)
    Capítulo 11 de "How to think..."

    [prev] [top] [next]

  34. (vazio)

    [prev] [top] [next]

    [prev] [top] [next]

TOP













































TOP

Bibliografia

Livros recomendados

  1. A. Downey, J. Elkner, C. Meyers How to Think like a Computer Scientist, livro principal.
    Existe uma versão mais recente (2007), How to Think Like a (Python) Programmer,
  2. B. Miller, B. Ranum, Problem Solving with Algorithms and Data Structures using Python, Franklin, Beedle and Associates, 2006.
  3. A. Gauld, Learn to Program Using Python, Addison-Wesley.
  4. H. M. Deitel, P. J. Deitel, J. P. Liperi, B. A. Wiedermann, Python: How to Program, Prentice-Hall, livro mais avanado que inclui tópicos como: programação web , processamento de XML, interligação a bases de dados, gráficos e multimédia.

Muitas outras referências podem ser interessantes...ver por exemplo os slides. Mas não nos esqueçamos que, para aprender programar, mais importante que ler livros é programar.

Ver também os "elementos de estudo"

TOP












































TOP

Prova prática, exames e classifica'ões

Classifica'ões

Classifica'ões da prova prática.

Alunos sem frequência (de entre os alunos que estavam inscritos s aulas práticas).


Notas importantes sobre a prova e o exame













































TOP

Docentes

 
    Turmas           Docente            xxx
    ---------------------------------------
    T  TP1  TP2  P1  Armando Matos      acm 
    P5  P6           Ana Paula Tomás    apt
    P4               Luis Antunes       lfa 
    P2  P3           Sérgio Crisóstomo  slc 
    ---------------------------------------
    email de cada docente: xxx@dcc.fc.up.pt

TOP












































TOP

Variado

Emacs: atalhos do teclado

Emacs: atalhos do teclado


Instala'ão do python

Para instalar python no seu sistema operativo (linux, windows, mac-os), procure em

http://www.python.org/download/

Para instalar python e emacs no sistema Windows é necessário que o emacs saiba o endereco do interpretador de python. Uma hipótese é sugerida pelo seguinte exemplo

Localiza'ão do programa 'emacs':

     C:\emacs-22.3-bin-i386\emacs-22.3\bin\runemacs.exe

"home":
     C:\Documents and Settings\acm\Application Data

file O ficheiro de configura'ão '.emacs' está no "home".
---------------------------------------
Localiza'ão do interpretador de pyhon (python command line)
     C:\Python25\python
---------------------------------------

conteúdo poss-vel do ficheiro '.emacs' - a parte importante é a linha 
...'(python-python-command "C:\\Python25\\python")
Quase tudo são comentários...

C:\Documents and Settings\acm\Application Data\.emacs:
(custom-set-variables
  ;; custom-set-variables was added by Custom.
  ;; If you edit it by hand, you could mess it up, so be careful.
  ;; Your init file should contain only one such instance.
  ;; If there is more than one, they won't work right.
 '(python-python-command "C:\\Python25\\python")
 '(show-paren-mode t)
 '(tool-bar-mode nil)
 '(transient-mark-mode t))
(custom-set-faces
  ;; custom-set-faces was added by Custom.
  ;; If you edit it by hand, you could mess it up, so be careful.
  ;; Your init file should contain only one such instance.
  ;; If there is more than one, they won't work right.
 )


Python: ficheiros; comandos da shell

Ver.


Python: obtendo informa'ão sobre os métodos associados a uma classe...


>>> s="aiai"        # s passa s ser uma string (objecto da classe str)
>>> type(s)
<type 'str'>        # ... como se vê!
>>> dir(s)          # Os métodos das strings:
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', 
 '__eq__', '__ge__', '__getattribute__', '__getitem__', 
 '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', 
 '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', 
 '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', 
 '__rmul__', '__setattr__', '__str__', 
 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 
 'expandtabs', 'find', 'index', 'isalnum', 'isalpha', 'isdigit', 
 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 
 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 
 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 
 'startswith', 'strip', 'swapcase', 'title', 'translate', 
 'upper', 'zfill']


print a.lower.__doc__  # Documenta'ão sobre "lower"
S.lower() -> string

Return a copy of the string S converted to lowercase.

>>> from math import *
>>> help("math")
...
...