9.4 - Loop com índices
Escrevi as funções na seção anterior com loops for
porque eu só precisava dos caracteres nas strings; não precisava fazer nada com os índices.
Para is_abecedarian
temos que comparar letras adjacentes, o que é um pouco complicado para o loop for:
def is_abecedarian(word):
previous = word[0]
for c in word:
if c < previous:
return False
previous = c
return True
Uma alternativa é usar a recursividade:
def is_abecedarian(word):
if len(word) <= 1:
return True
if word[0] > word[1]:
return False
return is_abecedarian(word[1:])
Outra opção é usar um loop while
:
def is_abecedarian(word):
i = 0
while i < len(word)-1:
if word[i+1] < word[i]:
return False
i = i+1
return True
O loop começa com i == 0
e termina quando i == len(word)-1
. Cada vez que passa pelo loop, o programa compara o “i-ésimo” caractere (que você pode considerar o caractere atual) com o caractere de posição i+1
(que pode ser considerado o caractere seguinte).
Se o próximo caractere for de uma posição anterior (alfabeticamente anterior) à atual, então descobrimos uma quebra na tendência alfabética, e retornamos False
.
Se chegarmos ao fim do loop sem encontrar uma quebra, então a palavra passa no teste. Para convencer-se de que o loop termina corretamente, considere um exemplo como 'flossy'
. O comprimento da palavra é 6, então o loop é executado pela última vez quando i for igual a 4, que é o índice do segundo caractere de trás para frente. Na última iteração, o programa compara o penúltimo caractere com o último, que é o que queremos.
Aqui está uma versão de is_palindrome
(veja o Exercício 6.3) que usa dois índices: um começa no início e aumenta; o outro começa no final e diminui.
def is_palindrome(word):
i = 0
j = len(word)-1
while i<j:
if word[i] != word[j]:
return False
i = i+1
j = j-1
return True
Ou podemos reduzir a um problema resolvido anteriormente e escrever:
def is_palindrome(word):
return is_reverse(word, word)
Usando is_reverse
da seção 8.11.