Compare two Lists for Anagrams - Java - java

I'm currently working on an anagram solver. I saw a really good post which had one recommendation on alphabetizing the letters of both the user input and dictionary list before comparing. It seemed interesting so I'm giving it a try. Previously I used permutations, but I want something that I can eventually (and efficiently) use to solve multi word anagrams.
I can put both my user input and dictionary into char arrays and sorting alphabetically. Now I need to compare each so I can determine if something is an anagram or not. I thought about taking the alphabetized user input and determining if the alphabetized dictionary contained it or not. I've posted my code below. As you can guess I'm a little confused on the logic of this process. I was wondering if someone could help me straighten out the logic a little. Thanks for any help.
public class AnagramSolver1 {
public static void main(String[] args) throws IOException {
List<String> dictionary = new ArrayList<String>();
List<String> inputList = new ArrayList<String>();
BufferedReader in = new BufferedReader(new FileReader("src/dictionary.txt"));
String line = null;
Scanner scan = new Scanner(System.in);
while (null!=(line=in.readLine())){
dictionary.add(line);
}
in.close();
char[] sortDictionary;
char[] inputSort;
System.out.println("Enter Word: ");
String input = scan.next();
inputList.add(input);
//Getting a little confused here. I thought about sorting my input
//then iterating through my dictionary (while sorting it too) and comparing
//thus far it produces nothing
for(int i = 0; i < inputList.size(); i++){
inputSort = inputList.get(i).toCharArray();
Arrays.sort(inputSort);
for (int j = 0; j < dictionary.size(); j++) {
sortDictionary = dictionary.get(i).toCharArray();
Arrays.sort(sortDictionary);
if(inputSort.equals(sortDictionary)){
System.out.println("Anagram" +dictionary.get(i));
} //end if
}//end for
}//end for
}//end main
}

Why not maintain a Map<String, Set<String>> that maps a sorted-character string to a set of strings that are its anagrams. You can update this map as you read words from the dictionary. For example, if you read the word dog you would add an entry to the map "dgo" => {"dog"} (notice that dgo consists of the sorted characters of the word dog). Then if you read the word god, you would sort its characters to obtain the same dgo and consequently amend the previous entry to be "dgo" => {"dog", "god"}. You would of course repeat this for every word in the dictionary.
This should allow for quick and easy querying. If you wanted to then find anagrams of the word dog you would use map.get(sortChars("dog")).
On another note, I'm going to reiterate what the other answer mentioned, namely that it's important to modularize your code. You should put logically related functions/tasks in their own methods as opposed to having everything in one place. This helps with readability and your/others' ability to maintain your code in the future.

You are doing too many things at once here. You've got file IO, user input, sorting and the algorithm all in one place. Try to modularize it so you have a function called isAnagram(List<Character> firstPhrase, List<Character> secondPhrase). Make sure that works correctly, then have all the other steps figure out how to call it. This way you can test your algorithm without requiring user input. This will be a much faster feedback loop.
It's algorithm will work like this:
(optionally) copy the contents of the input so you don't mutate the input
compare their lengths. If they're not equal, return false
sort each list
iterate element by element and check if they're equal. If they're not, return false
if you reach the end, return true.

Related

Display elements of a String which are not found on the other

We were told to do a program on stings and I wasn't able to attend class because I was sick. I am asking for your help on this task that was given to us.
Create a java program that will ask the user to input two Strings. Compare the two strings and display the letters that are found on the first string but are not found on the second string.
Here is what I have at the moment https://pastebin.com/7a4dHecR
I really have no Idea what to do so any help would be appreciated!
https://pastebin.com/7a4dHecR
import java.util.*;
public class filename{
public static void main(String[] args){
Scanner sc =new Scanner(System.in);
System.out.print("Input first string: ");
String one=sc.next();
System.out.println();
System.out.print("Input second string: ");
String two=sc.next();
}
}
There are many ways to do this. I'm going to give you some parts you can put together. They are not the shortest or simplest way to solve this particular problem, but they will be useful for other small programs you write.
Here are some hints:
First, figure out how to step through your code with a debugger.
Second, figure out how to find the Javadoc for Java library classes and their methods.
You need to do something for each character in a string. Use a for loop for that:
for (int i = 0; i < one.length(); i++) {
// your code here
}
You need to get a particular character of a String.
String c = one.substring(i, i+1);
Read the Javadoc for String.substring to understand what the i and i+1 parameters do.
Now you need to find a way to check whether a String contains another String. Look at the Javadoc for the String class.
Then you can put all this together.
You could try the following:
String diff: StringUtils.difference(one, two);
System.out.println(diff);

