domingo, 2 de marzo de 2014

Práctica contadora de palabras

Buenas gente, se va a crear una aplicación para contar el número de veces que aparece cada palabra en un texto dado. Para ello se crearán las clases PalabraEnTexto, ContadorPalabras, ContadorPalabrasSig y Main.


Como siempre, tenéis acceso a las clases y al enunciado así como al fichero de prueba directamente para descargar (a mi me hacéis un favor :p)


a) La clase PalabraEnTexto mantiene información de una palabra (String) así como del número de veces que aparece en un determinado texto (int).

1. La clase tendrá un constructor en el que se proporciona la palabra. Al construir el objeto, el número de veces que aparece la palabra se considera 1.  
2. Dos objetos de la clase PalabraEnTexto son iguales si coinciden las palabras que contiene, independientemente de que estén en mayúsculas o minúsculas. El número de apariciones no se tiene en cuenta.  
3. La representación de un objeto PalabraEnTexto debe mostrar la palabra que contiene y el número de veces que aparece.   

4. El método void incrementa() incrementa en uno el número de veces que aparece la palabra.



b) Crear la clase ContadorPalabras que almacena en un array las palabras que aparecen en un texto (array de PalabraEnTexto). Si en el transcurso de las operaciones que se hagan con objetos de esta clase, el array llega a tener un tamaño insuficiente, deberá crecer de manera que siempre quepan las palabras que se le proporcionen.
 1. La clase dispondrá de dos constructores; el primero de ellos, sin argumentos, que crea el array con un tamaño de 10; el segundo, con un argumento entero, que indicará el tamaño inicial del array. 
2. El método privado int esta(String pal) que devuelve la posición en la que se encuentra la palabra que corresponde a pal en el array o -­‐1 si no está.   
3. El método void incluye(String pal) deberá incrementar el número de apariciones de la palabra que corresponda a la cadena pal en el contador de palabras si es que ya existía, o incluir una palabra nueva en caso contrario.   
4. El método void incluyeTodas(String linea, String del) permite extraer de linea las palabras usando los delimitadores incluidos en del. Cada una de las palabras obtenidas se irán acumulando en el contador.   
5. El método void incluyeTodas(String [] texto, String del) incluye todas las palabras que se encuentra en el array texto. Cada elemento del array será una línea de texto y en cada línea, las palabras se deben separar usando los delimitadores incluidos en del.   
6. Crear el método PalabraEnTexto encuentra(String pal) que, dada una cadena de caracteres pal que representa una palabra, encuentra la instancia de PalabraEnTexto en el array que coincide con ella y la devuelve. Si la palabra no se encuentra en el texto deberá lanzar la excepción NoSuchElementException.   
7. La clase dispondrá de una representación de los objetos como la que se muestra en el ejemplo final. Usar StringBuilder para crear la representación, y obsérvese que, tras la última palabra, no hay coma).


c) La clase ContadorPalabrasSig representa objetos contadores de palabras que, en los procedimientos de inclusión, no contempla las palabras consideradas no significativas. Para ello, la clase deberá incluir un array de String que almacene estas palabras no significativas.
 1. Definir constructores apropiados, que incluyan un argumento para proporcionar el array de palabras no significativas. Supóngase que las palabras de este array están todas en mayúsculas. 
 2. Conseguir que las instancias de la clase ContadorPalabrasSig se comporten como las de ContadorPalabras, a excepción de que los procedimientos de inclusión de palabras no realicen ninguna acción cuando éstas no sean significativas. Aquí se presenta un ejemplo de uso de estas clases y la salida correspondiente.


Aquí teneis el test:
import java.util.NoSuchElementException;
public class Main {
 public static void main(String [] args) {
  String [] datos = {
    "Guerra tenía una jarra y Parra tenía una perra, ",
    "pero la perra de Parra rompió la jarra de Guerra.",
    "Guerra pegó con la porra a la perra de Parra. ",
    "¡Oiga usted buen hombre de Parra! ",
    "Por qué ha pegado con la porra a la perra de Parra.",
    "Porque si la perra de Parra no hubiera roto la jarra de Guerra,",
  "Guerra no hubiera pegado con la porra a la perra de Parra."};
  // Quitar el comentario según se use Scanner o StringTokenizer
   String delimitadores = "[ .,:;\\-\\!\\¡\\¿\\?]+"; // Para Scanner
  // String delimitadores = " .,:;-!¡¿?"; // Para StringTokenizer
  String [] noSig = {"CON", "LA", "A", "DE", "NO", "SI", "Y", "UNA"};
  ContadorPalabras contador = null, contadorSig = null;
  // Si no se incluye un argumento numérico, se crea por defecto.
  try {
   int n = Integer.parseInt(args[0]);
   System.out.println("Con argumento " + n);
   contador = new ContadorPalabras(n);
   contadorSig = new ContadorPalabrasSig(n, noSig);
  } catch (RuntimeException e) {
   System.out.println("Por defecto...");
   contador = new ContadorPalabras();
   contadorSig = new ContadorPalabrasSig(noSig);
  }
//  Incluimos todas las palabras que hay en datos
//  teniendo en cuenta los delimitadores
  contador.incluyeTodas(datos, delimitadores);
  contadorSig.incluyeTodas(datos, delimitadores);
  System.out.println(contador + "\n");
  System.out.println(contadorSig + "\n");
  try {
   System.out.println(contador.encuentra("parra"));
   System.out.println(contador.encuentra("Gorra"));
  } catch (NoSuchElementException e) {
   System.err.println(e.getMessage());
  }
 }
}

