Mostrando entradas con la etiqueta práctica. Mostrar todas las entradas
Mostrando entradas con la etiqueta práctica. Mostrar todas las entradas

miércoles, 16 de abril de 2014

Práctica prKWIC de Java

Buenas gente, por aquí estoy yo de nuevo. Se que vosotros quereis leer a Cris, pero ahora está en su pueblo y Blogger aún no permite publicar vía telegrama ni paloma mensajera.

Hoy os traigo la que, según creo, es la última práctica de Programación Orientada a Objetos de Primer año. De todos modos, si se me olvida alguna o hay alguna nueva siempre podéis avisarme y pasarme el enunciado ;)
Como siempre os dejo aquí linkeados el enunciado y la clase test.
Bueno, aquí voy con el enunciado:
El objetivo de esta práctica es realizar un glosario o índice de palabras atendiendo a su aparición en un conjunto de frases (KeyWord In Context, KWIC). La idea es analizar una colección de frases, extraer las distintas palabras que aparecen y construir una estructura que establezca una correspondencia entre cada palabra y el conjunto de frases en las que aparece. Para esta práctica será necesario repasar las clases String, StringBuilder y StringTokenizer, así como las clases correspondientes al marco de colecciones de java.
En concreto, se pide: 
a) Definir una clase Titulo que dé envoltura a una frase o título (de tipo String), y que permita
ordenar y comparar frases independientemente de si éstas contienen caracteres en minúsculas o
mayúsculas, así como un método String replace(String pal) para producir una cadena, a
partir del título, con las apariciones de la palabra pal sustituidas por "...". 
b) Definir una clase Indice que mantenga la información relativa a los caracteres separadores que se pueden presentar en los títulos y el índice (palabra -> conjunto de títulos en los que aparece) correspondiente a una colección de objetos de la clase Titulo. Esta clase tendrá:
- i. Dos constructores: uno con un argumento de tipo String con la relación de caracteres
separadores y otro con dos argumentos, uno de tipo String (como el anterior) y otro del
tipo Collection<String> con una relación de frases que habrá que analizar para
construir el correspondiente índice.
- ii. Un método void agregarTitulo(String t) para agregar un título al índice y otro
void agregarTitulo(Collection<String> ct) para agregar una colección de
títulos.
- iii. Un método String presentaIndice() que genere una presentación del índice de
forma que, cuando se imprima, quede como aparece en la salida del programa siguiente: 
Para las frases de entrada
“La rosa púrpura del Cairo”
“La rosa del azafrán”
“El color púrpura”
Salida:
AZAFRÁN
              La rosa del ...
CAIRO
              La rosa púrpura del ...
COLOR
              El ... púrpura
DEL
               La rosa ... azafrán
               La rosa púrpura ... Cairo
EL
               ... color púrpura
LA
               ... rosa del azafrán
               ... rosa púrpura del Cairo
PÚRPURA
               El color ...
               La rosa ... del Cairo
ROSA
               La ... del azafrán
               La ... púrpura del Cairo

c) Definir otra clase IndiceSignificativas, parecida a la clase Indice, que mantenga además
un conjunto de palabras que se consideran no significativas (artículos, preposiciones, conjunciones, …) y que ofrezca los mismos servicios con una diferencia de comportamiento en cuanto a las palabras que mantiene en el índice: sólo mantendrá las palabras significativas que aparezcan en los títulos. En concreto, esta clase tendrá dos constructores: uno con dos argumentos, el primero de tipo String con la relación de caracteres separadores y el segundo de tipo Collection<String> con una relación de palabras no significativas, y otro constructor con tres argumentos, el primero de tipo String con la relación de caracteres separadores, el segundo de tipo Collection<String> con una relación de frases que habrá que analizar para construir el correspondiente índice y el tercero de tipo Collection<String> con una relación de palabras no significativas.  
En este caso el método presentaIndice() generará una presentación del índice que,
cuando se imprima, quedará como aparece en la salida del programa siguiente: 
Para las frases de entrada
“La rosa púrpura del Cairo”
“La rosa del azafrán”
“El color púrpura”
Salida:
AZAFRÁN
               La rosa del ...
CAIRO
               La rosa púrpura del ...
COLOR
               El ... púrpura
