Написание средства поиска анаграмм (из списка слов в текстовом файле)

Я пытался закодировать средство поиска анаграмм на Java, чтобы в терминале после компиляции все, что мне нужно было сделать, это

  1. Введите java Anagramfind list.txt
  2. При появлении запроса введите слово, скажите treasure
  3. Программа печатает анаграмму, например austerer
  4. Появляется еще одно приглашение с вопросом, хочу ли я еще один (yes/no)

Файл list.txt содержит большинство, если не все слова английского языка.

Вот что у меня пока...

import java.util.*;
import java.io.*;

class ProjectAnagram {
    public static void main (String[] args throws IOException) {
        //THis here declares an array of strings
        Scanner dictionary = new Scanner new (fileInputStream(args[0]));
        String[] entireArray = new String[173528]; //name of array + 173258
        System.out.println ("Put something in please");
        Scanner keyboard = new Scanner(System.in);
        System.out.println ("Inserted");

        String word = keyboard;
    }

Мне все еще нужно добавить остальные.

В основном у меня были проблемы с использованием массивов, на которые я ссылался здесь:

У меня также возникают проблемы с использованием Stringbuffer, который проверяет, имеют ли слова одинаковые символы или нет.

Программа сначала проверяет, имеют ли входная строка и строка в текстовом файле одинаковую длину, чтобы исключить очевидные неанаграммы. Если нет, то он переходит к следующему слову в списке, возможно, с i++ в каком-то цикле.


person J. Doe    schedule 30.04.2016    source источник
comment
Ваш код крайне не компилируется. Пожалуйста, исправьте свой код в своем посте. Синтаксических ошибок много.   -  person Vampire    schedule 01.05.2016
comment
На самом деле это псевдокод, лол   -  person J. Doe    schedule 01.05.2016
comment
Если вы задаете вопрос по Java, пожалуйста, опубликуйте код Java. Этот псевдокод наверняка недействителен ни в одном вопросе, так как есть несбалансированные круглые скобки, несбалансированные фигурные скобки и так далее. Пожалуйста, исправьте код в вашем вопросе.   -  person Vampire    schedule 01.05.2016
comment
Если вы планируете просмотреть каждый элемент (слово на английском языке), вам действительно следует подумать над моим ответом. Хранение словаря в массиве с последующим использованием других алгоритмов ниже довольно неэффективно, особенно если словарь расположен в алфавитном порядке.   -  person ChiefTwoPencils    schedule 01.05.2016


Ответы (4)


Подобно поиску, являются ли две строки перестановками друг друга, вы можете отсортировать символы заданной строки и сделать ее ключом к списку анаграмм. Таким образом, независимо от строки, вы найдете только строки одинаковой длины, состоящие из одних и тех же символов.

Что-то типа:

Map<String, List<String>> map ...
map.get(getKey(string)).get(i); // i = the ith request for an anagram
person ChiefTwoPencils    schedule 30.04.2016
comment
Да, это работает. Спасибо за это! - person J. Doe; 01.05.2016
comment
@J.Doe, рад помочь. Если это окажется лучшим решением, смело принимайте его. - person ChiefTwoPencils; 01.05.2016

Попробуй это.

package stackoverflow;

import java.io.*;
import java.util.*;

public class ProjectAnagram {

    static String sort(String s) {
        char[] c = s.toCharArray();
        Arrays.sort(c);
        return String.valueOf(c);
    }

