Ordenar Array Dinámico con Groovy
Este pequeño programa de apenas 59 líneas de código nos permite ordenar un array dinámico de mayor a menor o de menor a mayor, según la opción seleccionada por el usuario. Un array dinámico básicamente es un contenedor de elementos no ordenados de un solo tipo con un tamaño flexible, puede incrementarse o reducirse en tiempo de ejecución cuando se agregan elementos o se eliminan.
Código fuente
def input = new Scanner(System.in) def listNums = [] def tmp = 0 def ordenarMayor(listNum, cant) { (0..cant - 1).each { x -> (0..cant - 1).each { y -> if(listNum[x] > listNum[y]) { tmp = listNum[x] listNum[x] = listNum[y] listNum[y] = tmp } } } println("Array ordenado: ${listNum}") } def ordenarMenor(listNum, cant) { (0..cant - 1).each { x -> (0..cant - 1).each { y -> if(listNum[x] < listNum[y]) { tmp = listNum[y] listNum[y] = listNum[x] listNum[x] = tmp } } } println("Array ordenado: ${listNum}") } print("Ingrese en el numero de valores a ordenar: ") def val = input.nextInt() (1..val).each { print("Ingrese el elemento #$it: ") item = input.nextInt() listNums << item } println(""" Selecciones una de las siguientes opciones: ------------------------------------------- 1) Ordenar de mayor a menor 2) Ordenar de menor a mayor -------------------------------------------""") print("Selecciones una opcion: ") def opt = input.nextInt() switch (opt) { case 1: ordenarMayor(listNums, val) break case 2: ordenarMenor(listNums, val) break default: println("No valido!") }
Groovy en un lenguaje de tipado Mixto, es decir, de tipado dinamico y estatico, con su sintaxis limpia que se inspira en Python. Al ser un lenguaje Mixto nos permite combinar declaraciones de variables estáticas como ocurre en la primera línea o dinámicas como ocurre en la segunda línea. Otro detalle a resaltar es la ausencia de import java.util.Scanner y es porque Groovy importa por defecto varios paquetes y clases, como lo es el paquete java.util.*, el cual contiene a la clase Scanner. Este programa fue escrito solo con tipado dinámico.
Creando objeto Scanner()
def input = new Scanner(System.in)
Lo primero es crear un objeto Scanner() que nos permite leer datos ingresados por el usuario, esto se logra usando la palabra reservada new seguida por la clase Scanner(), cuyo único argumento es System.in.
Creando Array Dinámico
def listNums = []
Bien, en esta línea creamos un array dinámico vacío. Así de sencillo se crea un array en Groovy, solo basta con definir la variable con la palabra clave def seguida del nombre de la variable y por último un par de corchetes “[]” vacíos, esto sera compilado como un objeto ArrayList<int>. Esto le puede sonar familiar a los programadores en Python.
Creando variable tmp
def tmp = 0
Esta variable solo juega el papel de auxiliar en el proceso para ordenar los elementos del array, sosteniendo los valores individuales para luego devolverlos al mismo array pero en una posición diferente.
Función ordenarMayor()
def ordenarMayor(listNum, cant) { (0..cant - 1).each { x -> (0..cant - 1).each { y -> if(listNum[x] > listNum[y]) { tmp = listNum[x] listNum[x] = listNum[y] listNum[y] = tmp } } } println("Array ordenado: ${listNum}") }
La función ordenarMayor() toma el array y ordena sus elementos de mayor a menor. Recibe dos argumentos, el primero es el array que deseamos ordenar y el segundo es la cantidad de elementos en el array. Cuando creamos funciones en Groovy podemos omitir el tipo de datos de los argumentos, recuerde que el programa está escrito en tipado dinámico. Esto le puede sonar familiar a los programadores en Python.
Closure .each {}, iterando sobre un rango
(0..cant - 1).each { x -> (0..cant - 1).each { y -> if(listNum[x] > listNum[y]) { tmp = listNum[x] listNum[x] = listNum[y] listNum[y] = tmp } } }
La Closure .each {} es un iterador de Groovy, ambos van a iterar sobre un rango desde 0 hasta cant – 1. El bucle externo va a iterar una vez por cada elemento del array en la posición x; mientras que el bucle interno va a iterar desde 0 hasta N – 1 por cada elemento en la posición x; por ejemplo, si hay 5 elemento en el array, el bucle interno va a iterar 5 veces por cada elemento elemento en el índice x, para un total de 25 iteraciones.
Sentencia if(), ordenando el array dinámico
if(listNum[x] > listNum[y]) { tmp = listNum[x] listNum[x] = listNum[y] listNum[y] = tmp }
Esta sentencia if va a evaluar si cada uno de los elementos del array ubicado en el índice x es mayor a los elementos del array ubicado en el índice y, por eso el bucle interno va a iterar N cantidad de veces por cada elemento en el índice x (como se explicó anteriormente) con la intención de evaluar si es mayor al elemento en el índice y. Si la condición es true, se realizan una serie de asignaciones que se explican a continuación:
* tmp = listNum[x]
: el elemento en el índice x es asignado a la variable tmp.
* listNum[x] = listNum[y]
: el elemento ubicado en el índice y es asignado asignado en el índice x.
* listNum[y] = tmp
: el elemento que había sido asignado a la variable tmp es asignado en el índice y.
Este pequeño proceso cambia de posición a los elementos, moviendo de índices a cada uno, para dejar a los números mayores al principio del array y dejado de últimas a los números menores.
Imprimiendo array ordenado
println("Array ordenado: ${listNum}")
Por último imprimimos en pantalla el array ordenado con la función println(), la expresión ${listNum} se le llama interpolación de strings y consiste en reemplazar la expresión entre llaves “{}” por el contenido en ella.
La lista se imprime de la siguiente forma: [2017, 2007, 1991, 1983, 1810].
Función ordenarMenor()
def ordenarMenor(listNum, cant) { (0..cant - 1).each { x -> (0..cant - 1).each { y -> if(listNum[x] < listNum[y]) { tmp = listNum[y] listNum[y] = listNum[x] listNum[x] = tmp } } } println("Array ordenado: ${listNum}") }
Esta función tiene exactamente la misma estructura que la función ordenarMayor() y de hecho funciona de la misma forma, solo hay un par de diferencias entre ambas que se encuentra en la sentencia if:
* La sentencia if() de la función ordenarMayor() evalúa si los elementos ubicados en el índice x son mayores que los elementos ubicados en el índice y; mientras que en la función ordenarMenor() se evalúa si los elementos en el índice x son menores que los elementos en el índice y.
* En la función ordenarMayor() la variable tmp toma el valor que hay en el índice x del array; mientra que en la función ordenarMenor() la variable tmp toma el valor que hay en el índice y.
* En la función ordenarMayor() el índice x del array toma el valor del índice y del array; mientras que en la función ordenarMenor() el índice y toma el valor del índice x.
* En la función ordenarMayor() el índice y del array toma el valor de la variable tmp; mientras que en la función ordenarMenor() el índice x toma el valor de la variable tmp.
Solicitando cantidad y leyendo el valor
print("Ingrese en el numero de valores a ordenar: ") def val = input.nextInt()
Primero mostramos un mensaje al usuario con la función print() solicitando que ingrese el número de valores a ordenar y después leemos el dato con el objeto input creado al principio, llamando al método .nextInt() para leer números enteros y lo asignamos a la variable val.
Iterando y agregando elementos al array
(1..val).each { print("Ingrese el elemento #$it: ") item = input.nextInt() listNums << item }
Con la Closure .each {} iteramos sobre un rango que va desde 1 hasta val, la función print() solo imprime un mensaje informando al usuario que ingrese un valor junto con el número de valores que se va ingresando con la expresión $it; por ejemplo, “Ingrese el elemento #3”. Leemos el dato con el objeto input creado al principio, llamando al método .nextInt() para leer números enteros y lo asignamos a la variable item. Por último vamos agregando cada valor al array usando el operador de inserción “<<“ seguido por el valor.
Seleccionando opción y mostrando resultado
println(""" Selecciones una de las siguientes opciones: ------------------------------------------- 1) Ordenar de mayor a menor 2) Ordenar de menor a mayor -------------------------------------------""") print("Selecciones una opcion: ") def opt = input.nextInt() switch (opt) { case 1: ordenarMayor(listNums, val) break case 2: ordenarMenor(listNums, val) break default: println("No valido!") }
La función print() solo nos muestra algo como esto:
Selecciones una de las siguientes opciones ------------------------------------------ 1) Ordenar de mayor a menor 2) Ordenar de menor a mayor ------------------------------------------
Un pequeño menú que le indica al usuario que seleccione alguna de las dos opciones presentes, ingresar el número 1 si desea ordenar el array de mayor a menor o el número 2 si lo desea ordenar de menor a mayor.
Leyendo opción seleccionada
print("Seleccione una opcion: ") def opt = input.nextInt()
Mostramos un mensaje al usuario con la función print() solicitando que escoja una opción, luego leemos el valor con el objeto input creado al principio, llamando al método .nextInt() para leer números enteros y lo asignamos a la variable opt.
La sentencia switch toma la variable opt y evalúa la opción que el usuario escogió y dependiendo de esto entonces llama a la función ordenarMayor() u ordenarMenor() que recibe 2 parametros, el primero es el array dinámico y el segundo es la cantidad de elementos que posee dicho array.
Ejecutando nuestro programa
Al ejecutar este pequeño programa nos da un resultado similar al siguiente:
[fixedtorres@linuxero]$ groovy OrdenarArrayDinamico.groovy Ingrese en el numero de valores a ordenar: 5 Ingrese el elemento #1: 1983 Ingrese el elemento #2: 2017 Ingrese el elemento #3: 1991 Ingrese el elemento #4: 1810 Ingrese el elemento #5: 2007 Selecciones una de las siguientes opciones: ------------------------------------------- 1) Ordenar de mayor a menor 2) Ordenar de menor a mayor ------------------------------------------- Selecciones una opcion: 1 Array ordenado: [2017, 2007, 1991, 1983, 1810] [fixedtorres@linuxero]$
Un array ordenado de menor a mayor si seleccionamos la opción #1.