From d0a9b576947dbd2e5f98f94063c0e60160fcc793 Mon Sep 17 00:00:00 2001 From: wugangca Date: Sat, 7 Dec 2019 13:35:19 -0700 Subject: [PATCH] BAEL-3418 Check If Two Strings Are Anagrams in Java (#8139) * BAEL-3418 Check If Two Strings Are Anagrams in Java * BAEL-3418 Update code based on code review feedback. * BAEL-3418 Update comments and rename constant based on code review feedback. * Move the repository to core-java-modules/core-java-string-algorithms-3/ * BAEL-3418 Only support alpha characters for the anagram * BAEL-3418 use preprocess in a separate method * BAEL-3418 Remove the temp variables --- .../core-java-string-algorithms-3/README.md | 5 ++ .../core-java-string-algorithms-3/pom.xml | 69 ++++++++++++++++++ .../java/com/baeldung/anagram/Anagram.java | 62 ++++++++++++++++ .../com/baeldung/anagram/AnagramUnitTest.java | 72 +++++++++++++++++++ 4 files changed, 208 insertions(+) create mode 100644 core-java-modules/core-java-string-algorithms-3/README.md create mode 100644 core-java-modules/core-java-string-algorithms-3/pom.xml create mode 100644 core-java-modules/core-java-string-algorithms-3/src/main/java/com/baeldung/anagram/Anagram.java create mode 100644 core-java-modules/core-java-string-algorithms-3/src/test/java/com/baeldung/anagram/AnagramUnitTest.java diff --git a/core-java-modules/core-java-string-algorithms-3/README.md b/core-java-modules/core-java-string-algorithms-3/README.md new file mode 100644 index 0000000000..3aa31cea53 --- /dev/null +++ b/core-java-modules/core-java-string-algorithms-3/README.md @@ -0,0 +1,5 @@ +## Java String Algorithms + +This module contains articles about string-related algorithms. + +### Relevant Articles: diff --git a/core-java-modules/core-java-string-algorithms-3/pom.xml b/core-java-modules/core-java-string-algorithms-3/pom.xml new file mode 100644 index 0000000000..a5dd31c762 --- /dev/null +++ b/core-java-modules/core-java-string-algorithms-3/pom.xml @@ -0,0 +1,69 @@ + + 4.0.0 + core-java-string-algorithms-3 + 0.1.0-SNAPSHOT + jar + core-java-string-algorithms-3 + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + + + + + + org.assertj + assertj-core + ${assertj.version} + test + + + com.google.guava + guava + 28.1-jre + + + + org.junit.jupiter + junit-jupiter-api + ${junit-jupiter-api.version} + test + + + + + core-java-string-algorithms-3 + + + src/main/resources + true + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${java.version} + ${java.version} + -parameters + + + + + + + 3.8.1 + 3.6.1 + 27.0.1-jre + 5.3.1 + + + diff --git a/core-java-modules/core-java-string-algorithms-3/src/main/java/com/baeldung/anagram/Anagram.java b/core-java-modules/core-java-string-algorithms-3/src/main/java/com/baeldung/anagram/Anagram.java new file mode 100644 index 0000000000..360bc5c6de --- /dev/null +++ b/core-java-modules/core-java-string-algorithms-3/src/main/java/com/baeldung/anagram/Anagram.java @@ -0,0 +1,62 @@ +package com.baeldung.anagram; + +import java.util.Arrays; +import com.google.common.collect.HashMultiset; +import com.google.common.collect.Multiset; + +public class Anagram { + // This definition only works for single byte encoding character set. + // For multibyte encoding, such as UTF-8, 16, 32 etc., + // we need to increase this number so that it can contain all possible characters. + private static int CHARACTER_RANGE = 256; + + public boolean isAnagramSort(String string1, String string2) { + if (string1.length() != string2.length()) { + return false; + } + char[] a1 = string1.toCharArray(); + char[] a2 = string2.toCharArray(); + Arrays.sort(a1); + Arrays.sort(a2); + return Arrays.equals(a1, a2); + } + + public boolean isAnagramCounting(String string1, String string2) { + if (string1.length() != string2.length()) { + return false; + } + int count[] = new int[CHARACTER_RANGE]; + for (int i = 0; i < string1.length(); i++) { + count[string1.charAt(i)]++; + count[string2.charAt(i)]--; + } + for (int i = 0; i < CHARACTER_RANGE; i++) { + if (count[i] != 0) { + return false; + } + } + return true; + } + + public boolean isAnagramMultiset(String string1, String string2) { + if (string1.length() != string2.length()) { + return false; + } + Multiset multiset1 = HashMultiset.create(); + Multiset multiset2 = HashMultiset.create(); + for (int i = 0; i < string1.length(); i++) { + multiset1.add(string1.charAt(i)); + multiset2.add(string2.charAt(i)); + } + return multiset1.equals(multiset2); + } + + public boolean isLetterBasedAnagramMultiset(String string1, String string2) { + return isAnagramMultiset(preprocess(string1), preprocess(string2)); + } + + private String preprocess(String source) { + return source.replaceAll("[^a-zA-Z]", "").toLowerCase(); + } + +} diff --git a/core-java-modules/core-java-string-algorithms-3/src/test/java/com/baeldung/anagram/AnagramUnitTest.java b/core-java-modules/core-java-string-algorithms-3/src/test/java/com/baeldung/anagram/AnagramUnitTest.java new file mode 100644 index 0000000000..bedeeb9418 --- /dev/null +++ b/core-java-modules/core-java-string-algorithms-3/src/test/java/com/baeldung/anagram/AnagramUnitTest.java @@ -0,0 +1,72 @@ +package com.baeldung.anagram; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class AnagramUnitTest { + @Test + public void givenAnagram_whenUsingSort_thenIdentifyAnagram() { + Anagram anagram = new Anagram(); + String string1 = "abcab"; + String string2 = "cabba"; + assertTrue(anagram.isAnagramSort(string1, string2)); + } + + @Test + public void givenAnagram_whenUsingCounting_thenIdentifyAnagram() { + Anagram anagram = new Anagram(); + String string1 = "abcab"; + String string2 = "cabba"; + assertTrue(anagram.isAnagramCounting(string1, string2)); + } + + @Test + public void givenAnagram_whenUsingMultiset_thenIdentifyAnagram() { + Anagram anagram = new Anagram(); + String string1 = "abcab"; + String string2 = "cabba"; + assertTrue(anagram.isAnagramMultiset(string1, string2)); + } + + @Test + public void givenAnagram_whenUsingLetterBasedMultiset_thenIdentifyAnagram() { + Anagram anagram = new Anagram(); + String string1 = "A decimal point"; + String string2 = "I’m a dot in place."; + assertTrue(anagram.isLetterBasedAnagramMultiset(string1, string2)); + } + + @Test + public void givenNonAnagram_whenUsingSort_thenIdentifyNotAnagram() { + Anagram anagram = new Anagram(); + String string1 = "abcaba"; + String string2 = "cabbac"; + assertFalse(anagram.isAnagramSort(string1, string2)); + } + + @Test + public void givenNonAnagram_whenUsingCounting_thenIdentifyNotAnagram() { + Anagram anagram = new Anagram(); + String string1 = "abcaba"; + String string2 = "cabbac"; + assertFalse(anagram.isAnagramCounting(string1, string2)); + } + + @Test + public void givenNonAnagram_whenUsingMultiset_thenIdentifyNotAnagram() { + Anagram anagram = new Anagram(); + String string1 = "abcaba"; + String string2 = "cabbac"; + assertFalse(anagram.isAnagramMultiset(string1, string2)); + } + + @Test + public void ggivenNonAnagram_whenUsingLetterBasedMultiset_thenIdentifyAnagram() { + Anagram anagram = new Anagram(); + String string1 = "A decimal point"; + String string2 = "I’m dot in place."; + assertFalse(anagram.isAnagramMultiset(string1, string2)); + } +}