PÚRPURA
               El color ...
               La rosa ... del Cairo
ROSA
               La ... del azafrán
               La ... púrpura del Cairo 
Probar el funcionamiento de las clases con la siguiente aplicación:

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
/*
public class Test {
 public static void main(String[] args) {
  String[] datos = { "La rosa púrpura del Cairo", "La rosa del azafrán",
    "El color Púrpura" };
  List<String> frases = Arrays.asList(datos);
  String separadores = " ,;.:()¿!¡?";
  Indice index = new Indice(separadores, frases);
  System.out.println(index.presentaIndice());
  String[] noSig = { "el", "ella", "la", "lo", "un", "una", "del" };
  Collection<String> colNoSig = Arrays.asList(noSig);
  IndiceSignificativas indexSig = new IndiceSignificativas(separadores,
    frases, colNoSig);
  System.out.println(indexSig.presentaIndice());
 }
}*/

public class Test {

 public static void main(String[] args) {

  String separadores = "[ ,;.:\\(\\)\\¿\\!\\¡\\?]+";
  //String separadores = " ,;.:()¿!¡?";

  try {
   Indice index = new Indice(separadores, "frases.txt");
   // para presentar por pantalla
   PrintWriter pw = new PrintWriter(System.out, true);
   index.presentaIndice(pw);
   // para guardar en fichero
   index.presentaIndice("salida.txt");

   // Ahora con palabrasNoSignificativas
   IndiceSignificativas indexSig = new IndiceSignificativas(
     separadores, "frases.txt", "noClaves.txt");
   // para presentar por pantalla
   indexSig.presentaIndice(pw);

   // para guardar en fichero
   indexSig.presentaIndice("salidaNoSig.txt");
  } catch (IOException e) {
   System.out.println("Error:" + e.getMessage());
  }
 }
}

Bueno, aquí os traigo los resultados: Primero la class Titulo:

public class Titulo implements Comparable<Titulo>{
 private String titulo;
 
 public Titulo(String t) {
  titulo = t;
 }
 
 public boolean equals(Object o) {
  return titulo.equalsIgnoreCase((String) o);
 }
 public int hashCode() {
  return titulo.hashCode();
 }
 @Override
 public int compareTo(Titulo tk) {
  return titulo.compareToIgnoreCase(tk.titulo);
 }
 
 public String toString() {
  return titulo;
 }
 public String replace(String pal) { //Devuelve la string original con las veces que aparezca pal cambiadas por "..." 
  StringBuilder sb = new StringBuilder(titulo);
  String palU = pal.toUpperCase();
  String sbU = sb.toString().toUpperCase();   //Stringbuilder a cadena y lo pasamos a mayuscula
  int ind = sbU.indexOf(palU);     //indexOf devuelve la posición de la primera aparicion de la palabra
  while (ind>=0) {         //  
   sb.replace(ind,  ind + pal.length(), "...");//Cambio el trozo de cadena de sb por el ...
   sbU = sb.toString().toUpperCase();   //Transformo el StringBuilder a cadena mayuscula de nuevo
   ind = sbU.indexOf(palU);     //vuelvo a buscar. Si no encuentra devuelve -1
  } 
  return sb.toString();
 }

}


Luego la class Indice:
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;


public class Indice {//Extrae de cada frase las palabras.
 protected SortedMap<String, SortedSet<Titulo>> indice;
 private String separadores;
 
 public Indice(String sep) {
  separadores = sep;
  indice = new TreeMap<String, SortedSet<Titulo>>();
 }
 public Indice(String sep, Collection<String> col) {
  this(sep);
  agregarTitulo(col);
 }
 public Indice(String sep, String filFrases) throws IOException {
  this(sep);
  agregarTituloFichero(filFrases);
 }
 
