-1

I recently took a quiz asking me to determine if elements in an array were anagrams. I completed an implementation, but upon running their tests, I only passed 1 of 5 test cases. The problem is, they wouldn't allow me to see what the tests were, so I'm really unsure about what I failed on. I've recreated my answer below, which basically multiplies the letters in a word and adds this number to an array. It then compares the numbers in one array to the numbers in the other, and prints true if they are the same. I'm basically asking what are some scenarios in which this would fail, and how would I modify this code to account for these cases?

public class anagramFinder {
    public static void main (String[] args){
        String[] listOne = new String[5];
        listOne[0] = "hello";
        listOne[1] = "lemon";
        listOne[2] = "cheese";
        listOne[3] = "man";
        listOne[4] = "touch";

        String[] listTwo = new String[5];
        listTwo[0] = "olleh";
        listTwo[1] = "melon";
        listTwo[2] = "house";
        listTwo[3] = "namer";
        listTwo[4] = "tou";

        isAnagram(listOne,listTwo);
    }

    public static void isAnagram(String[] firstWords, String[] secondWords){
        int firstTotal = 1;
        int secondTotal = 1;
        int[] theFirstInts = new int[firstWords.length];
        int[] theSecondInts = new int[secondWords.length];

        for(int i = 0;i<firstWords.length;i++){
            for(int j = 0;j<firstWords[i].length();j++){
                firstTotal = firstTotal * firstWords[i].charAt(j);
            }

            theFirstInts[i] = firstTotal;
            firstTotal = 1;
        }

        for(int i = 0;i<secondWords.length;i++){
            for(int j = 0;j<secondWords[i].length();j++){
                secondTotal = secondTotal * secondWords[i].charAt(j);
            }

            theSecondInts[i] = secondTotal;
            secondTotal = 1;
        }

        for(int i=0;i<minimum(theFirstInts.length,theSecondInts.length);i++){
            if(theFirstInts[i] == theSecondInts[i]){
                System.out.println("True");
            } else {
                System.out.println("False");
            }
        }
    }
    public static int minimum(int number,int otherNumber){
        if(number<otherNumber){
            return number;
        } else {
            return otherNumber;   
        }
    }
}

In my above example that I run in the main method, this prints True True False False False, which is correct

Alex
  • 3,111
  • 6
  • 27
  • 43
arc4randall
  • 3,275
  • 3
  • 27
  • 40
  • I have no idea what that code is supposed to be doing. – Hot Licks Jul 12 '14 at 20:11
  • 2
    You should really talk to your professor or TA about this code (on the quiz). They need to know why you are having problems. Also, when I was in college, we were taught "hand execution." Run this code yourself, by hand, with some different inputs and try discover where the errors might be. – markspace Jul 12 '14 at 20:18
  • It will tend to fail for any word over about 5 characters, since an `int` will overflow. Also, it's not clear that you can't have two different combos of letters produce the same product. – Hot Licks Jul 12 '14 at 20:20
  • 1
    And learn how to write comments. In your comments state what you *know* to be true at each step in the computation. – Hot Licks Jul 12 '14 at 20:21
  • well it was a quiz on a website, not for school, so I have no way of getting the test cases – arc4randall Jul 12 '14 at 21:22
  • I've found the 4th way that eluded me last night. – laune Jul 13 '14 at 04:09

2 Answers2

2

Copying my answer from a similar question.

Here's a simple fast O(n) solution without using sorting or multiple loops or hash maps. We increment the count of each character in the first array and decrement the count of each character in the second array. If the resulting counts array is full of zeros, the strings are anagrams. Can be expanded to include other characters by increasing the size of the counts array.

class AnagramsFaster{

    private static boolean compare(String a, String b){
        char[] aArr = a.toLowerCase().toCharArray(), bArr = b.toLowerCase().toCharArray();
        if (aArr.length != bArr.length)
            return false;
        int[] counts = new int[26]; // An array to hold the number of occurrences of each character
        for (int i = 0; i < aArr.length; i++){
            counts[aArr[i]-97]++;  // Increment the count of the character at i
            counts[bArr[i]-97]--;  // Decrement the count of the character at i
        }
        // If the strings are anagrams, the counts array will be full of zeros
        for (int i = 0; i<26; i++)
            if (counts[i] != 0)
                return false;
        return true;
    }

    public static void main(String[] args){
        System.out.println(compare(args[0], args[1]));
    }
}
Aswin
  • 541
  • 4
  • 13
1

The idea of multiplying ASCII codes isn't bad, but not perfect. It would need a deep analysis to show that two different words could have the same products, with the given range of 'a' to 'z', and within reasonable length.

One conventional approach would be to create a Map for counting the letters, and compare the Maps.

Another one would sort the letters and compare the sorted strings.

A third one would iterate over the letters of the first word, try to locate the letter in the second word, and reduce the second word by that letter.

I can't think of a fourth way, but I'm almost certain there is one ;-)

Later

Well, here's a fourth way: assign 26 prime numbers to 'a' to 'z' and (using BigInteger) multiply the primes according to the letters of a word. Anagrams produce identical products.

laune
  • 31,114
  • 3
  • 29
  • 42
  • ok, I get why this is better. The fourth method was basically what I was going for, but I guess if the numbers aren't prime you could end up having different letter combinations equaling the same product. Thanks for the clarification – arc4randall Jul 13 '14 at 04:19
  • Well, that, and the necessity to compute the product with an "unlimited" number of digits. – laune Jul 13 '14 at 07:44