diff --git a/.gitignore b/.gitignore index 236a7c71..a80c53d7 100644 --- a/.gitignore +++ b/.gitignore @@ -51,3 +51,5 @@ buildNumber.properties .mvn/timing.properties !/.mvn/wrapper/maven-wrapper.jar *_Practice.java + +htmlReport/ diff --git a/pom.xml b/pom.xml index 4db680c0..3188f0ff 100644 --- a/pom.xml +++ b/pom.xml @@ -60,6 +60,15 @@ junit-jupiter-api 5.5.1 + + + + com.sun + tools + 1.8 + system + + diff --git a/src/main/java/com/ctci/arraysandstrings/IsUnique.java b/src/main/java/com/ctci/arraysandstrings/IsUnique.java index 895d16b3..f6e91edb 100644 --- a/src/main/java/com/ctci/arraysandstrings/IsUnique.java +++ b/src/main/java/com/ctci/arraysandstrings/IsUnique.java @@ -6,46 +6,86 @@ */ public class IsUnique { - private static boolean hasAllUniqueCharacters(String str) { - if (str == null || str.length() > 128) return false; + /** + * Check whether the input string contains different individual characters and it in the ASCII table. + * + * @param str Input string + * @return true if all characters are different from each other, otherwise false. + */ + public static boolean isAllCharactersUniqueAndInASCII(String str) { + if (str == null || str.isEmpty()) { + return false; + } + + int maxCharIndex = 128; + int stringLength = str.length(); + + if (stringLength > maxCharIndex) { + return false; + } - boolean[] charSet = new boolean[128]; // assuming the string contains only ASCII characters - for (int i = 0; i < str.length(); i++) { - int charVal = str.charAt(i); - if (charSet[charVal]) { + boolean[] characterTrack = new boolean[maxCharIndex]; // assuming the string contains only ASCII characters + for (int i = 0; i < stringLength; i++) { + int charIndex = str.charAt(i); + if (charIndex >= maxCharIndex + || characterTrack[charIndex]) { return false; } - charSet[charVal] = true; + + characterTrack[charIndex] = true; } return true; } - private static boolean hasAllUniqueCharactersWhenStringContainsAllLowercase(String s) { + /** + * Check whether the input string contains different individual characters, lowercase + * and in between 'a' and 'z' + * + * @param str Input string + * @return true if all characters are different from each other,lowercase and between 'a' and 'z', otherwise false. + */ + public static boolean isAllCharactersUniqueAndLowercaseAndInAlphabet(String str) { + if (str == null + || str.isEmpty() + || str.length() > 26) { + return false; + } + int checker = 0; - for (int i = 0; i < s.length(); i++) { - int charValue = s.charAt(i) - 'a'; - if ((checker & (1 << charValue)) > 0) { + int stringLength = str.length(); + for (int i = 0; i < stringLength; i++) { + + char character = str.charAt(i); + if (!(character >= 'a' && character <= 'z')) { + return false; + } + + int characterIndex = character - 'a'; + int singleBitOnPosition = 1 << characterIndex ; + + if ((checker & singleBitOnPosition) > 0) { return false; } - checker |= (1 << charValue); + + checker |= singleBitOnPosition; // checker = checker | singleBitOnPosition; } return true; } public static void main(String[] args) { String s = "ram"; - System.out.println(hasAllUniqueCharacters(s)); + System.out.println(isAllCharactersUniqueAndInASCII(s)); s = "rama"; - System.out.println(hasAllUniqueCharacters(s)); + System.out.println(isAllCharactersUniqueAndInASCII(s)); s = "ramA"; - System.out.println(hasAllUniqueCharacters(s)); + System.out.println(isAllCharactersUniqueAndInASCII(s)); System.out.println("-------"); s = "ram"; - System.out.println(hasAllUniqueCharactersWhenStringContainsAllLowercase(s)); + System.out.println(isAllCharactersUniqueAndLowercaseAndInAlphabet(s)); s = "rama"; - System.out.println(hasAllUniqueCharactersWhenStringContainsAllLowercase(s)); + System.out.println(isAllCharactersUniqueAndLowercaseAndInAlphabet(s)); // not working as the input contains different cases s = "ramA"; - System.out.println(hasAllUniqueCharactersWhenStringContainsAllLowercase(s)); + System.out.println(isAllCharactersUniqueAndLowercaseAndInAlphabet(s)); } } diff --git a/src/main/test/com/ctci/arraysandstrings/IsUniqueTest.java b/src/main/test/com/ctci/arraysandstrings/IsUniqueTest.java new file mode 100644 index 00000000..ef373ded --- /dev/null +++ b/src/main/test/com/ctci/arraysandstrings/IsUniqueTest.java @@ -0,0 +1,224 @@ +package com.ctci.arraysandstrings; + +import org.junit.jupiter.api.*; + +public class IsUniqueTest { + + @Nested + @DisplayName("Test cases for isAllCharactersUniqueAndInASCII()") + class TestCasesForIsAllCharactersUniqueAndInASCII { + + @Test + public void isAllCharactersUniqueAndInASCII_StringIsNull_ReturnFalse() { + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndInASCII(null)); + } + + @Test + public void isAllCharactersUniqueAndInASCII_StringIsEmpty_ReturnFalse() { + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndInASCII("")); + } + + @Test + public void isAllCharactersUniqueAndInASCII_StringLengthSmallerOrEqual128_ReturnFalse() { + StringBuilder stringBuilder = new StringBuilder(); + + for (int i = 0; i < 128; i++) { + stringBuilder.append((char) i); + } + Assertions.assertTrue(IsUnique.isAllCharactersUniqueAndInASCII(stringBuilder.toString())); + + stringBuilder.setLength(0); + for (int i = 1; i < 127; i++) { + stringBuilder.append((char) i); + } + Assertions.assertTrue(IsUnique.isAllCharactersUniqueAndInASCII(stringBuilder.toString())); + } + + @Test + public void isAllCharactersUniqueAndInASCII_StringLengthLargerThan128_ReturnFalse() { + StringBuilder stringBuilder = new StringBuilder(); + + for (int i = 0; i < 128; i++) { + stringBuilder.append((char) i); + } + stringBuilder.append("a"); + + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndInASCII(stringBuilder.toString())); + } + + @Test + public void isAllCharactersUniqueAndInASCII_DuplicateAtHead_ReturnFalse() { + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndInASCII("aab")); + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndInASCII("AAb")); + + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndInASCII("ááb")); + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndInASCII("ÁÁb")); + + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndInASCII("1123456")); + } + + @Test + public void isAllCharactersUniqueAndInASCII_DuplicateAtMiddle_ReturnFalse() { + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndInASCII("abcbd")); + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndInASCII("aBcBd")); + + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndInASCII("aưcưd")); + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndInASCII("aƯcƯd")); + + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndInASCII("123436")); + } + + @Test + public void isAllCharactersUniqueAndInASCII_DuplicateAtTail_ReturnFalse() { + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndInASCII("aba")); + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndInASCII("AbA")); + + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndInASCII("ăbă")); + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndInASCII("ĂbĂ")); + + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndInASCII("1234566")); + } + + @Test + public void isAllCharactersUniqueAndInASCII_OnlyOneCharacter_ReturnTrue() { + Assertions.assertTrue(IsUnique.isAllCharactersUniqueAndInASCII("a")); + Assertions.assertTrue(IsUnique.isAllCharactersUniqueAndInASCII("1")); + Assertions.assertTrue(IsUnique.isAllCharactersUniqueAndInASCII("A")); + Assertions.assertTrue(IsUnique.isAllCharactersUniqueAndInASCII("#")); + } + + @Test + public void isAllCharactersUniqueAndInASCII_OnlyOneCharacter_ReturnFalse() { + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndInASCII("á")); + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndInASCII("Ô")); + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndInASCII("€")); + } + + @Test + public void isAllCharactersUniqueAndInASCII_InvalidString_ReturnFalse() { + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndInASCII("€á")); + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndInASCII("áÂ")); + } + + @Test + public void isAllCharactersUniqueAndInASCII_ValidString_ReturnTrue() { + Assertions.assertTrue(IsUnique.isAllCharactersUniqueAndInASCII("aAb")); + Assertions.assertTrue(IsUnique.isAllCharactersUniqueAndInASCII("abcBd")); + Assertions.assertTrue(IsUnique.isAllCharactersUniqueAndInASCII("abA")); + Assertions.assertTrue(IsUnique.isAllCharactersUniqueAndInASCII( + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")); + } + } + + @Nested + @DisplayName("Test cases for isAllCharactersUniqueAndLowercaseAndInAlphabet()") + class TestCasesForIsAllCharactersUniqueAndLowercaseAndInAlphabet { + + @Test + public void isAllCharactersUniqueAndLowercaseAndInAlphabet_StringIsNull_ReturnFalse() { + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet(null)); + } + + @Test + public void isAllCharactersUniqueAndLowercaseAndInAlphabet_StringIsEmpty_ReturnFalse() { + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("")); + } + + @Test + public void isAllCharactersUniqueAndLowercaseAndInAlphabet_StringLengthSmallerOrEqual26_ReturnFalse() { + StringBuilder stringBuilder = new StringBuilder(); + + for (int i = 97; i <= 122; i++) { // 'a' -> 'z' + stringBuilder.append((char) i); + } + Assertions.assertTrue(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet(stringBuilder.toString())); + + stringBuilder.setLength(0); + for (int i = 100; i <= 120; i++) { // 'a' -> 'z' + stringBuilder.append((char) i); + } + Assertions.assertTrue(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet(stringBuilder.toString())); + } + + @Test + public void isAllCharactersUniqueAndLowercaseAndInAlphabet_StringLengthLargerThan26_ReturnFalse() { + String a2z = "abcdefghijklmnopqrstuvwxyz"; + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet(a2z + (char) 96)); // 96 => ` + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet(a2z + (char) 123)); // 123 => { + } + + @Test + public void isAllCharactersUniqueAndLowercaseAndInAlphabet_Beyond_a2z_ReturnFalse() { + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("GH@")); + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("{} ")); + + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("ááb")); + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("ÁÁb")); + + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("1123456")); + } + + @Test + public void isAllCharactersUniqueAndLowercaseAndInAlphabet_DuplicateAtHead_ReturnFalse() { + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("aab")); + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("AAb")); + + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("ááb")); + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("ÁÁb")); + + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("1123456")); + } + + @Test + public void isAllCharactersUniqueAndLowercaseAndInAlphabet_DuplicateAtMiddle_ReturnFalse() { + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("abcbd")); + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("aBcBd")); + + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("aưcưd")); + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("aƯcƯd")); + + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("123436")); + } + + @Test + public void isAllCharactersUniqueAndLowercaseAndInAlphabet_DuplicateAtTail_ReturnFalse() { + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("aba")); + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("AbA")); + + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("ăbă")); + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("ĂbĂ")); + + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("1234566")); + } + + @Test + public void isAllCharactersUniqueAndLowercaseAndInAlphabet_OnlyOneCharacter_ReturnTrue() { + for (int i = 97; i <= 122; i++) { + Assertions.assertTrue(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet(String.valueOf((char) i))); + } + } + + @Test + public void isAllCharactersUniqueAndLowercaseAndInAlphabet_OnlyOneCharacter_ReturnFalse() { + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("A")); + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("á")); + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("Ô")); + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("€")); + } + + @Test + public void isAllCharactersUniqueAndLowercaseAndInAlphabet_InvalidString_ReturnFalse() { + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("€á")); + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("áÂ")); + Assertions.assertFalse(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("aB")); + } + + @Test + public void isAllCharactersUniqueAndLowercaseAndInAlphabet_ValidString_ReturnTrue() { + Assertions.assertTrue(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("mwq")); + Assertions.assertTrue(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("fwoklt")); + Assertions.assertTrue(IsUnique.isAllCharactersUniqueAndLowercaseAndInAlphabet("abcdefghijklmnopqrstuvwxyz")); + } + } + +}