Arreglos

Objetivos: Presentar los arreglos como objetos útiles para manejar datos.

Temas:


Motivación:

Se ha hecho una elección en la que participaron 8 candidatos. Cada candidato se identifica por un número entre 0 y 7. El resultado de la elección se encuentra en un archivo ``votos.txt'' que contiene una línea por cada sufragante. Esta línea indica el número del candidato que prefiere ese sufragante. Por ejemplo el contenido del archivo podría ser:

    3
    7
    1
    3
    1
En el archivo se observa que el candidato número 3 tiene 2 votos, al igual que el número 1 y que el candidato 7 tiene 1 voto.

Construir un programa que haga el recuento de los votos. El resultado de este programa debe ser:

    Candidato 0: x votos
    Candidato 1: y votos
    ...
    Candidato 7: z votos
Soluciones:


Un arreglo es un objeto que permite asociar valores a números enteros. Para entender este concepto, es conveniente visualizar un arreglo como una tabla con dos columnas:

Indice Valor
0 2
1 4
2 15
3 0
4 10
5 22
6 0
7 1

La columna de la izquierda contiene los índices y la columna de la derecha el valor asociado a cada índice. El ejemplo de más arriba podría ser la cantidad de votos captados por cada candidato. El número del candidato corresponde al índice y la cantidad de votos es el valor asociado.

Los arreglos son objetos que realizan principales dos operaciones: (i) obtener el valor asociado a un índice, y (ii) cambiar el valor asociado a un índice. Con estas operaciones es sencillo resolver el problema del recuento de los votos:

  TextReader lect= new TextReader("votos.txt");

  Array tab= new Array(8); // Crea un arreglo asociativo

  // Crear las filas del arreglo asociativo
  // El valor inicial asociado a cada candidato es 0
  int cand= 0;
  while (cand<=7) {
    tab.put(cand, 0); // Asocia 0 al candidato cand
    cand= cand+1;
  }

  // Leer los votos
  while(true) {
    int candVoto= lect.readInt();
    if (lect.eofReached())
      break;
    // Obtenemos el numero de votos del candidato
    int anterior= tab.getInt(candVoto); 
    int nuevo= anterior+1;
    tab.put(candVoto, nuevo); // Cambiar el valor asociado
  }

  cand= 0;
  while (cand<=7) {
    println("Candidato "+cand+": "+tab.getInt(cand));
    cand= cand+1;
  }

  lect.close();
(Ver el programa completo en Votos.java.)

Observaciones:


Arreglos con valores no enteros

El valor asociado a un índice puede ser un valor real. Por ejemplo, podemos asociar a cada candidato su estatura:

    Array tabEst= new Array(10);
    tabEst.put(0, 1.70);
    tabEst.put(1, 1.85);
    ...
    println("La estatura del candidato 3 es "+
            tabEst.getDouble(3));
También podemos asociar a cada candidato su nombre:

    Array tabNombres= new Array(10);
    tabNombres.put(0, "Ronald Reagan");
    tabNombres.put(1, "Margaret Tatcher");
    ...
    println("El candidato 5 es "+tabNombres.getString(5));

Ejercicio 1: (propuesto)

El archivo ``est.txt'' contiene los nombres de cada candidato en el siguiente formato:

    2 Margaret Tatcher
    7 Boris Yeltsin
    ...
    0 Ronald Reagan
El primer campo (columnas 0 a 1) indica el número del candidato y el segundo el nombre del candidato (columnas 2 en adelante). Los candidatos vienen en cualquier orden en el archivo. Escriba un programa que lea el archivo ``est.txt'' y construya un arreglo que asocie el número del candidato (el índice) con su nombre. Luego, el programa debe entablar el siguiente diálogo con el usuario:

    Número de candidato ? 7
    Su nombre es Boris Yeltsin
    Número de candidato ? 0
    Su nombre es Ronald Reagan
    Número de candidato ? x
    Su nombre es ...
    ...
    Número de candidato ? -1
    fin

Resumen:

Operaciones para manejar arreglos

Ejemplo Significado Resultado
Array tab= new Array(8); Crea un arreglo de 8 elementos con índices del 0 al 7 Un arreglo de 8 elementos
tab.put(3, 200); Asocia el valor entero 200 al índice 3 no tiene
tab.put(5, 3.14); Asocia el valor real 3.14 al índice 5 no tiene
tab.put(0, "hola"); Asocia el string "hola" al índice 0 no tiene
tab.put(7, true); Asocia el valor true al índice 7 no tiene
int n= tab.getInt(3); Obtiene el entero asociado al índice 3 200
double x= tab.getDouble(5); Obtiene el real asociado al índice 5 3.14
String s= tab.getString(0); Obtiene el string asociado al índice 0 "hola"
boolean b= tab.getBoolean(7); Obtiene el valor booleano asociado al índice 7 true

