I need to read the user input and compare this to a dictionary.txt. The user may input any number of characters and the program must return all the words in the English language that can be made from these characters. The letters can be used in any order and may only be used once.
For example:
User Input: "odg"
Output: "dog" , "god" ... and any others
After quite a substantial amount of research, I have come up with the following partial solution:
Read user input
Convert to an array of characters
Loop through the document depending on array length
Using indexOf to compare each character in this array to each line, then printing the word/s which do not return -1
How do I compare a set of characters inputted by the user to those found in a text file (dictionary) ? The characters do not have to be in any order to match .(as seen in the example used above)
Bear with me here, I know this must be one of the most inefficient ways to do such a task! Any further ideas on how to implement my original idea would be appreciated, while I am also open to any new and more efficient methods to perform this operation.
Below is what I have come up with thus far:
public static void main(String[] args) throws FileNotFoundException {
BufferedReader reader1 = new BufferedReader(new FileReader(FILENAME));
Scanner sc = new Scanner(System.in);
String line;
ArrayList<String> match = new ArrayList<>();
System.out.println("Enter characters to see which english words match: ");
String userInput = sc.next();
char arr[] = userInput.toCharArray();
int i;
try {
while ((line = reader1.readLine()) != null) {
for (i=0; i < arr.length; i++)
{
if ((line.indexOf(userInput.charAt(i)) != -1) && (line.length() == arr.length)) {
match.add(line);
}
else {
// System.out.println("no matches");
}
}
}
System.out.println(match);
}
catch (IOException e) {
e.printStackTrace();
}
**Current results: **
Words in text file:
cab
dog
god
back
dogs
quick
User input: "odg"
Program output:
[god, god, god, dog, dog, dog]
The program should return all words in the dictionary that can be made out of the string entered by the user I am managing to return both instances in this case, however, each are displayed for three times (arr.length).
First of all, interesting question. I implemented my solution and Ole V.V's solution. Here are the codes based on your post. I test the only test case you provided, not sure whether this is what you want. Let me know if it is not working as you expected.
Solution One: counting O(nk)
public static void main(String[] args) throws IOException {
BufferedReader reader1 = new BufferedReader(new FileReader(FILENAME));
Scanner sc = new Scanner(System.in);
System.out.println("Enter characters to see which english words match: ");
String userInput = sc.next();
Map<Character, Integer> counter = count(userInput);
String line;
while ((line = reader1.readLine()) != null) {
Map<Character, Integer> lineCounter = count(line);
if(lineCounter.equals(counter)) {
System.out.println(line);
}
}
}
public static Map<Character, Integer> count(String input) {
Map<Character, Integer> result = new HashMap<Character, Integer>();
for (char c: input.toCharArray()) {
result.putIfAbsent(c, 0);
result.put(c, result.get(c) + 1);
}
return result;
}
Solution Two: sorting O(nk)
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader(FILENAME));
Scanner sc = new Scanner(System.in);
System.out.println("Enter characters to see which english words match: ");
String userInput = sc.next();
userInput = sort(userInput);
String line;
while ((line = reader.readLine()) != null) {
String sortedLine = sort(line);
if(sortedLine.equals(userInput)) {
System.out.println(new String(line));
}
}
}
// counting sort
public static String sort(String input) {
char c[] = input.toCharArray();
int length = c.length;
char output[] = new char[length];
int count[] = new int[256];
for (int i = 0; i < length; i++) {
count[c[i]] = count[c[i]] + 1;
}
for (int i = 1; i <= 255; i++) {
count[i] += count[i - 1];
}
for (int i = 0; i < length; i++) {
output[count[c[i]] - 1] = c[i];
count[c[i]] = count[c[i]] - 1;
}
return new String(output);
}
The standard solution to this kind of problem is: sort the characters of the user input. So odg will become dgo and back will become abck. For each word in the dictionary, do the same sorting. So cab will become abc and dog will be dgo — hey, that’s the same as the first user input, so now we know that this word should be output.
The strong point with this solution is you make sure every letter is used exactly once. It even takes duplicate letters into account: if the same letter comes twice in the user input, it will only find words that also contain that letter exactly twice.
If you like, you can prepare your word list in advance by building a map where the keys are the alphabetically sorted words and the values are lists of words that contain those same letters. So key dgo will map to a list of [dog, god]. Then you just have to sort the input and make a lookup.
I'll show you a solution that is easy to understand and implement but not the fastest available:
Possible solution: Array sorting
Treat input string and dictionary word as array of chars, sort them, then compare them:
public static boolean stringsMatchSort(String a, String b) {
// Different length? Definitely no match!
if (a.length() != b.length()) {
return false;
}
// Turn both Strings to char arrays
char[] charsA = a.toCharArray();
char[] charsB = b.toCharArray();
// Sort both arrays
Arrays.sort(charsA);
Arrays.sort(charsB);
// Compare them, if equal: match!
return Arrays.equals(charsA, charsB);
}
Note how I made the meat of your program / problem into a method. You can then easily use that method in a loop that iterates over all words of your dictionary. The method doesn't care where the words come from: a file, a collection, additional user input, the network, etc.
It also helps to simplify your program by dividing it into smaller parts, each with a smaller responsibility. This is commonly known as divide & conquer and is one of the most valuable strategies for both, new and old programmers alike, when it comes to tackling complicated problems.
Other solutions: Prime numbers, HashMaps, ...
There are other (including faster and more elegant) solutions available. Take a look at these related questions, which yours is pretty much a duplicate of:
"How to check if two words are anagrams"
"finding if two words are anagrams of each other"
Additional notes
Depending on your application, it might be a good idea to first read the dictionary into a suitable collection. This would be especially helpful if you perform multiple "queries" against the same dictionary. Or, if the dictionary is really huge, you could already strip out duplicates during the creation of the collection.
Related
I have a java program that reads a txt file and counts the words in that file. I setup my program so the String read from the txt file is saved as an ArrayList, and my variable word contains that ArrayList. The issue with my code is that my if statement does not seem to add a value to my count variable each time it detects space in the word string, it seems to only run the if statement once. How can I make it so the if statement finds a space, adds a +1 to my counter value, removes the space, and looks for the next space in the word variable's string? Here is the code:
import java.io.*;
import java.util.*;
public class FrequencyCounting
{
public static void main(String[] args) throws FileNotFoundException
{
// Read-in text from a file and store each word and its
// frequency (count) in a collection.
Scanner inputFile = new Scanner(new File("phrases.txt"));
String word= " ";
Integer count = 0;
List<String> ma = new ArrayList<String>();
while(
inputFile.hasNextLine()) {
word = word + inputFile.nextLine() + " ";
}
ma.add(word);
System.out.println(ma);
if(word.contains(" ")) {
ma.remove(" ");
count++;
System.out.println("does contain");
}
else {
System.out.println("does not contain");
}
System.out.println(count);
//System.out.println(ma);
inputFile.close();
// Output each word, followed by a tab character, followed by the
// number of times the word appeared in the file. The words should
// be in alphabetical order.
; // TODO: Your code goes here.
}
}
When I execute the program, I get a value of 1 for the variable count and I get a returned string representation of the txt file from my phrases.txt
phrases.txt is :
my watch fell in the water
time to go to sleep
my time to go visit
watch out for low flying objects
great view from the room
the world is a stage
the force is with you
you are not a jedi yet
an offer you cannot refuse
are you talking to me
Your if statement is not inside any loop, so it will only execute once.
A better approach, which would save a shit ton of runtime, is to read each line like you already do, use the String.split() method to split it on spaces, then add each element of the returned String[] to your list by using the ArrayList.addAll() method (if that one exist, otherwise (optionally, ensure the capacity and) add the elements one by one).
Then count by using the ArrayList.size() method to get the number of elements.
Based on the comments in your code :
// Read-in text from a file and store each word and its
// frequency (count) in a collection.
// Output each word, followed by a tab character, followed by the
// number of times the word appeared in the file. The words should
// be in alphabetical order.
My understanding is that you need to store count for every word, rather having a total count of words. For storing count for every word which should be stored itself in alphabetical order, it is better to go with a TreeMap.
public static void main(String[] args) {
Map<String, Integer> wordMap = new TreeMap<String, Integer>();
try {
Scanner inputFile = new Scanner(new File("phrases.txt"));
while(inputFile.hasNextLine()){
String line = inputFile.nextLine();
String[] words = line.split(" ");
for(int i=0; i<words.length; i++){
String word = words[i].trim();
if(word.length()==0){
continue;
}
int count = 0;
if(wordMap.containsKey(word)){
count = wordMap.get(word);
}
count++;
wordMap.put(word, count);
}
}
inputFile.close();
for(Entry<String,Integer> entry : wordMap.entrySet()){
System.out.println(entry.getKey()+"\t"+entry.getValue());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
What is your goal here ? Do you just want to read the file and count numbers of words?
You need to use a while loop instead of an if statement that'll just run once. Here's a better way to do what you want to do:
Scanner inputFile = new Scanner(new File("phrases.txt"));
StringBuilder sb = new StringBuilder();
String line;
int totalCount = 0;
while(inputFile.hasNextLine()) {
line = inputFile.nextLine();
sb.append(line).append("\n"); // This is more efficient than concatenating strings
int spacesOnLine = countSpacesOnLine(line);
totalCount += spacesOnLine;
// print line and spacesOnLine if you wish to here
}
// print text file
System.out.println(sb.toString());
// print total spaces in file
System.out.println("Total spaces" + totalCount);
inputFile.close();
Then add a method that counts the spaces on a line:
private int countSpacesOnLine(String line) {
int totalSpaces = 0;
for(int i = 0; i < line.length(); i++) {
if (line.charAt(i) == ' ')
totalSpaces += 1;
}
return totalSpaces;
}
You can achieve your objective with the following one liner too:
int words = Files.readAllLines(Paths.get("phrases.txt"), Charset.forName("UTF-8")).stream().mapToInt(string -> string.split(" ").length).sum();
probably I am late, but here is c# simple version:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace StackOverflowAnswers
{
class Program
{
static void Main(string[] args)
{
string contents = File.ReadAllText(#"C:\temp\test.txt");
var arrayString = contents.Split(' ');
Console.WriteLine("Number of Words {0}", arrayString.Length);
Console.ReadLine();
}
}
}
ok so the goal of my program (very basic at this point) is to take in a string of words for example: ("i give you 34 and you give me 50") and what i want is to populate my array with every occurrence of a number in the string. all this gives me back is the last number i give the code ive checked the whole array and all i can ever get back is the last number.
public static void main(String[] args) throws IOException {
BufferedReader read= new BufferedReader(new InputStreamReader(System.in));
String phrase;
int count = 0;
int[] numbers = new int[5];
phrase = read.readLine();
for (int i = 0; i < phrase.length()-1; i++){
if (phrase.substring(i).matches("((-|\\+)?[0-9]+(\\.[0-9]+)?)+")){
numbers[count] = Integer.parseInt(phrase.substring(i));
count++;
System.out.println(numbers[0]);
}
}
}
Some things to point out.
I don't know why you are using a substring method on the input.
You only printed numbers[0]. An array isn't good anyway because you never know how many numbers the input will have.
You are using parseInt, when you group on decimal numbers.
Pattern & Matcher would be recommended over String#matches
Here is the corrected code
List<Double> numbers = new ArrayList<>();
Pattern p = Pattern.compile("([-+]?[0-9]+(?:\\.[0-9]+)?)");
String phrase = "I give you 30, you give me 50. What about 42.1211?";
Matcher m = p.matcher(phrase);
while (m.find()) {
numbers.add(Double.parseDouble(m.group()));
}
System.out.println(numbers); // [30.0, 50.0, 42.1211]
I am just starting out in Java so I appreciate your patience. Anyways, I am writing a word count program as you can tell by the title, I am stuck at the numWords function below the for loop, I am not sure what I should set it equal to. If someone could set me in the right direction that would be awesome. Thank you. Here is all of my code thus far, let me know if I not specific enough in what I am asking, this is my first post. Thanks again.
import java.util.Scanner;
public class WCount {
public static void main (String[] args) {
Scanner stdin = new Scanner(System.in);
String [] wordArray = new String [10000];
int [] wordCount = new int [10000];
int numWords = 0;
while(stdin.hasNextLine()){
String s = stdin.nextLine();
String [] words = s.replaceAll("[^a-zA-Z ]", "").toLowerCase().split("\\s\
+");
for(int i = 0; i < words.length; i++){
numWords = 0;
}
}
}
}
If your code is intended to just count words, then you don't need to iterate through the words array at all. In other words, replace your for loop with just:
numWords += words.length;
Most likely a simpler approach would be to look for sequences of alpha characters:
Matcher wordMatch = Pattern.compile("\\w+").matcher();
while (wordMatch.find())
numWords++;
If you need to do something with the words (such as store them in a map to a count) then this approach will make that simpler:
Map<String,Integer> wordCount = new HashMap<>();
Matcher wordMatch = Pattern.compile("\\w+").matcher();
while (wordMatch.find()) {
String word = wordMatch.group();
int count = wordCount.getOrDefault(word, 0);
wordCount.put(word, count + 1);
}
Don't worry. We were all beginners once.
First of all, you don't need to do the loop because "length" attribute already has it. But, if you want to practice with loops is so easy as increasing the counter each time the iterator advances and that's it.
numWords++;
Hint: Read the input
String sentence = stdin.nextLine();
Split the string
String [] words = sentence.split(" ");
Number of words in a sentence
System.out.println("number of words in a sentence are " + words.length);
You mentioned in comments that you would also like to print the line in alphabetical order. For that Java got you covered:
Arrays.sort(words);
The best way to count the amount of words in a String String phrase is simply to get a String array from it using the String method split String[] words = phrase.split(" ") and giving it as argument the space itself, this will return a String array with each different words, then you can simple check its lengthwords.length and this will give you the exact number.
I’ve written a small program that reads text from a file and prints the reverse of every word within the text file.
Now I want to try and efficiently find if all the words that are reverse are actual words in the english dictionary and prints these out as a list sorted by string length with each pair occurring once.
Here’s what I’ve been able to write so far
String word;
String[] reverse;
int wordLength;
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws FileNotFoundException {
// TODO code application logic here
Map<Integer, String> aMap2 = new HashMap<Integer, String>();
String mString = "";
int mInt = 0;
String word;
String[] reverse = new String[1];
int wordLength;
FileInputStream fileIn = new FileInputStream ("example.txt”);
//text in the text file - "what he saw was not part of a trap just a ton of crazy snow"
Scanner scan = new Scanner(fileIn);
Scanner lineScanner;
Scanner wordscanner = null;
String aLine;
String aWord;
while(scan.hasNextLine()){
aLine = scan.nextLine();
lineScanner = new Scanner(aLine);
lineScanner.useDelimiter(",");
word = lineScanner.next();
System.out.println(word);
try{
wordscanner = new Scanner(new File("example.txt"));
} catch(FileNotFoundException x){
x.printStackTrace();
}
while(wordscanner.hasNext()){
Scanner newWord = new Scanner(wordscanner.next());
boolean b;
while(b = newWord.hasNext()){
String foundWord = newWord.next();
wordLength = foundWord.length();
char ch = ' ';
String reverseWord = “";
for(int i = wordLength-1; i >= 0; i--){
ch = foundWord.charAt(i);
//System.out.println(ch);
reverseWord = reverseWord + ch;
}
for(int k = 0; k < reverse.length; k++){
reverse[k] = foundWord + ", " + reverseWord;
mString = reverse[k];
mInt = reverse[k].length();
aMap2.put(mInt, mString);
}
}
}
}
Map<Integer, String> sorted = sortByKeys(aMap2);
System.out.println(sorted);
}
public static <K extends Comparable,V extends Comparable> Map<K,V> sortByKeys(Map<K,V> map){
List<K> keys = new LinkedList<K>(map.keySet());
Collections.sort(keys);
//LinkedHashMap will keep the keys in the order they are inserted
//which is currently sorted on natural ordering
Map<K,V> sortedMap = new LinkedHashMap<K,V>();
for(K key: keys){
sortedMap.put(key, map.get(key));
}
return sortedMap;
// http://javarevisited.blogspot.co.uk/2012/12/how-to-sort-hashmap-java-by-key-and-value.html
}
This gives me the following result
what he saw was not part of a trap just a ton of crazy snow
{4=a, a, 6=of, fo, 8=ton, not, 10=snow, wons, 12=crazy, yzarc}
Now, my problem is how do I cross check the reverse of the words (preferably character by character) with a dictionary text file to see if the reverse words make up meaningful words?
I’ve looked around here and I’ve seen some suggestions but I couldn’t find one that helped me understand how to solve my current issue.
I’ve thought of using a Binary Search Tree, my idea was to load the dictionary file into a Binary Tree and search the Tree to see if the reverse words make up existing words then print them out. But I’ve been unable to proceed due to the fact that I don’t understand how to get a string from one text file then compare it with a second text file.
Lastly, can you help point me in the right direction in getting the words to appear in a 2D Array, please?! I tried it a few times but it just doesn’t work and I’m out of ideas :( !
THanks in advance.
You can read the dictionary file line by line. assuming that each line contains a single word you need to put that line into a hashset. Then you can go over the words that you read from the first file, reverse each of them and check that the reversed word is in that hash set.
public Set<String> readFileIntoSet(String fileName) {
Set<String> result = new HashSet<String>();
for (Scanner sc = new Scanner(new File(fileName)); sc.hasNext(); )
result.add(sc.nextLine());
return result;
}
In your main method add a call to readFileIntoSet:
Set<String> dictionary = readFileIntoSet("your_dictionary_file");
Then, after you find the reversed word, check that it appears in the dictionary:
if (dictionary.contains(reverseWord))
system.out.println("this word: " + reverseWord + " appears in the dictionary!");
Please also note that the String class offers a "reverse" method. Thus, you can get rid of the for(int i = wordLength-1; i >= 0; i--){ ... } loop and just use reverseWord = foundWord.reverse();
Hi I'm in a programming class over the summer and am required to create a program that reads input from a file. The input file includes DNA sequences ATCGAGG etc and the first line in the file states how many pairs of sequences need to be compared. The rest are pairs of sequences. In class we use the Scanner method to input lines from a file, (I read about bufferedReader but we have not covered it in class so not to familiar with it) but am lost on how to write the code on how to compare two lines from the Scanner method simultaneously.
My attempt:
public static void main (String [] args) throws IOException
{
File inFile = new File ("dna.txt");
Scanner sc = new Scanner (inFile);
while (sc.hasNextLine())
{
int pairs = sc.nextLine();
String DNA1 = sc.nextLine();
String DNA2 = sc.nextLine();
comparison(DNA1,DNA2);
}
sc.close();
}
Where the comparison method would take a pair of sequences and output if they had common any common characters. Also how would I proceed to input the next pair, any insight would be helpful.. Just stumped and google confused me even further. Thanks!
EDIT:
Here's the sample input
7
atgcatgcatgc
AtgcgAtgc
GGcaAtt
ggcaatt
GcT
gatt
aaaaaGTCAcccctccccc
GTCAaaaaccccgccccc
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
gctagtacACCT
gctattacGcct
First why you are doing:
while (sc.hasNextLine())
{
int pairs = sc.nextLine();
While you have pairs only in one line not pairs and two lines of input, but number of lines once? Move reading pairs from that while looop and parse it to int, then it does not matter but you could use it to stop reading lines if you know how many lines are there.
Second:
throws IOException
Might be irrelevant but, really you don't know how to do try catch and let's say skip if you do not care about exceptions?
Comparision, if you read strings then string has method "equals" with which you can compare two strings.
Google will not help you with those problems, you just don't know it all, but if you want to know then search for basic stuff like type in google "string comparision java" and do not think that you can find solution typing "Reading two lines from an input file using Scanner" into google, you have to go step by step and cut problem into smaller pieces, that is the way software devs are doing it.
Ok I have progz that somehow wokrked for me, just finds the lines that have something and then prints them out even if I have part, so it is brute force which is ok for such thing:
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class program
{
public static void main (String [] args) throws IOException
{
File inFile = new File ("c:\\dna.txt");
Scanner sc = new Scanner (inFile);
int pairs = Integer.parseInt(sc.nextLine());
for (int i = 0; i< pairs-1; i++)
{
//ok we have 7 pairs so we do not compare everything that is one under another
String DNA1 = sc.nextLine();
String DNA2 = sc.nextLine();
Boolean compareResult = comparison(DNA1,DNA2);
if (compareResult){
System.out.println("found the match in:" + DNA1 + " and " + DNA2) ;
}
}
sc.close();
}
public static Boolean comparison(String dna1, String dna2){
Boolean contains = false;
for (int i = 0; i< dna1.length(); i++)
{
if (dna2.contains(dna1.subSequence(0, i)))
{
contains = true;
break;
}
if (dna2.contains(dna1.subSequence(dna1.length()-i,dna1.length()-1 )))
{
contains = true;
break;
}
}
return contains;
}
}