Instituto Superior de Engenharia de Lisboa Licenciatura em Engenharia Informática e de Computadores Algoritmos e Estruturas de Dados Semestre de Inverno 2015/2016 Segunda série de exercícios Observações: • Data de entrega: 27 de Novembro de 2015. • Não é permitida a utilização de algoritmos e estruturas de dados já existentes na biblioteca base da plataforma Java. 1. Exercícios 1. Realize o método estático da classe Utils, public static int NElement( int[] array, int l, int r, int n ); que retorna o n-ésimo menor elemento do sub-array (v; l; r). 2. Realize na classe ListUtils 2.1. O método, public static <E> Node<E> interleaved(Node<Node<E>> list)) que retorna uma lista duplamente ligada circular e com sentinela, resultante da junção, de modo intercalado, das listas duplamente ligadas circulares e com sentinelas, presentes em list. Por exemplo, se estiverem presentes em list as listas [1; 2; 3; 4], [4; 5; 6] e [7; 8; 9; 10], a lista resultante será [1; 4; 7; 2; 5; 8; 3; 6; 9; 4; 10]. A lista list deverá ficar vazia. Note que list também é uma lista duplamente ligada circular e com sentinela, devendo os nós das suas listas, serem reaproveitados na lista resultante. 2.2. O método, public static <E> E mostOccurrent(Node<E>[] lists, Comparator<E> cmp) que dado um array de listas duplamente ligadas, não circulares e sem sentinela, ordenadas de modo crescente pelo comparador cmp, retorna o elemento presente nas listas lists com maior número de ocorrências, segundo o comparador cmp. As listas lists podem ser modicadas. Assuma que cada objeto do tipo Node<E> tem 3 campos: um value e duas referências, prev e next. Em caso de empate de ocorrências, deverá ser retornado o menor elemento, segundo o comparador cmp. Caso não existam elementos, deverá ser retornado null. 3. Realize a classe Iterables. Para a implementação da mesma, considere que a classe Pair está definida do seguinte modo: public class Pair<K,V>{ public K key; public V value; //… }. A classe Iterables deverá conter: 3.1. O método estático, public static Iterable<String> getPhrasesStart(Iterable<Iterable<String>> phrases, String prefix) que retorna um iterável com as frases que ocorram na sequência de frases equivalente à concatenação das sequências presentes em phrases, e que contenham prefix como primeira palavra. A implementação deste método deve minimizar o espaço ocupado pelo iterável. O iterador associado ao iterável retornado não suporta o método remove. Por exemplo, se phrases contiver as seguintes sequências de palavras: [[“O”,“rato”,“roeu”,“a”,“rolha”,“da”,”garrafa”,“do”,“rei”,“da”,“Rússia”], [“Fui”, “ao”, “mar”, “colher”, “cordões”, “vim”, “do”, “mar”, “cordões”, “colhi”], [“O”,“original”,“nunca”,“se”,“desoriginou”,“nem”,“nunca”,“se”,“desoriginalizará”], [“Três”,“pratos”,“de”,“trigo”,“para”,“três”,“tristes”,“tigres”] ] e se prefix=“O”, então o objeto retornado deve representar a sequência: [“O rato roeu a rolha da garrafa do rei da Rússia”, “O original nunca se desoriginou nem numca se desoriginalizará”]. 3.2. O método estático, public static <K,V> Iterable<Pair<K,V>> getEntries( HashNode<K,V>[] hashMap ) que dado o mapa hashMap, que mapeia chaves do tipo K em valores do tipo V, obtém uma sequência dos pares presentes no mapa hashMap. A implementação deste método deve minimizar o espaço ocupado pelo iterável. O iterador associado ao iterável retornado não suporta o método remove. Assuma que o mapa foi implementado recorrendo a uma tabela de dispersão com encadeamento externo em listas simplesmente ligadas, não circulares e sem sentinela. Para a implementação deste método, considere que o tipo HashNode<K,V> tem 2 campos: um pair do tipo Pair<K,V> e next do tipo HashNode<K,V>. 3.3. O método estático, public static <E> Iterable<Pair<E, Integer>> histogram(E[] array) que dada a sequência representada pelo array não ordenado de elementos E, retorna um iterável de pares com o histograma da sequência. O algoritmo implementado deve usar uma tabela de dispersão para o cálculo do histograma. 2. Problema: Substituição de palavras por sinónimos em documentos Considere que se pretende implementar uma aplicação para a substituição de palavras num documento por sinónimos. Esta aplicação recebe como parâmetro dois ficheiros de texto: • um documento, onde se pretende substituir todas as palavras pelos respectivos sinónimos, contidas no ficheiro de sinónimos. • um ficheiro dicionário, em que cada linha deste ficheiro é composta por duas palavras, nomeadamente, a palavra e um sinónimo da mesma. A aplicação Replace retorna um novo documento, também ficheiro de texto, onde todas as substituições por sinónimos, presentes no ficheiro de sinónimos, foram realizadas. No contexto do desenvolvimento da aplicação, será necessário implementar um Map<K,V>, que mapeia chaves a valores. Este tipo de dados deverá ter as seguintes operações: • public V put(K key, V value) - Associa o valor value à chave key no mapa. Se o mapa já contiver um mapeamento para a chave key, substitui-o pelo novo valor value. Esta operação deverá retornar o valor que se encontrava associado à chave key, ou null caso não existisse mapeamento para a chave; • public V get(K key) - Retorna o valor ao qual a chave key está mapeada, ou null, se o mapa não contém mapeamento para essa chave; • public V remove(K key) - Remove o mapeamento para uma chave key no mapa, se este mapeamento existir. Retorna o valor que estava associado à chave key, ou null, se não existir mapeamento para essa chave; • public boolean replace(K oldK, K newK, V newV) – Substitui, caso exista, o par cuja chave é oldK por um novo par (newK, newV) e retorna true. Caso a chave oldK não exista ou já exista um par com a chave newK retorna false. • public int size() - Retorna o número de mapeamentos chave-valor presentes no mapa; • public boolean isEmpty() - Retorna true se o mapa não contém mapeamentos chave-valor; • public Set<Map.Entry<K,V>> entrySet() – Retorna uma vista do conjunto dos mapeamentos chavevalor contidos neste mapa. • public Set<Map.Entry<K,V>> keySet() – Retorna uma vista do conjunto das chaves contidas neste mapa. • public Collection<Map.Entry<K,V>> values() – Retorna uma vista da coleção dos valores contidos neste mapa. Observação: para a implementação deste tipo de dados, poderá utilizar interfaces definidas em java.util e também os seguintes tipos definidos em java.util: java.util.AbstractSet e java.util.AbstractCollection. Funcionalidades a implementar As funcionalidades a implementar são as seguintes: 1. A aplicação Replace; 2. Uma implementação do tipo de dados Map, tendo em conta que a sua utilização será na aplicação Replace. Parâmetros de Execução da aplicação Replace Para iniciar a execução da aplicação Replace, terá de se executar java Replace dictionary.txt Durante a sua execução, a aplicação deverá processar os seguintes comandos: • replaceby document.txt synonym.txt que produz o documento synonym.txt, contendo uma cópia do documento document.txt em que as palavras presentes em dictionary.txt são substituídas pelo respetivo sinónimo. • getPairs k que, lista os primeiros k pares de palavras do dicionário. • next que, lista os k pares de palavras que se encontram a seguir aos listados no último comando next ou getPairs. O k corresponde ao número de palavras dado no último comando getPairs. Avaliação Experimental Realize uma avaliação experimental do(s) algoritmo(s) desenvolvido(s) para a resolução deste problema. Apresente os resultados graficamente, utilizando uma escala adequada.