Y aquí los resultados:

Por defecto...
[GUERRA: 5, TENÍA: 2, UNA: 2, JARRA: 3, Y: 1, PARRA: 7, PERRA: 6, PERO: 1, LA: 10, DE: 8, ROMPIÓ: 1, PEGÓ: 1, CON: 3, PORRA: 3, A: 3, OIGA: 1, USTED: 1, BUEN: 1, HOMBRE: 1, POR: 1, QUÉ: 1, HA: 1, PEGADO: 2, PORQUE: 1, SI: 1, NO: 2, HUBIERA: 2, ROTO: 1]

[GUERRA: 5, TENÍA: 2, JARRA: 3, PARRA: 7, PERRA: 6, PERO: 1, ROMPIÓ: 1, PEGÓ: 1, PORRA: 3, OIGA: 1, USTED: 1, BUEN: 1, HOMBRE: 1, POR: 1, QUÉ: 1, HA: 1, PEGADO: 2, PORQUE: 1, HUBIERA: 2, ROTO: 1]

PARRA: 7
No se encuentra la palabra

Y ahora os dejo con las respuestas: Primero la clase PalabraEnTexto:
public class PalabraEnTexto {
 private String palabra;
 private int contador;
 
 public PalabraEnTexto(String w){
  palabra = w.toUpperCase();
  contador = 0;
 }
 
 public void incrementa() {
  contador++;
 }
 
 protected String getString() {
  return palabra;
 }
 
 public boolean equals(Object o) {
  return palabra.toLowerCase().equals( ((PalabraEnTexto)o).getString().toLowerCase() );
 }
 
 public String toString() {
  return palabra + ": " + contador;
 }
}
Ahora la clase ContadorPalabras
public class ContadorPalabras {
 private PalabraEnTexto[] array;
 private int ultimo;
 
 public ContadorPalabras() {
  array  = new PalabraEnTexto[10];
  ultimo = 0;
 }
 public ContadorPalabras(int n) {
  array  = new PalabraEnTexto[n];
  ultimo = 0;
 }
 
 private int esta(String pal) {
  int i = -1;
  for (int j = 0; j <= ultimo; j++) {
   if(array[j] != null && pal.toUpperCase().equals(array[j].getString())) i = j;
  }
  return i;
 }
 
 public void incluye(String pal) {
  int aux = esta(pal);
  if(aux==-1 ) {
   array[ultimo] = new PalabraEnTexto(pal);
   array[ultimo].incrementa();
   ultimo++;
   if(ultimo >= array.length-2) redimensionar();
  }
  else {
   array[aux].incrementa();
  }
 }
 
 private void redimensionar() {
  PalabraEnTexto[] auxiliar = new PalabraEnTexto[array.length*2];
  for(int i = 0; i <= ultimo; i++) {
   auxiliar[i] = array[i];
  }

  array = auxiliar;
 }
 
 public void incluyeTodas(String linea, String del) {
  Scanner sc = new Scanner(linea);
  sc.useDelimiter(del);
  
  while(sc.hasNext()) {
   incluye(sc.next());
  }
 }
 public void incluyeTodas(String [] texto, String del) {
  for(String std : texto) {
   incluyeTodas(std, del);
  }
 }

 public PalabraEnTexto encuentra(String pal) {
  int x = esta(pal);
  if (x != -1)  return array[x];
  else throw new NoSuchElementException("No se encuentra la palabra");
 }
 
 StringBuilder st = new StringBuilder("[");
 
 
 public String toString () {
Y ya por último la clase ContadorPalabrasSig
public class ContadorPalabrasSig extends ContadorPalabras{
 private String [] noSig;
 
 public ContadorPalabrasSig(String[] st) {
  super();
  noSig = st.clone();
 }
 public ContadorPalabrasSig(int n, String[] st) {
  super(n);
  noSig = st.clone();
 }
 
 public void incluye(String pal) {
  int i = -1;
  boolean esSig = true;
  for (int j = 0; j< noSig.length; j++) {
   if(pal.equalsIgnoreCase(noSig[j])) {
    esSig = false;
   }
  }
  if(esSig == true) {
   super.incluye(pal);    
  }
  
 }
}

No hay comentarios:

Publicar un comentario