sexta-feira, 9 de outubro de 2009

Problema 2.16

Pretende-se um programa que determine se uma dada cadeia de caracteres é, ou não, uma capicua. São capicuas as cadeias que são idênticas lidas da esquerda para a direita, e da direita para a esquerda. Exemplo: madam.


def capicua_a(cad):
"""
Determina se a cadeia é uma capicua.
"""
cap_p = True
while cap_p and (len(cad) >= 2):
cap_p = cap_p and (cad[0] == cad[-1])
cad = cad[1:-1]
return cap_p


Qual a lógica do programa? Comparar os caracteres a igual distância das extremidades (linha 7) e determinar se o resultado é verdadeiro ou falso. Se for falso, cap_p, que no início é True, passa a False provocando o abandono do ciclo while (linha 6). Se o cilco while terminar porque foram analisados todos os pares caracteres então cap_p será True (nunca é alterada) e esse valor é devolvido (linha 9). A variável cap_p funciona como uma bandeira que sinaliza uma condição(flag).

11 comentários:

  1. A seguinte comparação não era suficiente para o problema?

    cad == cad[::-1] and len(cad) >=2

    ResponderEliminar
  2. O programa até se resolve só com uma linha:-)...

    def capicua(cad):
    return cad == cap[::-1]

    A minha ideia foi introduzir os conceitos de ciclo while e de flag.

    Não sei se o que pretende seria (cad[0] == cad[-1]) and (len(cad) >= 2). Mesmo que use isso não se esqueça que tem que devolver um valor (True ou False) no final. Uma solução poderá ser:

    def capicua(cad):
    while len(cad) >= 2 and cad[0] == cad[-1]:
    cad = cad[1:-1]
    return (len(cad) < 2)
    Note que a ordem dos dois testes no ciclo while tem que se a apresentada.

    ResponderEliminar
  3. Só com isto o programa não funciona:
    def capicua(cad):
    return cad == cap[::-1]

    Mas esta maneira é igualmente fácil e simples:
    def capicua(str1):
    if str1 == str1[::-1]:
    print "E uma capicua"
    else:
    print "Nao e capicua"

    ResponderEliminar
  4. Para o Milton: funciona sim. O seu problema está em que seguramente apenasdefine e não usa capicua: faça
    print capicua('...')

    ResponderEliminar
  5. Sim, a minha ideia era como disse:
    def capicua(a)
    return a == a[::-1]

    Foi até como fiz e funcionava. Estava a achar estranho, por ser tão simples de resolver e por ter dito nas aulas teóricas qualquer coisa como "se não conhecermos as potencialidades da linguagem provavelmente vamos dar mais voltas do que as precisas" ter resolvido dessa maneira.
    Confirma, então, que não preciso de usar uma condição if para ter o resultado lógico de uma condição, certo? Isto é, posso associar a um objecto o valor da condição a >= b com uma instrução do género:
    valor = a >= b

    ResponderEliminar
  6. Confirmo. As operações booleanas (==, !=, >, <, etc) devolvem um objecto do tipo booleano: True ou False. Depois pode associar o objecto ao nome que quiser. Claro que nos testes dos if e dos ciclos for ou while terá que usar s uma expressão que dê um resultado booleano ou como tal seja considerada. Por exemplo é possível algo como:
    if 4:
    print 'sempre verdadeiro'

    if []:
    print 'nunca cá chego...'

    ResponderEliminar
  7. Só estava a dizer que aqui:

    def capicua(cad):
    return cad == cap[::-1]

    O erro está em estar escrito cap[::-1] em vez de cad[::-1] (o p esta trocado com o d)

    ResponderEliminar
  8. um método simples e penso que acessível a todos

    def capicua():
    c=raw_input('insira a palavra: ')

    if c[::-1]==c:
    print 'e uma capicua'
    else:
    print 'nao e uma capicua'

    ResponderEliminar
  9. Resolvi assim:

    def capicua(x):
    contador=0
    for i in range(len(x)):
    if x[i]!=x[-1-i]:
    contador+=1
    if contador>1:
    print "nao eh capicua"
    else:
    print "eh capicua"

    (Só depois vi a condição da capicua ser maior que 1)

    ResponderEliminar
  10. Rui Gonçalves: o seu programa é muito ineficiente. Repare que, mesmo quando já sabe que não é capicua, continua a testar até ao final da sequência. Deve por isso recorrer a um ciclo que é executado condicionalmente, por exemplo, um ciclo while. Se quer insistir no ciclo for, então o código deve ser algo assim:

    ...
    for i in range(len(x)):
    ...if x[i] != x[-1-i]:
    ......return False
    return True

    ResponderEliminar