Professional Documents
Culture Documents
Tarea 5
Diccionarios
Profesor de Ctedra:
Profesor Auxiliar:
Alumno:
Fecha:
Benjamin Bustos
Boris Romero
Daniel Rojas Vilar
24/11/2015
CC3001
CC3001
ndice de contenidos
1
Introduccin..................................................................................................................................... 3
Diseo de la solucin....................................................................................................................... 3
2.1
2.2
2.3
Comparacin............................................................................................................................ 4
Implementacin............................................................................................................................... 4
3.1
3.2
3.3
Comparacin............................................................................................................................ 6
Resultados y conclusiones.............................................................................................................. 7
Anexos............................................................................................................................................. 8
5.1
Parte 1...................................................................................................................................... 8
5.1.1
Programa principal..............................................................................................................8
5.1.2
Heap................................................................................................................................... 9
5.2
Parte 2.................................................................................................................................... 11
5.2.1
Programa principal............................................................................................................ 11
5.2.2
Nodo................................................................................................................................. 12
5.2.3
TablaHash......................................................................................................................... 12
5.3
Parte 3.................................................................................................................................... 14
CC3001
1 Introduccin
El objetivo de esta tarea es utilizar dos implementaciones distintas del TDA Diccionario para
resolver un problema particular, y hacer un anlisis de eficiencia para ambos mtodos. El problema a
estudiar es el de crear una funcin que, dado un diccionario de largo m guardado en un String D y un
texto en un String T, retorne el nmero de palabras en T que aparecen en D.
El primer mtodo utilizado corresponde a pasar el diccionario a un arreglo ordenado, para
luego revisar palabra por palabra el texto, utilizando bsqueda binaria para verificar si se encuentra en
D (Parte 1).
El segundo mtodo consiste en usar una tabla de hash para ordenar el diccionario, en la que
despus se buscan las palabras de T, usando como funcin de hash la suma numrica de los valores
de los caracteres, mdulo el tamao de D, y manejando las colisiones mediante encadenamiento
(Parte 2).
Finalmente, se desea comparar la eficiencia de ambos mtodos, por lo que se implementa una
funcin COMPARA(D,T) que mide los tiempos de ejecucin de las dos funciones anteriores (que
llamaremos SCORE_ARREGLO(D,T) y SCORE_HASH(D,T) respectivamente), para todos los prefijos de
D (es decir, los m sub-diccionarios Dk que incluyen slo las k primeras palabras de D, para k[1,...,m]).
Los resultados se presentan finalmente tabulados en STDOUT (Parte 3).
2 Diseo de la solucin
2.1 Implementacin con Arreglo Ordenado
Se implementa una clase Heap que maneja Strings y permite obtener siempre el mayor en
trminos lexicogrficos, utilizando el mtodo predefinido compareTo(). SCORE_ARREGLO(D,T) utiliza
un objeto de esta clase para ordenar D, insertando una por una todas las palabras del diccionario en
el Heap, y luego extrayndolas en orden decreciente (sacando siempre el mximo) para construir un
arreglo ordenado en orden creciente.
Luego se recorre el texto T, revisando para cada palabra si sta se encuentra en D. De ser as,
se aumenta en uno un contandor, que finalmente se retorna. La bsqueda en D se realiza con la
estrategia de bsqueda binaria, posible gracias al trabajo de ordenamiento previo: se llama una
funcin buscar(D, palabra) que retorna true si palabra est en el arreglo diccionario, y false si no.
Esta funcin utiliza ndices i y j, al comienzo iguales a 0 y m-1 respectivamente, que marcan el
subconjunto de diccionario sobre el que se realiza la bsqueda. En cada iteracin se toma el punto
4
CC3001
medio M entre ambos lmites y se compara el elemento en ese ndice con palabra: si es igual,
significa que est en diccionario, por lo que retorna true; si palabra es menor, contina la bsqueda
actualizando j=M-1; si palabra es mayor, contina actualizando i=M+1. Finalmente, si se llega a un
conjunto vaco sin encontrar la palabra buscada, se retorna false.
D utilizando el mtodo insertar(String palabra). Luego recorre T, buscando cada palabra en la tabla
de hash usando buscar(String palabra), e incrementando un contador cada vez que una palabra de T
se encuentre en la tabla, el que finalmente se retorna.
2.3 Comparacin
COMPARA(D,T) convierte D a un arreglo sin cambiar su orden, y usa un String subDiccionario
que inicialmente corresponde slo a la primera palabra de D. Luego itera, llamando en cada caso a
SCORE_ARREGLO(subDiccionario, T) y SCORE_HASH(subDiccionario, T) y guardando en variables el
momento en el que se llaman y en que terminan de ejecutarse, utilizando el mtodo
System.nanoTime(), que entrega el tiempo actual del sistema en nanosegundos. Con estos datos
calcula el tiempo de ejecucin de ambos mtodos y los imprime tabulados en la pantalla. Al final de
5
CC3001
cada ciclo concatena la siguiente palabra de D al String subDiccionario, terminando cuando llega a la
ltima palabra.
3 Implementacin
3.1 Implementacin con Arreglo Ordenado
public static int SCORE_ARREGLO(String D, String T) {
String[] diccionario=D.split(" "); //arreglo desordenado con palabras del diccionario
//palabras en D se separan por espacios
int m=diccionario.length; //largo de D
//ordenar diccionario con Heapsort
Heap cola=new Heap(m); //crear Heap vaco de tamao igual al largo de D
for (int j=0; j<m; j++) //pasar todas las palabras al Heap
cola.insertar(diccionario[j]);
//ordenar de menor a mayor
for (int j=m-1; j>=0; j--) {
String palabra=cola.extraerMax();
diccionario[j]=palabra;
}
//recorrer T
String[] texto=T.split(" ");
int n=texto.length;
int k=0; //contador de apariciones
for (int j=0; j<n; j++) {
if (buscar(diccionario,texto[j]))
k++; //la palabra buscada est en el diccionario
}
return k;
}
public static boolean buscar(String[] D, String palabra) {
//buscar palabra en diccionario ordenado D usando bsqueda binaria
//retorna true si se encuentra, false si no
int i=0; //lmite inferior
int j=D.length-1; //lmite superior
while (i<=j) { //mientras el conjunto no sea vaco
int m=(i+j)/2;
if (D[m].compareTo(palabra)==0)
return true; //se encontr la palabra
else if (D[m].compareTo(palabra)>0)
j=m-1; //seguir buscando en la primera mitad
else
i=m+1; //seguir buscando en la segunda mitad
}
return false; //no se encontr
}
//La implementacin del Heap es anloga a la de los apuntes del curso, y puede revisarse en Anexos
CC3001
3.3 Comparacin
public static void COMPARA(String D, String T) {
String[] diccionario=D.split(" ");
int m=diccionario.length;
//probar con todos los sub-diccionarios
CC3001
4 Resultados y conclusiones
Anlisis de eficiencia (diccionario D de largo m y texto T de largo n):
a) Implementacin con arreglo ordenado:
Ordenar D usando Heapsort: insertar y extraer cada elemento de D en el Heap una vez
=> O(m logm).
b) Implementacin con tabla de hash: m elementos en una tabla de tamao m => =1.
TOTAL: O(n+m).
Esto coincide con los resultados entregados por la funcin COMPARA(D,T), en los que se
observa que los tiempos de ejecucin del mtodo implementado con un arreglo ordenado crecen ms
rpidamente con el tamao de D que los del mtodo que utiliza la tabla de hash, alcanzndose
8
CC3001
diferencia significativas para diccionarios largos. Sin embargo, para diccionarios con pocas palabras
estas diferencias son casi imperceptibles, e incluso se da el caso en que el primer mtodo resulta
ms rpido que el segundo.
CC3001
5 Anexos
5.1 Parte 1
5.1.1 Programa principal
package cc3001.tarea5.rojas_daniel;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Parte1 {
public static boolean buscar(String[] D, String palabra) {
//buscar palabra en diccionario D usando busqueda binaria
//retorna true si se encuentra, false si no
int i=0;
int j=D.length-1;
while (i<=j) { //mientras el conjunto no sea vacio
int m=(i+j)/2;
if (D[m].compareTo(palabra)==0)
//se encontro la palabra
return true;
else if (D[m].compareTo(palabra)>0)
//seguir buscando en la primera mitad
j=m-1;
else
//seguir buscando en la segunda mitad
i=m+1;
}
//no se encontro
return false;
10
CC3001
}
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader (new InputStreamReader(System.in));
String input;
String output = "";
//leemos una linea completa a la vez
while (( input = in.readLine () ) != null) {
String[] entrada = input.split("\\|");
output += SCORE_ARREGLO(entrada[0],entrada[1]) + "\n";
}
System.out.print(output);
System.out.flush();
in.close();
}
5.1.2 Heap
package cc3001.tarea5.rojas_daniel;
public class Heap {
int n; //tamano del Heap
String[] a;
Heap(int m) {
a=new String[m+1]; //la primera posicin no se usa
n=0;
}
boolean estaVacio() {
if (n==0)
return true;
else
return false;
}
11
CC3001
12
CC3001
5.2 Parte 2
5.2.1 Programa principal
package cc3001.tarea5.rojas_daniel;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Parte2 {
public static int SCORE_HASH(String D, String T) {
//arreglo desordenado con palabras del diccionario
String[] diccionario=D.split(" ");
int m=diccionario.length;
//construir tabla
TablaHash tabla=new TablaHash(m);
for (int j=0; j<m; j++)
tabla.insertar(diccionario[j]);
//recorrer texto
String[] texto=T.split(" ");
int n=texto.length;
int k=0; //contador de apariciones
for (int j=0; j<n; j++) {
if (tabla.buscar(texto[j]))
k++;
}
return k;
}
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader (new InputStreamReader(System.in));
String input;
String output = "";
//leemos una linea completa a la vez
while (( input = in.readLine () ) != null) {
String[] entrada = input.split("\\|");
output += SCORE_HASH(entrada[0],entrada[1]) + "\n";
}
System.out.print(output);
System.out.flush();
in.close();
}
13
CC3001
5.2.2 Nodo
package cc3001.tarea5.rojas_daniel;
public class Nodo {
String palabra;
Nodo siguiente;
Nodo(String p) {
palabra=p;
siguiente=null;
}
}
5.2.3 TablaHash
package cc3001.tarea5.rojas_daniel;
public class TablaHash {
int m;
Nodo[] tabla;
TablaHash(int largo) {
tabla=new Nodo[largo];
m=largo;
}
int hash(String palabra) {
int suma=0;
int l=palabra.length();
//sumar valores de caracteres
for (int j=0; j<l; j++) {
suma+=(int)palabra.charAt(j);
}
//sacar residuo
int h=suma % m;
return h;
}
14
CC3001
15
CC3001
5.3 Parte 3
package cc3001.tarea5.rojas_daniel;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Parte3 {
public static void COMPARA(String D, String T) {
String[] diccionario=D.split(" ");
int m=diccionario.length;
//probar con todos los sub-diccionarios
String subDiccionario=diccionario[0]; //solo primera palabra
int j=1;
while (true) {
//guardar tiempo antes y despues de ejecutar cada metodo
long t0=System.nanoTime();
Parte1.SCORE_ARREGLO(subDiccionario, T);
long t1=System.nanoTime();
Parte2.SCORE_HASH(subDiccionario, T);
long t2=System.nanoTime();
//calcular tiempo transcurrido con cada metodo
float tiempo1=(float)(t1-t0)/(1000*1000);
float tiempo2=(float)(t2-t1)/(1000*1000);
//imprimir resultados en la pantalla
System.out.printf("%d\t%f\t%f\n",j,tiempo1,tiempo2);
if (j==m) //si se probo con todos los sub-diccionarios
break;
//agregar la siguiente palabra del diccionario
subDiccionario+=" "+diccionario[j++];
}
}
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader (new InputStreamReader(System.in));
String input;
//leemos una linea completa a la vez
while (( input = in.readLine () ) != null) {
String[] entrada = input.split("\\|");
COMPARA(entrada[0],entrada[1]);
}
System.out.flush();
in.close();
16
CC3001
17