Curso de PHP – Clase 5 – Resolución de ejercicios propuestos

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.

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 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:

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

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.

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.

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

Veamos otra forma de resolverlo que tiene algunas similitudes

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:

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.

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.

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.

Este es el típico ejercicio donde hay que usar un algoritmo para obtener el máximo elemento de un arreglo.

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

Ejercicio 5

Idem anterior pero encontrar el mínimo.

El algoritmo es el mismo, pero hay alguna variante. Veámoslo.

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

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

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 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.

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:

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!

Soy programador web y me desempeño como Líder Técnico y de Proyectos en Polar Bear Development. Trabajo con tecnologías como PHP, Javascript, MySQL y HTML5 para el desarrollo de sitios y sistemas web. Me especializo en Zend Framework 2 y otros frameworks MVC, como también en WordPress y otros CMS. Lidero equipos de desarrolladores trabajando con Scrum. Vivo en Buenos Aires, Argentina.
 

4 thoughts on “Curso de PHP – Clase 5 – Resolución de ejercicios propuestos

  1. El curso consiste en esta serie de artículos que voy publicando. Es gratuito y abierto para todo el mundo. En este enlace están todas las clases publicadas hasta ahora.

    Saludos

  2. Tengo un problema con foreach y me preguntaba si podías aclarármelo. Este es el siguiente:
    $tipos es un array que incluye clases de establecimiento. Y lo que intento es filtrar la consulta por tipos que paso a la variable $tipos.
    Cuando hago la consulta:
    foreach($tipos as $check) {
    $result = mysql_query(“select id_cliente, nombre, tipo, precio, icono1, localidad FROM restauracion WHERE tipo = ‘$check'”);
    }

    if (mysql_num_rows($result) > 0) {

    Hace el bucle, pero va pisando los valores y solo da el último del array $tipos. Me ayudaría mucho que me orientaras, pues llevo dándole vueltas un buen tiempo y no doy con ello.
    Gracias de antemano.

  3. Hola Joaquin

    Hay varias cosas que están mal en el código. En primer lugar, introducir una consulta en un bucle no es una buena práctica. Afecta mucho la performance del programa.
    Lo que te está pasando puntualmente en ese código es que la variable $result se está pisando en cada iteración del foreach. Es por eso que al salir del bucle, en la siguiente línea, tengas el último valor de $result.
    Lo que te recomendaría que hagas es que hagas una única consulta a la base de datos, y que te traiga todo aquello que necesites lo más ordenado posible. Luego, si es necesario separar algunas partes que aún faltan, podrías hacer un procesamiento secuencial. Esto significa que recorras los resultados y los pases ordenados a otro tipo de estructura. La idea aquí también es que este recorrido lo hagas una única vez, para no afectar la performance del programa.

    Espero haberte orientado.
    Saludos

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

*