    public static void main(String[] args) throws FileNotFoundException {
        Map<String, List<String>> words = new HashMap<>();
        try (Scanner in = new Scanner(new File(args[0]))) {
            while (in.hasNext()) {
                String word = in.next();
                String sorted = sort(word);
                List<String> list = words.get(sorted);
                if (list == null)
                    words.put(sorted, list = new ArrayList<>());
                list.add(word);
            }
        }
        Scanner in = new Scanner(System.in);
        while (true) {
            System.out.print("Enter word (or press ENTER to quit): ");
            if (!in.hasNextLine()) break;
            String s = in.nextLine();
            if (s.length() == 0) break;
            System.out.println(words.get(sort(s)));
        }
    }
}
person saka1029    schedule 30.04.2016
comment
Извините, почему-то не компилируется. - person J. Doe; 01.05.2016
comment
В любом случае спасибо. Могу я спросить, почему он не скомпилируется или почему static String sort(String s) находится на самом верху? - person J. Doe; 01.05.2016
comment
Вложить все или только static String sort(String s)? - person J. Doe; 01.05.2016
comment
Теперь он говорит это cannot find symbol в разных строках. - person J. Doe; 01.05.2016
comment
Ах, да, я забыл импортировать. Спасибо! - person J. Doe; 01.05.2016

РЕДАКТИРОВАТЬ: Этот ответ - эффективный способ сделать это!

Время поиска Hashmaps составляет O(1).

Нам потребуется 3 итерации. Во-первых, чтобы добавить количество символов в первой строке в хэш-карту, во-вторых, чтобы удалить количество символов во второй строке из хэш-карты, в-третьих, чтобы перебрать хэш-карту и посмотреть, все ли значения равны 0.

Итак, это дало бы нам алгоритм O (n).

person Nishant Roy    schedule 30.04.2016
comment
Итак, OO является анаграммой NP? Алгоритм хеширования очень слабый. В лучшем случае это может служить индикатором, но вам все равно придется сравнивать символы. - person Vampire; 01.05.2016
comment
@BjörnKautler, а что, если мы изменим его на: hash += Math.pow(str.charAt(i),2); - person Nishant Roy; 01.05.2016
comment
В качестве альтернативы этот ответ работает и эффективен. - person Nishant Roy; 01.05.2016
comment
Что ж, хеширование лучше, но я относительно уверен, что оно также имеет много конфликтов. Вы можете сделать это еще лучше, используя CRC, MD5 или SHA-1, но чем безопаснее вы делаете, тем больше времени на это требуется. Вы также можете просто использовать мой однострочник, хотя я не проверял его производительность :-) - person Vampire; 01.05.2016
comment
У вашего однострочника была сортировка, которая будет O (n log n). Ответ, на который я ссылался, будет хранить каждый символ из первой строки в хэш-карте, затем удалять каждый символ во второй строке из хэш-карты, затем он будет перебирать хэш-карту и смотреть, были ли какие-либо значения 0 > Это будет O (n) . - person Nishant Roy; 01.05.2016
comment
Как я уже сказал, я не знаю о его производительности, но он будет работать, и это всего в одну строку. ;-) - person Vampire; 01.05.2016
comment
@NishantRoy, но все, что нужно, это определить, является ли это перестановкой. Им нужен способ получить одну из n анаграмм. Они также хотят иметь возможность получить больше по запросу. - person ChiefTwoPencils; 01.05.2016

person    schedule
comment
Я ошибочно неправильно понимаю разницу между перестановкой и анаграммой; разве они не должны быть действительными словами? - person ChiefTwoPencils; 01.05.2016
comment
Конечно, ingsetT не является допустимой анаграммой, но каждая анаграмма - это просто перестановка нового слова, и OP работает со списком слов. - person Vampire; 01.05.2016
comment
То есть вместо Testing и ingset я мог бы заменить его на переменные word и entirearray сверху соответственно? - person J. Doe; 01.05.2016
comment
Я не уверен, потому что вы все еще не исправили свой код выше, поэтому неясно, что к чему. Но если word — это слово, введенное пользователем, а entirearray — одно из слов списка слов, тогда да. Но из именования я предполагаю, что entirearray - это весь список слов, поэтому вы должны перебрать entirearray и проверить каждую запись с этой строкой, хотя, конечно, вы не должны делать ...toArray() материал для входного слова для каждого слова словаря, но сделать это один раз и повторное использование. - person Vampire; 01.05.2016
comment
И если вы часто проверяете весь список слов и у вас достаточно памяти, возможно, стоит вычислить отсортированные массивы слов списка слов один раз после чтения списка слов с сопоставлением с исходным словом, а затем выполнять поиск повторно. Затем вы можете даже отсортировать отсортированный список и использовать алгоритм бинарного поиска, или вы можете добавить в свой файл списка слов сопоставление отсортированного символа со словом, чтобы вам не приходилось делать это при каждом запуске программы. Есть много способов оптимизировать это. - person Vampire; 01.05.2016
comment
Я удалил непонятные части своего кода и добавил, что мне нужно добавить недостающий материал :). Итак, скажем, я хотел взять одно слово из entireArray, как бы я сослался на это в методах? - person J. Doe; 01.05.2016
comment
Я не уверен, что вы спрашиваете. Если вы хотите взять 5-е слово entireArray, это будет entireArray[4]. Но если это был ваш вопрос, пожалуйста, идите и прочитайте книгу об основах Java. ;-) - person Vampire; 01.05.2016
comment
Извините, плохо сформулированный вопрос. Но вы все же успели на него ответить, так что спасибо! Я думал, что если бы я потом вставил метод через ., мне понадобились бы круглые скобки, а не квадратные скобки. - person J. Doe; 01.05.2016
comment
Да, скобки нужны для вызова метода, но доступ к элементам массива не является методом. Как я уже сказал, прочитайте книгу об основах Java. - person Vampire; 01.05.2016