How would I separate a sentence into individual words with a loop and send them individually into an ArrayList in Java?

I have a very specific problem for my CS course. I have a sentence in a string, and I need that separated into individual words within an ArrayList, and cannot use the split method.
The issue I have is that I have had zero teaching on arrays, only the bare minimum teaching for loops and String statements. I've done a lot of research and figured out the best way to go about making the loop, and sending the words to the ArrayList, however I still can't find a good way to actually have it loop through the sentence and separate each individual word at all. I get how easily it can be done to separate the very first word, however after that I get lost. I have no idea how to make the loop for its other iterations specifically grab the next word in the sentence after the one it previously got.
(Note: The only utilities imported are Scanner, File, HashMap, ArrayList, Random, and *)
What I'm looking for is any tips of specific methods I should try and employ or research. Or perhaps a set of code that is fairly functional in doing something similar to what I'm looking for that I can look at and build my own code off of.
When you said the word "word"(That's weird) I assume that they are separated by spaces. If you are reading in the inputs, then just use Scanner... Then:
Scanner input = new Scanner(System.in);
ArrayList<String> words = new ArrayList<String>();
for(int i = 0;i<numberOfWord;i++){
words.add(input.next());// .next() method read data that are separated by space
}
or:
String theLineOfWord;//Given to you
StringTokenizer st = new StringTokenizer(theLinOfWord);//Used to separate words.
ArrayList<String> words = new ArrayList<String>();
while(st.hasMoreTokens()){
words.add(st.nextToken();
}
or:
public static ArrayList<String> getWords(String line){
ArrayList<String> words = new ArrayList<String>();
line += " ";//add a space to ignore the ending case
while(line.length() != 0) {
words.add(line.substring(0, line.indexOf(' ')));//add the word to the list
line = line.substring(line.indexOf(' ') + 1, line.length());//take out the useless string away
}
return words;
}

Ask user to choose from array

I'm practicing Java and wanted to let the user choose an option from the Array such as:
String Food[] = {"Beans","Rice","Spaghetti"};
So far I only know of Scanner, but this is my first program so I don't know much of the subject.
Also, is there a way to print it? besides doing:
System.out.println(Food[0]); //and so on
for every single one of them.
Edit: not a Array list.
You can print the Array not ArrayList by doing:
System.out.println(Arrays.toString(Food));
It will print out: [Beans, Rice, Spaghetti]
If you are talking about an ArrayList, you would have to do:
ArrayList<String> Food = new ArrayList<String>();
Food.add("Beans");
Food.add("Rice");
Food.add("Spaghetti");
Then, you can loop over the ArrayList and build your own String with a StringBuilder
After reading your comment, I think you have a problem structuring your program. I will help you with that. Basically you have to complete these steps:
Program starts
Program outputs the options available in the menu
Program asks the user to choose one of the listed options
User chooses an option
Program will repeat step 3, only if the user wants to keep adding stuff to his order.
If the user does not want anything else, the Program outputs the total cost of the order
Some ideas of how to achieve this the right way:
I would use a class to encapsulate the characteristics of an "order". For instance: description, name, and price are important stuff that you need to be able to track per item.
when you don't know how many times your program will run, you have two options: using a do while loop or a while loop. Try to think in a condition that could make your program run indefinitely a number of times until the user is done. Inside the loop, you could have a sum variable where you would keep track of the items that the user wants.
It is better to keep track of items by just using numbers than Strings. Computers are faster to find stuff this way. So, if you use a HashMap to mock a database system in your program, it would make it better and faster. Then, instead of using if else to control your flow, you could use a switch instead.
I hope this helps.
EDIT: For a more efficient way of printing out the contents of the array, use an enhanced for-loop:
for(String f : Food)
{
System.out.println(f);
}
This is effectively the same as:
for(int i = 0; i < Food.size(); i++)
{
System.out.println(Food[i])
}
If I'm understanding what you're trying to do correctly, I think this should suffice (disclaimer, it's been a while since I've worked with Scanner():
public static void main(String[] args)
{
String[] food = {"Beans","Rice","Spaghetti"}; // Java standards are lowercase for variables and objects, uppercase for class names.
Scanner in = new Scanner(System.in);
System.out.println("What would you like to eat? Options:");
for(String f : food)
{
System.out.println(f);
}
String response = in.next();
boolean validEntry = false;
for(String f: food)
{
if(response.equalsIgnoreCase(f))
{
validEntry = true;
}
}
if(validEntry)
{
System.out.println("You chose " + response);
}
else
{
System.out.println("Invalid entry. Please retry.")
}
}

Remove previous String entries

Not exactly sure how to phrase this question.
I'm writing a spell check program, that reads words from a text file. These words are then added to an ArrayList of type:
ArrayList<String> dictionaryList = new ArrayList<String>();
Now, the program runs as an endless loop (until 'q' is typed), and the user is prompted to search for a word. If the word can be found, the program returns a simple "Found word" message.
Otherwise; take the search term and generate variations of that word. These variations are added to the list:
ArrayList<String> allSimilarWords = new ArrayList<String>();
For instance, the word "coffei" would generate a series of "similar words", one of them being "coffee" (a word in the English language).
Now, seeing that I have both a list of all the dictionary words, as well as a list of the similar words, the program checks if words in allSimilarWords are contained in dictionaryList.
I have checked my generateSimilarWords-method, and it works as expected.
However, there is a problem when asking for user input the second time. The first time (typing "coffei" (where coffee is in the dictionary list)), the program produces the following output:
Enter search term:
coffei
Suggestion for similar words:
-coffee
Since this is an endless loop, the program asks me to enter another word. Now, if I type "banaan" (where banana is in the dictionary), the program produces the following output:
Enter search term:
banaan
Suggestion for similar words:
-coffee
-banana
Hence, it "remembers" me searching for coffei, and provides "coffee" as a suggested word, in addition to the word "banana". I've been trying to figure out why this happens, but cannot find my error. Any help would be highly appreciated. Following is the code:
CODE
//GETTING SIMILAR WORD ARRAYLIST
public ArrayList<ArrayList<String>> getSimilarWords(String searchWord) {
this.searchWord = searchWord;
char[] wordAsCharacterArray = searchWord.toCharArray(); //Convert search String to a character array
//Call helper methods to add the suggested similar words to the similarWordArrayList
similarWordArrayList.add(charSwap(wordAsCharacterArray)); //Add swapped character suggestions
similarWordArrayList.add(charRemove(wordAsCharacterArray)); //Add removed character suggestions
similarWordArrayList.add(charAdd(wordAsCharacterArray)); //Add removed character suggestions
similarWordArrayList.add(charReplace(wordAsCharacterArray)); //Add removed character suggestions
return similarWordArrayList;
}
The similarWordArrayList is later "converted" to an ArrayList containing only String elements, as opposed to being a list of type ArrayList < ArrayList< String > >.
//Method to generate and suggest similar words
private void suggestWords(ArrayList<ArrayList<String>> similarWords) {
allSimilarWords = convertSingleList(similarWords);
String currWord = "";
outer: for(int i = 0; i < allSimilarWords.size(); i++) { //Iterate through the list of similar words
currWord = allSimilarWords.get(i); //Set current similar word to a String variable
for(int j = 0; j < i; j++) {
if(currWord.equalsIgnoreCase(allSimilarWords.get(j))) {
continue outer;
}
}
if(myDictionaryList.contains(currWord)) {
System.out.println("-" + currWord);
}
}
}
Method for finding the String:
public void findString(String word) {
searchTerm = word;
if(myDictionaryList.contains(word)) { //If found
System.out.println("Found word!"); //Notify
}
else {
//Find all similar words
System.out.println("Suggestions for similar words: ");
similarWords = handler.getSimilarWords(searchTerm);
suggestWords(similarWords);
}
}
Any help on how I can fix this, so that the program only prints out suggested words based on the LAST search term (and not remembering previously suggested words), is highly appreciated.
I think, the first thing, you have to do is to clear your arraylist before adding words to it.
//GETTING SIMILAR WORD ARRAYLIST
public ArrayList<ArrayList<String>> getSimilarWords(String searchWord) {
this.searchWord = searchWord;
char[] wordAsCharacterArray = searchWord.toCharArray(); //Convert search String to a character array
//Clear the list before adding words
similarWordArrayList.clear();
//Call helper methods to add the suggested similar words to the similarWordArrayList
similarWordArrayList.add(charSwap(wordAsCharacterArray)); //Add swapped character suggestions
similarWordArrayList.add(charRemove(wordAsCharacterArray)); //Add removed character suggestions
similarWordArrayList.add(charAdd(wordAsCharacterArray)); //Add removed character suggestions
similarWordArrayList.add(charReplace(wordAsCharacterArray)); //Add removed character suggestions
return similarWordArrayList;
}

Word Count from a file

I'm at the start of writing my program (this is for a class) and I'm running into trouble to just write it down. Here's a list of goals I am hoping to meet.
It is a method given a .txt file (using java.io.File)
It needs to read the file and split the words, duplicates are allowed. (I plan to use String.split and util.regex.Pattern to work out whitespace and punctuation)
I'm aiming to put the words in a 1D array and then just find the length of the array.
The problem I'm running into is parsing the txt file. I was told in class that Scanner can, but I'm not finding it while R(ing)TFM. I guess I'm asking for some directions in the API that helps me understand how to read a file with Scanner. Once I can get it to put each word in the array I should be in the clear.
EDIT: I figured out what I needed to do thanks to everyone's help and input. My final snippet ends up looking like this, should anyone in the future come across this question.
Scanner in = new Scanner(file).useDelimiter(" ");
ArrayList<String> prepwords=new ArrayList<String>();
while(in.hasNext())
prepwords.add(in.next());
return prepwords; //returns an ArrayList without spaces but still has punctuation
I had to throw IOExceptions since java hates not being sure a file exists, so if you run into "FileNotFoundException", you need to import and throw IOException. At the very least this worked for me. Thank you everyone for your input!
BufferedReader input = new BufferedReader(new FileReader(filename));
input.readLine();
This is what I use to read from files. Note that you have to handle the IOException
Here is a link to the JSE 6.0 Scanner API
Here is the info you need to complete your project:
1. Use the Scanner(File) constructor.
2. Use a loop that is, essentially this:
a. Scanner blam = new Scanner(theInputFile);
b. Map<String, Integer> wordMap = new HashMap<String, Integer>();
c. Set<String> wordSet = new HashSet<String>();
d. while (blam.hasNextLine)
e. String nextLine = blam.nextLine();
f. Split nextLine into words (head about the read String.split() method).
g. If you need a count of words: for each word on the line, check if the word is in the map, if it is, increment the count. If not, add it to the map. This uses the wordMap (you dont need wordSet for this solution).
h. If you just need to track the words, add each word on the line to the set. This uses the wordSet (you dont need wordMap for this solution).
3. that is all.
If you dont need either the map or the set, then use a List<String> and either an ArrayList or a LinkedList. If you dont need random access to the words, LinkedList is the way to go.
Something simple:
//variables you need
File file = new File("someTextFile.txt");//put your file here
Scanner scanFile = new Scanner(new FileReader(file));//create scanner
ArrayList<String> words = new ArrayList<String>();//just a place to put the words
String theWord;//temporary variable for words
//loop through file
//this looks at the .txt file for every word (moreover, looks for white spaces)
while (scanFile.hasNext())//check if there is another word
{
theWord = scanFile.next();//get next word
words.add(theWord);//add word to list
//if you dont want to add the word to the list
//you can easily do your split logic here
}
//print the list of words
System.out.println("Total amount of words is: " + words.size);
for(int i = 0; i<words.size(); i++)
{
System.out.println("Word at " + i + ": " + words.get(i));
}
Source:
http://www.dreamincode.net/forums/topic/229265-reading-in-words-from-text-file-using-scanner/

Categories