 public void agregarTitulo(Collection<String> col) {
  // TODO Auto-generated method stub
  for(String tit: col) {
   agregarTitulo(tit);
  }
 }
 public void agregarTitulo(String tit) {
  // TODO Auto-generated method stub
  //1º tokenizamos el titulo con los separadores
  Titulo tit2 = new Titulo(tit);
  StringTokenizer st = new StringTokenizer(tit, separadores);
  while(st.hasMoreTokens()) {
   String palabra = st.nextToken().toUpperCase();
   if(!indice.containsKey(palabra)) {
    indice.put(palabra, new TreeSet<Titulo>());
    indice.get(palabra).add(tit2);
    
   } else {
    indice.get(palabra).add(tit2);
   }
  }
 }
 public void agregarTitulo(Scanner sc) {
  while(sc.hasNextLine()) {
   String linea = sc.nextLine();
   agregarTitulo(linea);
  }
 }
 public void agregarTituloFichero(String filFrases) throws IOException {
  Scanner sc = new Scanner(new File(filFrases));
  agregarTitulo(sc); //Método auxiliar
  sc.close();
 }
 public String presentaIndice() {
  String str = "";
  for(String pal : indice.keySet()) {          //recorre las palabras clave 
   str = str + pal + "\n";
   for(Titulo tit : indice.get(pal)) {         //Nos da los titulos de cada palabra clave
    str = str + "\t" + tit.replace(pal);
    str = str + "\n";
   }
  }
  return str;
 }
 
 public void presentaIndice(String salida) throws IOException{
  PrintWriter pw = new PrintWriter(salida);
  presentaIndice(pw);
  pw.close();
 }
 public void presentaIndice(PrintWriter pw){
  for(String pal : indice.keySet()){        //Estos dos bucles podrían cambiarse por un simple
   pw.println(pal);        //pw.println(presentaIndice());
   for(Titulo tit : indice.get(pal)) {
    pw.println("\t" + tit.replace(pal));
   }
  }
 }
}

Y por último la class IndiceSignificativas:

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;


public class IndiceSignificativas extends Indice{
 private SortedSet<String> noSignificativas;
 
 public IndiceSignificativas(String sep, Collection<String> noSig) {
  super(sep);
  //la coleccion las recorre, pasa a mayusculas y las mete en el conjunto de forma ordenada
  noSignificativas = new TreeSet<String>();
  for(String str : noSig) {
   noSignificativas.add(str.toUpperCase());
  }
 }
 public IndiceSignificativas(String sep, Collection<String> col, Collection<String> noSig){ //Falta Otro Constructor
  this(sep, noSig);
  this.agregarTitulo(col);
 }
 public IndiceSignificativas(String sep, String fichNoSig) throws IOException {
  super(sep);
  noSignificativas = new TreeSet<String>();
  palabrasNoSignificativas(fichNoSig);
  
 }
 public IndiceSignificativas(String sep, String fich, String fichNoSig) throws IOException {
  super(sep, fich);
  noSignificativas = new TreeSet<String>();
  palabrasNoSignificativas(fichNoSig);
  
 }

 public void palabrasNoSignificativas(String filNoSig) throws FileNotFoundException {
  Scanner sc = new Scanner(new File(filNoSig));
  palabrasNoSignificativas(sc);
 }
 public void palabrasNoSignificativas(Scanner sc)  {
  while(sc.hasNext()) {
   String linea = sc.next();
   noSignificativas.add(linea);
  }
 }
 public String presentaIndice() {
  String str = "";
  for(String pal : indice.keySet()) {          //recorre las palabras clave 
   if(!noSignificativas.contains(pal)) {
    str = str + pal + "\n";
    for(Titulo tit : indice.get(pal)) {         //Nos da los titulos de cada palabra clave
     str = str + "\t" + tit.replace(pal);
     str = str + "\n" + "\n";
    }
   }
   
  }
  return str;
 }
 public void presentaIndice(String salida) throws IOException{
  PrintWriter pw = new PrintWriter(salida);
  presentaIndice(pw);
  pw.close();
 }
 public void presentaIndice(PrintWriter pw){
  for(String pal : indice.keySet()){        //Estos dos bucles podrían cambiarse por un simple
   if(!noSignificativas.contains(pal.toLowerCase())) {
     pw.println(pal);        //pw.println(presentaIndice());
     for(Titulo tit : indice.get(pal)) {
      pw.println("\t" + tit.replace(pal));
     }
   }
   
  }
 }
 
}

Bueno gente, espero que os hayan gustado mis entradas de POO y os hayan sido de gran ayuda para aprobar ésta asignatura con buena nota ^^ Eso no significa que me vaya, aún quedan muchas cosas por subir :P

Hasta la próxima!! ;)

