1. Curso de PHP – Clase 5 – Resolución de ejercicios
propuestos
Publicado el 24/05/2012 por Alejandro en Curso de PHP Básico • 2 comentarios
Etiquetas: curso, php
En la última clase teórica del curso de PHP vimos las estructuras iterativas que sirven
para repetir porciones de código. Exploramos los bucles for, foreach, while y do…
while. Propuse seis ejercicios para poner en práctica lo visto. Así que, sin más, voy a
pasar a mostrar como resolverlos.
Como siempre, el código fuente donde está la resolución de estos ejercicios lo pueden
encontrar aquí. Y la salida de ese código, aquí.
Ejercicio 1
Dado un array de 20 elementos que consiste en números reales (con coma decimal) y
que cada elemento representa la venta del día de un comercio. Calcular el promedio de
venta por día utilizando alguna estructura iterativa. Mostrar el resultado por pantalla.
Ya habíamos hecho un ejercicio para calcular un promedio. Aquí la ventaja es que los
valores están cargados en un array y nos da la posibilidad de usar algún bucle. El
enunciado no dice qué estructura utilizar así que podemos elegir.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
$ventas_dia = array (120.25, 85.05, 90.36, 98.95, 102.51,
79.17, 89.55, 80.69, 86.77, 115.85,
124.25, 92.24, 94.97, 112.73, 127.85,
100.05, 105.42, 91.12, 99.51, 95.63
);
$total = 0;
for ($i=0; $i<=count($ventas_dia)-1; $i++) {
$total += $ventas_dia[$i];
}
$promedio = $total / count($ventas_dia);
echo 'El promedio de ventas es: '.$promedio;
?>
Primero definimos un array $ventas_dia y le cargamos los valores que son números
reales, es decir, números de coma flotante. Luego, se inicializa en cero la variable que
sumará todos los valores: $total.
El bucle que utilizo es el for. ¿Por qué elegí for? Porque el array tiene justo 20
elementos y este tipo de bucle permite iterar un número fijo de veces. Se comienza el
2. for en 0 porque el primer elemento del arreglo es $ventas_dia[0]. La condición para
seguir adelante las iteraciones será siempre que la variable $i que realiza el conteo sea
menor o igual que la cantidad de elementos del array.
La función count cuenta la cantidad de elementos del array. Pensemos esta parte. $i
debe contar de uno en uno desde 0 hasta 19. No hasta 20. Si $i llega a valer 20
tendremos un error de offset. Por lo tanto, tomamos el total de elementos del array con
la función count, eso nos dará 20 y luego le restamos 1.
Adentro del bucle lo que haremos es acumular los valores de cada elemento del array en
una suma. Usamos el operador += en vez de usar:
?
1$total = $total + $ventas_dia[$i];
Pero es exactamente lo mismo.
Luego, hay que calcular el promedio que es la suma de todos los elementos dividido la
cantidad de elementos. Nuevamente utilizamos count para contar los elementos del
array. Finalmente utilizamos echo para mostrar el resultado por pantalla.
Salida
El promedio de ventas es: 99.646
Ejercicio 2
Dado el siguiente array: $nombres = array
(‘roberto’,’juan’,’marta’,’moria’,’martin’,’jorge’,’miriam’,’nahuel’,’mirta’). Realizar
un programa en PHP que lo recorra y genere un nuevo array con aquellos nombres que
comiencen con la letra m. Definir qué bucle conviene usar y luego mostrar el array por
pantalla sin usar var_dump ni print_r. Los nombres deben aparecer separados por
coma.
Bueno, para los que están siguiendo el curso, admito que hice una trampita: omití
explicar algo que es muy necesario para realizar este ejemplo. Me refiero a determinar
cuál es la primer letra de un string o cadena de caracteres. De todas formas, lo mejor
que pueden hacer cuando no entienden algo es investigar cómo se hace.
Existen muchas maneras de resolver este y todos los ejercicios, pero en este caso voy a
mostrarles dos variantes.
?
1
2
3
4
5
6
7
<?php
// una manera de hacerlo
$nombres = array ('roberto','juan','marta','moria','martin',
'jorge','miriam','nahuel','mirta');
$nombres_con_m = array();
$r = 0;
3. 8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
foreach ($nombres as $nombre) {
if ($nombre[0] == 'm') {
$nombres_con_m[$r] = $nombre;
$r++;
}
}
foreach ($nombres_con_m as $clave=>$valor) {
echo $valor;
if (count($nombres_con_m)-1 != $clave)
echo ', ';
else
echo '.';
}
?>
Definimos el array del enunciado y luego otro que lo dejamos vacío. Para dejar vacío un
array simplemente abrimos y cerramos los paréntesis después de la palabra clave array.
Vamos a contar utilizando un foreach. Primero inicializamos $r, nuestro contador en 0.
Iremos pasando de elemento en elemento con $nombres as $nombre. Recuerden:
$nombres es el nombre del array y $nombre la variable que tomará el valor del
elemento en cada iteración.
Para saber si la primera letra de una variable que tiene cadena de caracteres es una m,
hay que usar la instrucción que se ve en el código. Resulta que los strings son también
arrays y que puede indicarse cada caracter o letra poniendo un número entre corchetes e
indicando la posición del caracter que se desea. Como en este caso se necesita comparar
la primera letra, se pone un 0. El if chequeará que la primera letra del elemento $nombre
sea igual a m. Si lo es, $nombre pasará a ubicarse en el array $nombres_con_m en la
posición que $r lo indique. Luego, se incrementará $r.
Si se fijan, $r se utiliza para ir ubicando en el array nuevo los elementos que se tengan
que pasar. Es importante aclarar que al realizar la operación, los elementos no dejan de
estar en el array original, sino que es más bien una especie de copia. En realidad, son
referencias que se agregan a ese elemento, como si las posiciones de los arrays
apuntaran al mismo elemento.
Toda esa estructura sirve para seleccionar aquellos nombres que comienzan con la letra
m.
El segundo foreach sirve para mostrar por pantalla los resultados. Aquí aprovecho para
mostrar algo adicional que no expliqué en la clase teórica. Se trata de la clave y el valor
usados dentro del foreach. Recuerden de la clase de arrays, que estos estaban formados
por una clave asociada a un valor. Bien, el foreach permite manejar dentro del bucle a
ambos elementos. Recuerden también que en los arrays enumerativos, las claves son
números.
4. Este foreach lo que hará es mostrar los nombres con m. El if que aparece después
chequea si no se llegó al último elemento. Si esto es así, entonces muestra por pantalla
una coma para separar los nombres. Si se llegó al último elemento, en vez de una coma,
muestra un punto. Este if funciona únicamente con arrays enumerativos donde las claves
son números ordenados.
Salida
marta, moria, martin, miriam, mirta.
Veamos otra forma de resolverlo que tiene algunas similitudes
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
// otra manera de hacerlo
$nombres = array ('roberto','juan','marta','moria','martin',
'jorge','miriam','nahuel','mirta');
$nombres_con_m = array();
foreach ($nombres as $nombre) {
if ($nombre[0] == 'm')
$nombres_con_m[] = $nombre;
}
for ($i=0; $i<=count($nombres_con_m)-1; $i++) {
echo $nombres_con_m[$i];
// si es el ultimo paso
if ($i == count($nombres_con_m))
echo '.';
else
echo ', ';
}
?>
El primer foreach tiene una diferencia. En vez de utilizar una variable para contar y
acomodar los nombres que empiezan con m, se agregan los elementos de forma directa
al final del array en la línea:
?
1$nombres_con_m[] = $nombre;
Mucho más sencillo. ¿No creen?
Luego, en vez de un foreach, usamos un for para recorrer el array $nombres_con_m. Al
mostrarlo por pantalla, naturalmente hay que usar el índice $i y también en el chequeo
de si se está en el último elemento.
La salida de este código es exactamente la misma que con la otra variante.
5. Ejercicio 3
Realizar un programa que arme la estructura HTML de una tabla con 20 filas y 10
columnas utilizando dos bucles for. Dentro de las celdas debe ponerse una letra O.
Este ejercicio está bueno para combinar HTML con PHP. Noten que en este curso,
hasta el momento no he hecho mención alguna a la estructura del documento HTML.
Eso lo veremos la siguiente clase. Así que por ahora, no hace falta armar la estructura
conocida de este código de marcas. Sí de la tabla que vamos a generar.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<table>
<?php
for ($i=1; $i<=20; $i++):
?>
<tr>
<?php
for ($s=1; $s<=10; $s++):
?>
<td>O</td>
<?php
endfor;
?>
</tr>
<?php
endfor;
?>
</table>
Por fuera del código PHP van las etiquetas <table></table>. Usaremos dos bucles for
para iterar en cantidades fijas. Un for externo se encargará de repetir las filas y uno
interno se encargará de repetir las columnas. El de afuera se ejecutará 20 veces y el de
adentro 20 veces 10, es decir 20 x 10 que es igual a 200.
Se usa una variable contador $i para el externo y otra variable $s para el interno.
Recuerden que <tr></tr> se usa para definir las filas y que <td></td> son las celdas
propiamente.
Como ven, cuando se trabaja con HTML es más fácil utilizar la sintaxis alternativa de
las sentencias tanto iterativas como selectivas.
El resultado de este código lo pueden ver en la correspondiente salida cuyo enlace está
al principio del artículo.
Ejercicio 4
Dado un array enumerativo de 10 elementos de números enteros (sin coma decimal),
encontrar el máximo de todos esos números usando una estructura iterativa y mostrarlo
por pantalla.
6. Este es el típico ejercicio donde hay que usar un algoritmo para obtener el máximo
elemento de un arreglo.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$numeros = array (10, 2, 3, 14, 15, 1, 7, 9, 8, 11);
$paso = 0;
while ($paso <= count($numeros)-1) {
if ($paso == 0)
$maximo = $numeros[0];
else {
if ($numeros[$paso] > $maximo)
$maximo = $numeros[$paso];
}
$paso++;
}
echo 'El maximo es: '.$maximo;
?>
Definimos el array con los números e inicializamos una variable contadora llamada
$paso ya que opté por un while para poder mostrar su uso. Bien se podría haber
planteado con un for.
El while se ejecutará siempre que la variable contadora $paso tenga un valor menor o
igual al índice que corresponde al último elemento del array, al igual que el bucle for.
Por eso aparece el -1 restando luego del count($numeros).
El algoritmo es bastante simple pero vamos a explicarlo en detalle. En la primera
iteración, cuando $paso vale 0, aún no hay un máximo definido así que por defecto el
primer elemento pasará a ser el máximo. Luego, en el resto de los casos, habrá que
comparar el elemento actual de la iteración con el máximo, si este lo supera, entonces
será el nuevo máximo. Si esto no ocurre, no pasará nada. En cada iteración, como
estamos en un while habrá que alterar el valor de la variable que aparece en la
condición. En este caso, se incrementará $paso.
Al final del while, el valor mas grande del array quedará alojado en la variable
$maximo. Prueben cambiar los valores del array y verán que de todas formas el
algortimo seguirá funcionando.
Salida
El maximo es: 15
Ejercicio 5
Idem anterior pero encontrar el mínimo.
7. El algoritmo es el mismo, pero hay alguna variante. Veámoslo.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$numeros = array (10, 2, 3, 14, 15, 1, 7, 9, 8, 11);
$paso = 0;
while ($paso <= count($numeros)-1) {
if ($paso == 0)
$minimo = $numeros[0];
else {
if ($numeros[$paso] < $minimo)
$minimo = $numeros[$paso];
}
$paso++;
}
echo 'El minimo es: '.$minimo;
?>
Se debe cambiar el signo en la comparación. También cambiamos el nombre de la
variable $maximo por $minimo para que tenga relación con lo que va a almacenar.
¿Esperaban algo más complicado? La clave de este ejercicio es deducirlo analizando el
código del ejercicio anterior.
Salida
El minimo es: 1
Ejercicio 6
Hacer un programa que calcule todos los números primos entre 1 y 50 y los muestre
por pantalla. Un número primo es un número entero que sólo es divisible por 1 y por sí
mismo.
Este ejercicio me encanta y sirve para explicar como funciona la sentencia break y
también permite mostrar de qué forma evitarla.
Tendremos que recorrer todos los números del 1 al 50 y a cada uno de ellos dividirlos
por 1, luego por 2, luego por 3 y así sucesivamente. En cada división hay que verificar
qué ocurre con el resto. Si el resto da cero entonces el número es divisible. Si da distinto
de cero, entonces no es divisible. Es necesario utilizar el operador resto de la división
entera %.
Primero veamos una solución utilizando break
?
1
2
<?php
// resolucion utilizando BREAK
8. 3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
for ($i=1; $i<=50; $i++) {
$div = 2;
$primo = true;
do {
if ($i % $div == 0) {
$primo = false;
break;
}
$div++;
} while($i >= $div*2);
if ($primo == TRUE )
echo $i.' ';
}
?>
El for recorrerá desde el 1 hasta el 50. Es decir que $i será nuestro número a analizar si
es primo o no en cada iteración. $div será la variable que guardará el divisor y que se irá
incrementando. Usaremos un do… while a modo de bucle interno. En esta estructura, se
irá dividiendo a $i por $div todas las veces que sea necesario para probar si es primo o
no.
Recordemos la definición: un número es primo si es divisible por 1 y por sí mismo.
Todos los números son divisibles por 1, por lo tanto no tiene sentido probar la división
por 1, este es el motivo por el cual $div se inicializa en 2. A su vez, todos los números
son divisibles por sí mismos. Es decir que los primos no son divisibles por los que están
entre el 2 y el inmediato número inferior a sí mismos.
$div se irá incrementando en uno y en cada paso se hará el resto de la división entera: $i
% $div. Si da 0, significa que ese número es divisible por otro, entonces no es primo.
Por eso, usamos una variable booleana (con valores TRUE o FALSE) para indicar el
resultado.
El break rompe el bucle do…while cuando encuentra un número que divide a nuestro $i.
¿Por qué lo rompe? Supongamos que $i vale 28, $div empieza valiendo 2, al realizar la
división entera, el resultado es 0. Por lo tanto, 28 no es primo. ¿Tiene sentido seguir
incrementando $div y seguir dividiendo si ya sabemos que el número no es primo? No.
Por lo tanto, es toda una tentación utilizar break para interrumpir el ciclo.
Ese sería el caso en el que el número a analizar no es primo. Pero veamos qué ocurre
cuando sí lo es. La variable $primo arranca en TRUE en cada iteración del for. Dentro
del do… while será dividida por $div. Supongamos que $i vale 11. Sabemos que no es
divisible por 2, ni por 3, ni por 4 ni por 5. El valor de $primo no se alterará en ningún
momento y al finalizar el while seguirá siendo TRUE. Por lo tanto, como ven, luego del
while aparece un if donde se verifica el valor de $primo y en caso de ser verdadero, se
muestra el número $i por pantalla.
Ahora analicemos la condición de corte del while, que es lo más difícil de todo. El while
debe repetirse siempre que el valor de nuestro número $i sea igual o más grande que el
9. de $div por dos. Esto se entenderá mejor con un ejemplo. Supongamos que nuestro $i
vale 41. Debemos dividirlo por 1, 2, 3, 4, etc. Pero cuando lleguemos a la mitad
aproximadamente, es decir, 20 estaremos en el último posible divisor. ¿Por qué? Porque
si seguimos dividiendo usando como divisores los números que vienen después de la
mitad el resultado nunca podrá ser entero.
Ahora veamos como evitar ese break.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// resolucion sin utilizar break
for ($i=1; $i<=50; $i++) {
$div = 2;
$primo = true;
do {
if ($i % $div == 0)
$primo = false;
$div++;
} while(($i >= $div*2) && ($primo == TRUE));
if ($primo == TRUE )
echo $i.' ';
}
Se incluye la variable $primo dentro de la condición del while. De esta forma, cuando
ya sepamos que el número no es el que buscamos, la variable $primo se pondrá en
FALSE y para que el while se vuelva a repetir es condición necesaria lo que expliqué
recién del valor de $i y de su divisor $div pero también que el valor de $primo sea
TRUE. El AND (&&) exige que ambas condiciones se cumplan al mismo tiempo para
continuar repitiendo el while.
La salida de ambos códigos es:
1 3 5 7 11 13 17 19 23 29 31 37 41 43 47
Y hasta acá hemos llegado. Si encuentran más ejercicios para hacer practiquen porque a
programar se aprende escribiendo código frente a la pantalla pasando horas y horas.
Espero que estas clases les sean de ayuda.
¡Hasta la próxima!