Avatar of thirdeyechai

thirdeyechai's solution

to Anagram in the Java Track

Published at Dec 11 2019 · 0 comments
Instructions
Test suite
Solution

Given a word and a list of possible anagrams, select the correct sublist.

Given "listen" and a list of candidates like "enlists" "google" "inlets" "banana" the program should return a list containing "inlets".

Setup

Go through the setup instructions for Java to install the necessary dependencies:

https://exercism.io/tracks/java/installation

Running the tests

You can run all the tests for an exercise by entering the following in your terminal:

$ gradle test

Use gradlew.bat if you're on Windows

In the test suites all tests but the first have been skipped.

Once you get a test passing, you can enable the next one by removing the @Ignore("Remove to run test") annotation.

Source

Inspired by the Extreme Startup game https://github.com/rchatley/extreme_startup

Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

AnagramTest.java

import org.junit.Ignore;
import org.junit.Test;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

public class AnagramTest {


    @Test
    public void testNoMatches() {
        Anagram detector = new Anagram("diaper");
        assertTrue(detector.match(Arrays.asList("hello", "world", "zombies", "pants")).isEmpty());
    }

    @Ignore("Remove to run test")
    @Test
    public void testDetectMultipleAnagrams() {
        Anagram detector = new Anagram("master");
        List<String> anagrams = detector.match(Arrays.asList("stream", "pigeon", "maters"));
        assertThat(anagrams, allOf(hasItem("maters"), hasItem("stream")));
    }

    @Ignore("Remove to run test")
    @Test
    public void testEliminateAnagramSubsets() {
        Anagram detector = new Anagram("good");
        assertTrue(detector.match(Arrays.asList("dog", "goody")).isEmpty());
    }

    @Ignore("Remove to run test")
    @Test
    public void testDetectLongerAnagram() {
        Anagram detector = new Anagram("listen");
        List<String> anagrams = detector.match(Arrays.asList("enlists", "google", "inlets", "banana"));
        assertThat(anagrams, hasItem("inlets"));
    }

    @Ignore("Remove to run test")
    @Test
    public void testDetectMultipleAnagramsForLongerWord() {
        Anagram detector = new Anagram("allergy");
        List<String> anagrams = detector.match(Arrays.asList("gallery", "ballerina",
                                                             "regally", "clergy",
                                                             "largely", "leading"));
        assertThat(anagrams, allOf(hasItem("gallery"), hasItem("regally"), hasItem("largely")));
    }

    @Ignore("Remove to run test")
    @Test
    public void testDetectsMultipleAnagramsWithDifferentCase() {
        Anagram detector = new Anagram("nose");
        List<String> anagrams = detector.match(Arrays.asList("Eons", "ONES"));
        assertThat(anagrams, allOf(hasItem("Eons"), hasItem("ONES")));
    }

    @Ignore("Remove to run test")
    @Test
    public void testEliminateAnagramsWithSameChecksum() {
        Anagram detector = new Anagram("mass");
        assertTrue(detector.match(Collections.singletonList("last")).isEmpty());
    }

    @Ignore("Remove to run test")
    @Test
    public void testCaseInsensitiveWhenBothAnagramAndSubjectStartWithUpperCaseLetter() {
        Anagram detector = new Anagram("Orchestra");
        List<String> anagrams = detector.match(Arrays.asList("cashregister", "Carthorse", "radishes"));
        assertThat(anagrams, hasItem("Carthorse"));
    }

    @Ignore("Remove to run test")
    @Test
    public void testCaseInsensitiveWhenSubjectStartsWithUpperCaseLetter() {
        Anagram detector = new Anagram("Orchestra");
        List<String> anagrams = detector.match(Arrays.asList("cashregister", "carthorse", "radishes"));
        assertThat(anagrams, hasItem("carthorse"));
    }

    @Ignore("Remove to run test")
    @Test
    public void testCaseInsensitiveWhenAnagramStartsWithUpperCaseLetter() {
        Anagram detector = new Anagram("orchestra");
        List<String> anagrams = detector.match(Arrays.asList("cashregister", "Carthorse", "radishes"));
        assertThat(anagrams, hasItem("Carthorse"));
    }

    @Ignore("Remove to run test")
    @Test
    public void testIdenticalWordRepeatedIsNotAnagram() {
        Anagram detector = new Anagram("go");
        assertTrue(detector.match(Collections.singletonList("go Go GO")).isEmpty());
    }

    @Ignore("Remove to run test")
    @Test
    public void testAnagramMustUseAllLettersExactlyOnce() {
        Anagram detector = new Anagram("tapper");
        assertTrue(detector.match(Collections.singletonList("patter")).isEmpty());
    }

    @Ignore("Remove to run test")
    @Test
    public void testWordsAreNotAnagramsOfThemselvesCaseInsensitive() {
        Anagram detector = new Anagram("BANANA");
        assertTrue(detector.match(Arrays.asList("BANANA", "Banana", "banana")).isEmpty());
    }

    @Ignore("Remove to run test")
    @Test
    public void testWordsOtherThanThemselvesCanBeAnagrams() {
        Anagram detector = new Anagram("LISTEN");
        List<String> anagrams = detector.match(Arrays.asList("Listen", "Silent", "LISTEN"));
        assertThat(anagrams, hasItem("Silent"));
    }

}
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

class Anagram {

    private String word;

    public Anagram(String s) {
        word = s;
    }

    /** The match method determines which words in a list are anagrams of this word
    *  return a list of anagrams */
    public List<String> match(List<String> wordList) {
        List<String> s1 = new LinkedList<>();
        List<String> s2 = new LinkedList<>();
        // rearrange word to alphabetical character order e.g "hello" becomes "ellho"
        char[] charArray = word.toLowerCase().toCharArray();
        Arrays.sort(charArray);
        String sortedString1 = new String(charArray);

        for (String s : wordList) {
            // Words cannot be anagrams of themselves e.g "BANANA" is not an anagram of "banana"
            if (!word.equalsIgnoreCase(s)) {
                // potential anagrams must be of equal length to a word
                if (word.length() == s.length()) {
                    s1.add(s);
                }
            }
        }
        for (String s : s1) {
            // Reorder words to alphabetical character order
            charArray = s.toLowerCase().toCharArray();
            Arrays.sort(charArray);
            String sortedString2 = new String(charArray);

            // anagrams should have the same alphabetical character ordering
            // e.g "master" and "stream" both are ordered alphabetically as "aemrst"
            if (sortedString1.equals(sortedString2)) {
                s2.add(s);
            }
        }
        return s2;
    }
}

Community comments

Find this solution interesting? Ask the author a question to learn more.

thirdeyechai's Reflection

I'm not too pleased with the quality of this solution. I need to spend some time refactoring it to improve readability, efficiency and brevity. Think of it as a first draft.