Actualización: He encontrado los archivos de entrada y salida y os los linkeo aquí:

Frases. 
Noclaves.
Salida
SalidanoSig

lunes, 14 de abril de 2014

Práctica AnagramasSimple Java POO

Buenas gente, aquí os traigo otra práctica. prAnagramasSimple. Como siempre, aquí os dejo linkeados el pdf (es el mismo que el de la práctica de llaves) y un programa principal para probarlo.

A diferencia de la práctica de las llaves, ésta parte del pdf si me permite copiar por lo que aquí os dejo el enunciado ;)
1. Un anagrama de una palabra es otra palabra obtenida mediante una permutación de sus letras; por ejemplo, saco es un anagrama de cosa. La signatura de una palabra se define como la cadena resultante de ordenar alfabéticamente las letras de dicha palabra en minúsculas. Así, la signatura de saco y cOSa es acos. Teniendo en cuenta esto se deberá construir una clase Palabra con las siguientes características: · Las instancias de esta clase deben mantener información de una palabra: una cadena de caracteres que la representa y su correspondiente signatura. · El constructor de la clase recibirá como argumento la cadena de caracteres y deberá construir su signatura. · La clase contará con un método boolean esAnagrama(Palabra), que determinará si la palabra argumento es o no un anagrama de la receptora. · Redefine los métodos equals(Object), hashCode() y toString(), teniendo en cuenta que para que dos palabras sean iguales basta con que lo sean las cadenas de caracteres correspondientes, con independencia de su tipografía (no se distinguen mayúsculas de minúsculas). · Deberá existir un orden natural entre palabras basado en el orden lexicográfico de las cadenas correspondientes con independencia de su tipografía. · Debe existir un método String getPalabra() que devuelve la cadena que representa la palabra y otro String getSignatura() que devuelve la cadena que representa la signatura. 2. Crear la clase Anagrama que almacenará palabras a partir de cadenas de caracteres que le proporcionaremos. En la información almacenada, cada palabra estará asociada con el conjunto de otras palabras incluidas en esta clase con las que forma un anagrama (ver el listado más abajo). · Define un constructor para crear la clase que inicializará las estructuras necesarias para guardar la información. Las palabras deberán estar ordenadas según el orden natural (ver el listado más abajo). · Define el método void nuevaPalabra(String) que incluye una nueva palabra a partir de la cadena que se le proporciona. Si la palabra ya se encuentra en la estructura no hace nada. Si no estaba, deberá asociarse a cualquier palabra que forme anagrama con ella. Además, esas que forman anagrama también deberán estar asociadas con ésta. Por ejemplo, al introducir mora, se debe asociar con amor, roma y ramo y a su vez, estas tres se deben asociar con mora. · Define el método void mostrarEnConsola() que muestra la información contenida en el anagrama en la salida estándar. El listado que hay más abajo muestra cómo hacerlo. Si las palabras introducidas en un anagrama son olí, ramo, amor, cosa, caso, ostra, lío, roma, astro, mora, lió, saco, el método que muestra en consola deberá producir la siguiente salida (nótese que no se muestra la signatura de las palabras): amor ( mora ramo roma ) astro ( ostra ) caso ( cosa saco ) cosa ( caso saco ) lió ( ) lío ( olí ) mora ( amor ramo roma ) olí ( lío ) ostra ( astro ) ramo ( amor mora roma ) roma ( amor mora ramo ) saco ( caso cosa ) 3. Además del orden natural definido para las palabras, construye una clase SatPalabra que proporcione un orden alternativo para las palabras basado en la longitud de las cadenas y, en caso de igualdad, en el orden ascendente lexicográfico, con independencia de su tipografía. Incluir un nuevo constructor a la clase Anagrama que tome como argumento un objeto de SatPalabra y cree un anagrama que genere el listado con esta ordenación alternativa: lió ( ) lío ( olí ) olí ( lío ) amor ( mora ramo roma ) caso ( cosa saco ) cosa ( caso saco ) ramo ( amor mora roma ) roma ( amor mora ramo ) saco ( caso cosa ) astro ( ostra ) ostra ( astro ) Ejemplo del programa principal (las palabras se debe introducir como argumentos del programa): 
public class mainAnagramas {
 public static void main (String[] args) {
  System.out.println("Orden Natural");
  Anagrama an1 = new Anagrama();
  for (String arg: args) {
   an1.nuevaPalabra(arg);
  }
  an1.mostrarEnConsola();
  System.out.println();
  System.out.println("Orden Alternativo");
  Anagrama an2 = new Anagrama(new SatPalabra());
  for (String arg: args) {an2.nuevaPalabra(arg);
  }
  an2.mostrarEnConsola();
 }
}