Los valores en un arreglo pueden ser cualesquiera entre enteros, reales, strings o booleanos. ¡Pero cuidado! Al obtener su valor, el tipo del valor asociado debe coincidir con el tipo pedido. Es decir, previamente se debe haber invocado tab.put(k, v) en donde v era del tipo pedido.

Por otra parte, en un arreglo construido con Array, los índices siempre deben ser de tipo entero (La clase StringMap es un arreglo que acepta índices de tipo String).

Ejercicio 2:

Escribir un programa que lea las líneas del archivo ``datos.txt'' y las muestre en la consola en orden inverso. Por ejemplo, si el contenido de ``datos.txt'' es:

    Un arreglo asociativo o mapa es un
    objeto que permite asociar valores
    a números enteros o strings.
el programa debe mostrar en la pantalla:

    a números enteros o strings.
    objeto que permite asociar valores
    Un arreglo asociativo o mapa es un
Solución:

La idea es construir un arreglo que asocie cada línea con su número de línea en el archivo (comenzando de 0). El problema es que al crear el arreglo se necesita saber a priori cuantas líneas tiene el archivo, lo que no es posible determinar sin leer completamente una vez el archivo.

Supuesto razonable: el archivo no tiene más de 1000 líneas (en realidad este supuesto no es tan razonable, pero típicamente en los controles se le dice explícitamente cuál es el tamaño máximo del archivo).

    Array tab= new Array(1000);
    TextReader lect= new TextReader("datos.txt");
    int i= 0;
    while (true) {
      String lin= lect.readLine();
      if (lect.eofReached())
        break;
      tab.put(i, lin);
      i= i+1;
    }
    lect.close();
    // i es el número de líneas del archivo
    i= i-1;
    while (i>=0) {
      println(tab.getString(i));
      i= i-1;
    }
(Ver el programa completo en Invierte.java.)

Observaciones:


Patrones de recorrido de arreglos

Típicamente, los arreglos asociativos poseerán llaves en un rango de enteros conocidos. Por ejemplo entre 0 y n-1 o 1 y n. Para manipular estos arreglos se usan los siguientes patrones:


Ejercicio 3

El archivo ``notas.txt'' contiene las notas de un control en un curso de estadísticas. El formato del archivo es el siguiente:

    Gloria Hernandez    6.0
    Juan Perez          5.5
    Jose Urrutia        5.8
    etc.
El primer campo es el nombre del alumno y el segundo es su nota en el control. El nombre se encuentra entre las columnas 0 y 19 y la nota entre la 20 y 22. Escriba un programa que lea una sola vez el archivo ``notas.txt'' y despliegue en pantalla los nombres de las personas que obtuvieron la mejor nota.

Solución:

Solución:

    // Creación de arreglos
    Array tabNombres= new Array(1000);
    Array tabNotas= new Array(1000);
    // Inicialización de los arreglos y cálculo
    // de la mejor nota
    TextReader lect= new TextReader("notas.txt");
    int i= 0;
    double maxNota= 0.0;
    while (true) {
      String lin= lect.readLine();
      if (lect.eofReached()) // Patrón de lectura de datos
        break;
      String nom= trim(substring(lin, 0, 20));
      double nota= parseDouble(trim(substring(lin, 20, 3)));
      // Patrón de inicialización de arreglos
      tabNombres.put(i, nom);
      tabNotas.put(i, nota);
      if (nota>maxNota)
        maxNota= nota;
      i= i+1; // Patrón de conteo para el nro. de línea
    }
    lect.close();
    // i es el número de líneas leídas
    // Determinar nombres de los que obtuvieron la mejor nota.
    int j=0;
    while (j<i) {
      if (tabNotas.getDouble(j)==maxNota)
        println(tabNombres.getString(j));
      j= j+1;
    }
(Ver el programa completo en Mejores.java.)


Ejercicio 4: (propuesto)

Modifique el programa anterior de modo que muestre en pantalla junto a los nombres de las personas que obtuvieron la mejor nota, los nombres de las personas que obtuvieron la segunda mejor nota. En pantalla se debe mostrar el siguiente resultado:

    La mejor nota fue un 6.5
    Los alumnos fueron:
    Mariano Benitez
    Adriana Gonzalez

    La segunda mejor nota fue un 6.2
    Los alumnos fueron:
    Andres Concha
Ejercicio 5: (propuesto)

Escriba un programa que lea el archivo de notas y muestre en pantalla la siguiente información:

    Nota  Nro. de alumnos
    6.5   2
    6.2   1
    5.9   4
    ...
    2.6   1
Su programa debe indicar cuántos alumnos obtuvieron cada nota presente en el control, partiendo por la mejor nota y terminando por la peor nota.

Hint: cree un arreglo con 70 elementos. Utilice como índice la nota multiplicada por 10 y truncada a número entero (con trunc).