Algoritmos de Programación con Python

6.4. Procesamiento sencillo de cadenas

Problema 6.1. Nuestro primer problema es muy simple: Queremos contar cuántas letras A hay en una cadena x.

1. Especificación: Dada una cadena x, la función retorna un valor contactor que representa cuántas letras A tiene x.

2. Diseño: ¿Se parece a algo que ya conocemos?

Ante todo es claro que se trata de un ciclo definido, porque lo que hay que tratar es cada uno de los caracteres de la cadena x, o sea que estamos frente a un esquema:

para cada letra de x
    averiguar si la letra es "A"
    y tratarla en consecuencia

Nos dice la especificación que se necesita una variable contador que cuenta la cantidad de letras A que contiene x. Y por lo tanto sabemos que el tratamiento es: si la letra es A se incrementa el contador en 1, y si la letra no es A no se lo incrementa, o sea que nos quedamos con un esquema de la forma:

para cada letra de x
    averiguar si la letra es "A"
    y si lo es, incrementar en 1 el contador

¿Estará todo completo? Alicia Hacker nos hace notar que en el diseño no planteamos el retorno del valor del contador. Lo completamos entonces:

para cada letra de x
    averiguar si la letra es "A"
    y si lo es, incrementar en 1 el contador
retornar el valor del contador

¿Y ahora estará todo completo? E. Lapurado, nuestro alumno impaciente nos induce a poner manos a la obra y a programar esta solución, y el resto del curso está de acuerdo.

3. Implementación

Ya vimos que Python nos provee de un mecanismo muy poderoso para recorrer una cadena: una instrucción for que nos brinda un carácter por vez, del primero al último.

Proponemos la siguiente solución:

def contarA(x):
    for letra in x:
        if letra == "A":
            contador = contador + 1
    return(contador)

Y la probamos

>>> contarA("Ana")
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "<stdin>", line 4, in contarA
UnboundLocalError: local variable 'contador' referenced
before assignment
>>>

¿Qué es lo que falló? ¡falló el diseño! Evidentemente la variable contador debe tomar un valor inicial antes de empezar a contar las apariciones del caracter A. Volvamos al diseño entonces.

Nota Es muy tentador quedarse arreglando la implementación, sin volver al diseño, pero eso es de muy mala práctica, porque el diseño queda mal documentado, y además podemos estar dejando de tener en cuenta otras situaciones err6neas.

4. Diseño (revisado) Habíamos llegado a un esquema de la forma

para cada letra de x
    averiguar si la letra es "A"
    y si lo es, incrementar en 1 el contador
retornar el valor del contador

¿Cuál es el valor inicial que debe tomar contador? Como nos dice la especificación contador cuenta la cantidad de letras A que tiene la cadena x. Pero si nos detenemos en medio de la computación, cuando aún no se recorrió toda la cadena sino sólo los primeros 10 caracteres, por ejemplo, el valor de contador refleja la cantidad de A que hay en los primeros 10 caracteres de x.

Si llamamos parte izquierda de x al segmento de x que ya se recorrió, diremos que cuando leímos los primeros 10 caracteres de x, su parte izquierda es el segmento x[0:10].

El valor inicial que debemos darle a contador debe reflejar la cantidad de A que contiene la parte izquierda de x cuando aún no iniciamos el recorrido, es decir cuando esta parte izquierda es x[0:0](o sea la cadena vacía). Pero la cantidad de caracteres iguales a A de la cadena vacía es 0.

Por lo tanto el diseño será:

inicializar el contador en 0
    para cada letra de x
    averiguar si la letra es "A"
    y si lo es, incrementar en 1 el contador
retornar el valor del contador

(lo identificaremos como el esquema Inicialización - Ciclo de tratamiento - Retorno de valor). Pasamos ahora a implementar este diseño:

5. Implementación (del diseño revisado)

def contarA (x):
    """ La funcion contarA(x) cuenta cuántas
        letras "A" aparecen en la cadena x ."""
    contador = 0
    for letra in x:
        if letra == "A":
            contador = contador + 1
    return(contador)

6. Prueba

>>> contarA ("banana")
0
>>> contarA ("Ana")
1
>>> contarA ("lAn")
1
>>> contarA ("lAAn")
2
>>> contarA ("lAnA")
2
>>>

7. Mantenimiento:

Esta función resulta un poco limitada. Cuando nos pidan que contemos cuántas letras E hay en una cadena tendremos que hacer otra función. Tiene sentido hacer una función más general que nos permita contar cuántas veces aparece un carácter dado en una cadena.

Ejercicio 6.4. Escribir una función contar(l, x) que cuente cuántas veces aparece un carácter l dado en una cadena x.

Ejercicio 6.5. ¿Hay más letras A o más letras E en una cadena? Escribir un programa que lo decida.

Ejercicio 6.6. Escribir un programa que cuente cúantas veces aparecen cada una de las vocales en una cadena. No importa si la vocal aparece en mayúscula o en minúscula.


Copyright (c) 2011-2014 Rosita Wachenchauzer, Margarita Manterola, Maximiliano Curia, Marcos Medrano, Nicolás Paez. La copia y redistribución de esta página se permite bajo los términos de la licencia Creative Commons Atribución - Compartir Obras Derivadas Igual 3.0 siempre que se conserve esta nota de copyright.