La salida producida:
Orden natural:
amor ( mora ramo roma )
astro ( ostra )
caso ( cosa saco )
cosa ( caso saco )
lió ( )
lío ( olí )
mora ( amor ramo roma )
olí ( lío )
ostra ( astro )
ramo ( amor mora roma )
roma ( amor mora ramo )
saco ( caso cosa )

Orden alternativo:
lió ( )
lío ( olí )
olí ( lío )
amor ( mora ramo roma )
caso ( cosa saco )
cosa ( caso saco )
mora ( amor ramo roma )
ramo ( amor mora roma )
roma ( amor mora ramo )
saco ( caso cosa )
astro ( ostra )
ostra ( astro )
Y aquí tenéis las soluciones:


Class Anagrama:
import java.util.*;


public class Anagrama {
 private Map<Palabra, Set<Palabra>> anagramas;
 
 public Anagrama() {
  anagramas = new TreeMap<Palabra, Set<Palabra>>();
 }
 public Anagrama(Comparator<Palabra> cs) {
  anagramas = new TreeMap<Palabra, Set<Palabra>>(cs);
 }
 public void nuevaPalabra(String pal) {
  Palabra sPal = new Palabra(pal);
  if(!anagramas.containsKey(sPal)) {
   //Creo una nueva entrada en la aplicación
   //Creo el conjunto vacío
   Set<Palabra> conjunto = new TreeSet<Palabra>();
   anagramas.put(sPal, conjunto);
  
   for(Palabra p: anagramas.keySet()) {
    if(sPal.esAnagrama(p) && (!sPal.equals(p))) {
     Set<Palabra> con = anagramas.get(p);
     con.add(sPal);
     Set<Palabra> condof = anagramas.get(sPal);
     condof.add(p);
    
    }  
   }
  }
 }


 public void mostrarEnConsola() {
  for( Palabra p : anagramas.keySet()) {
   System.out.print(p + "\t (" );
   for (Palabra p2 : anagramas.get(p)) {
    if(!p.equals(p2)) System.out.print(p2 + " ");
   }
   System.out.println(")");
  }
 }
}


Class Palabra:
import java.util.Arrays;


public class Palabra implements Comparable<Palabra>{
 private String cadena;
 private String signatura;
 
 public Palabra(String p) {
  cadena = p.toLowerCase();
  char [] s = p.toCharArray();
  Arrays.sort(s);
  signatura = new String(s);
 }
 
 public boolean esAnagrama(Palabra p) {
  return signatura.equals(p.signatura);
 }
 
 public boolean equals(Object p) {
 // boolean iguales = true;
  return cadena.equalsIgnoreCase(((Palabra) p).getPalabra());
 }
 
 public int hashCode() {
  return cadena.hashCode();
 }

 public String toString() {
  String std = new String(cadena /*+ " y su anagrama correspondiente " + signatura*/);
  return std;  
 }

 @Override
 public int compareTo(Palabra s) {
  // TODO Auto-generated method stub
  return cadena.compareToIgnoreCase(s.cadena);
 }
 public String getPalabra() {
  return cadena;
 }
 public String getSignatura() {
  return signatura;
 }
}


Class SatPalabra:
import java.util.Comparator;


public class SatPalabra implements Comparator<Palabra>{
 public int compare(Palabra arg0, Palabra arg1) {
  int ns;
  int aux = arg0.getPalabra().length() - arg1.getPalabra().length();
  if(aux<0) ns = -1;
  else if (aux> 0) ns = 1;
  else ns = arg0.compareTo(arg1);
  return ns;
 }

}

Bueno, ésta puede ser más pesada por el hecho de enterarse primero de lo que es un anagrama y, bueno, que tampoco es mucha diversión :p pero ánimo, que ya vereis que conforme avanzais se vuelve todo más ameno ;)

Saludos