HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Finding permutations of a word

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
permutationswordfinding

Problem

This was a basic anagram problem. Take an input word, find all its permutations, then check a dictionary file to see what if any of those are real words.

Dictionary file

My input data:

8
lasting
lameness
severer
lapse
alerting
medical
tasking
crates


My answer:

3 3 3 5 4 4 3 6


The code works slowly, as in, it took maybe a minute. Aside from any other criticism, I'm curious to the following:

-
Why are these two so different in speed? Casting as String was much faster:

String current = (String) iter.next();


and

String current = iter.next().toString();


-
Is there a smarter way than looping through the dictionary every single time for every permutation of a word?

-
Is there a better data structure for the dictionary than an ArrayList? If so, why?

```
package com.secryption.CA127Anagrams;

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

/**
* Created by bmarkey on 11/26/15.
*/

public class Anagrams {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
Scanner inFile;
System.out.println("Enter Data: ");
int testCases = Integer.parseInt(in.nextLine());
ArrayList dictionary = new ArrayList<>();

try {
File file = new File("/home/me/words.txt");
inFile = new Scanner(file);

while (inFile.hasNextLine()) {
dictionary.add(inFile.nextLine());
}
inFile.close();

} catch (Exception e) {
e.printStackTrace();
}

for (int i = 0; i allCombos = getPermutations(inputStr);

Iterator iter = allCombos.iterator();

while (iter.hasNext()) {
String current = (String) iter.next();
// String current = iter.next().toString();
for( int j = 0; j getPermutations(String str) {
Set permResult = new HashSet();

if (str == null) {
return null;
} else if (str.le

Solution

The algorithm

Given two string \$S\$ and \$Z\$, \$S\$ is a permutation of \$Z\$ if and only if they have the same multiset of characters. The fastest way of checking this is to sort the characters in each of the two strings which will produce two new strings \$S'\$ and \$Z'\$. Finally, if \$S' = Z'\$, \$S\$ is a permutation of \$Z\$. For example: \$S = \text{stop}\$, \$Z = \text{spot}\$, \$S' = Z' = \text{opst}\$.

You can improve the performance:

Create a HashMap, call it "map",
For each "word" in the word file, do:
    Sort "word" by characters ("fdsbs" -> "bdfss")
    If "word" is not in "map":
        Put "word" into "map" with value "1"
    Else:
        map.put(word, map.get(word) + 1) # Increment count


In order to process an input word, just sort it by characters and do a simple lookup from map. Summa summarum:

import java.util.*;
import java.io.File;
import java.io.FileNotFoundException;

public class Anagrams {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.println("Enter number of test cases: ");
        int testCases = Integer.parseInt(in.nextLine());

        File file = new File("/path/to/words.txt");
        Map map = readFile(file);

        for (int i = 0; i  readFile(File file) {
        Map map = new HashMap<>();

        try (Scanner fileScanner = new Scanner(file)) {
            while (fileScanner.hasNext()) {
                String word = sort(fileScanner.next());

                if (map.containsKey(word)) {
                    map.put(word, map.get(word) + 1);
                } else {
                    map.put(word, 1);
                }
            }
        } catch (FileNotFoundException ex) {
            return null;
        }

        return map;
    }

    private static String sort(String input) {
        char[] chars = input.toCharArray();
        Arrays.sort(chars);
        return new String(chars);
    }
}

Code Snippets

Create a HashMap<String, Integer>, call it "map",
For each "word" in the word file, do:
    Sort "word" by characters ("fdsbs" -> "bdfss")
    If "word" is not in "map":
        Put "word" into "map" with value "1"
    Else:
        map.put(word, map.get(word) + 1) # Increment count
import java.util.*;
import java.io.File;
import java.io.FileNotFoundException;

public class Anagrams {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.println("Enter number of test cases: ");
        int testCases = Integer.parseInt(in.nextLine());

        File file = new File("/path/to/words.txt");
        Map<String, Integer> map = readFile(file);

        for (int i = 0; i < testCases; i++) {
            String s = sort(in.nextLine());
            System.out.println(map.getOrDefault(s, 0) - 1);
        }
    }

    private static Map<String, Integer> readFile(File file) {
        Map<String, Integer> map = new HashMap<>();

        try (Scanner fileScanner = new Scanner(file)) {
            while (fileScanner.hasNext()) {
                String word = sort(fileScanner.next());

                if (map.containsKey(word)) {
                    map.put(word, map.get(word) + 1);
                } else {
                    map.put(word, 1);
                }
            }
        } catch (FileNotFoundException ex) {
            return null;
        }

        return map;
    }

    private static String sort(String input) {
        char[] chars = input.toCharArray();
        Arrays.sort(chars);
        return new String(chars);
    }
}

Context

StackExchange Code Review Q#112319, answer score: 6

Revisions (0)

No revisions yet.