Suponha que tem uma cadeia de caracteres com um dado comprimento e a pretende dividir em n partes iguais. Implemente em Python o respectivo programa não se esquecendo de prever o caso de o comprimento da cadeia não ser múltiplo de n.
Enviou-me a sua tentativa de solução que não funcionava:
01.
def
divide(f, p):
02.
aux
=
[]
03.
a
=
len(f)
04.
lpp
=
(len(f)
-
1
)
/
p
05.
dif
=
0
06.
x
=
lpp
07.
faux
=
''
08.
n
=
0
09.
while
(n < p):
10.
faux
=
f[dif:lpp
+
1
]
11.
aux.append(faux)
12.
dif
=
(dif
+
lpp)
+
1
13.
lpp
=
(lpp
+
x)
14.
n
=
n
+
1
15.
return
aux
Qual é a lógica desta solução? Bem andar a partir a frase em pedaços todos do mesmo comprimento. Calcula-se esse comprimento na linha 4. Usam-se duas marcas (dif e lpp) para determinar os limites de cada pedaço, que vão sendo guardados em aux, a capa passagem pelo ciclo while. A ideia faz sentido.
Vamos ver alguns dos seus problemas. Começo pelo código inútil:
a = len(f), não está lá a fazer nada, nunca sendo usado.
faux = '' : esta inicialização não é preciso para nada
Agora os erros:
lpp = (len(f) - 1) / p: não se deve retirar um ao comprimento, dado o modo como a divisão funciona.
faux[f[dif:lpp+1]: errado devido à soma de 1.
dif = dif + lpp +1: aqui talvez o erro maior! Em cada etapa dif deve avançar para o valor de lpp.
Posto tudo isto uma solução usando esta ideia seria (notem que uso x no lugar de lpp, por uma questão de clareza):
01.
def
divide_corrigido(f, p):
02.
aux
=
[]
03.
lpp
=
len(f)
/
p
04.
dif
=
0
05.
x
=
lpp
06.
n
=
0
07.
while
(n < p):
08.
faux
=
f[dif:x]
09.
aux.append(faux)
10.
dif
=
x
11.
x
=
x
+
lpp
12.
n
=
n
+
1
13.
aux.append(f[dif:])
14.
return
aux
Mas não estou satisfeito, pois podemos encontrar uma solução mais elegante, tendo por base o mesmo princípio: duas marcas que vão avançando a cada passagem pelo ciclo. Mas para tal podemos usar uma combinação de um ciclo for com a operação range:
01.
def
divide_ec(frase,n):
02.
"""divide a frase em n pedaços iguais."""
03.
# número de caracteres em cada parte
04.
num_car
=
len(frase)
/
n
05.
# calcula e guarda em aux
06.
aux
=
[]
07.
for
i
in
range(
0
,len(frase),num_car):
08.
aux.append(frase[i:i
+
num_car])
09.
return
aux
O trabalho de fazer avançar a marca correctamente é assegurado pelo modo de funcionar do range comn três argumentos. Concordarão que este programa é mais claro do que o proposto! E prevê o caso de a frase ter um comprimento que não é múltiplo de n!
Se gostarem de listas por compreensão podem ainda prescindir de aux.:
1.
def
divide_ec_2(frase,n):
2.
num_car
=
len(frase)
/
n
3.
return
[frase[i:i
+
num_car]
for
i
in
range(
0
,len(frase),num_car)]
Mas voltemos ao enunciado, que nos fala em n partes iguais. Se corrermos o programa, verificamos que nos casos em que não é múltiplo existem n+1 partes! Como corrigir este aspecto? Uma solução será esticar a cadeia e passar a ter cadeias todas do mesmo tamanho, menos a última. Esta era, aliás, a interpretação correcta do enunciado...
1.
def
divide_ec_3(frase,n):
2.
"""divide uma sequência frase em n partes.
3.
A última pode ser menor."""
4.
parte
=
(len(frase)
+
n
-
1
)
/
n
5.
aux
=
[]
6.
for
i
in
range(
0
,n):
7.
aux.append(frase[parte
*
i:parte
*
(i
+
1
)])
8.
return
aux
E até nos podemos dar ao luxo de ter uma solução recursiva!!
1.
def
divide_ec_4(frase,n):
2.
if
n
=
=
0
:
3.
return
[]
4.
else
:
5.
return
[frase[:len(frase)
/
n]]
+
divide_ec_4(frase[len(frase)
/
n:],n
-
1
)
E assim terminamos este exercício. aprendemos muito com os nossos erros ... e com os erros dos outros!!
Bom post. Pessoalmente tb gosto de analisar código usando diversos algoritmos e até paradigmas diferentes. Muitas vezes acabamos melhorando bastante o processo com isso.
ResponderEliminarSó uma correção, na chamada recursiva de divide() no return deve ser divide_ec_4().
Abraço.