From 254ac8754efc6796a86cb73897e87a47d4e9a06e Mon Sep 17 00:00:00 2001 From: JeevaRamanathan Date: Thu, 2 Oct 2025 22:01:08 +0530 Subject: [PATCH 01/15] added isogram utility class and unit tests Signed-off-by: JeevaRamanathan --- .../com/thealgorithms/strings/Isogram.java | 83 +++++++++++ .../thealgorithms/strings/IsogramTest.java | 136 ++++++++++++++++++ 2 files changed, 219 insertions(+) create mode 100644 src/main/java/com/thealgorithms/strings/Isogram.java create mode 100644 src/test/java/com/thealgorithms/strings/IsogramTest.java diff --git a/src/main/java/com/thealgorithms/strings/Isogram.java b/src/main/java/com/thealgorithms/strings/Isogram.java new file mode 100644 index 000000000000..99b75210c3af --- /dev/null +++ b/src/main/java/com/thealgorithms/strings/Isogram.java @@ -0,0 +1,83 @@ +package com.thealgorithms.strings; + +import java.util.HashSet; +import java.util.Set; + +/** + * An isogram (also called heterogram or nonpattern word) is a word in which no + * letter of the word occurs more than once. Each character appears exactly + * once. + * + * For example, the word "uncopyrightable" is the longest common English isogram + * with 15 unique letters. Other examples include "dermatoglyphics" (15 + * letters), + * "background" (10 letters), "python" (6 letters), and "keyboard" (8 letters). + * But words like "hello" and "programming" are not isograms because some + * letters + * appear multiple times ('l' appears twice in "hello", while 'r', 'm', 'g' + * repeat + * in "programming"). + * + * Isograms are particularly valuable in creating substitution ciphers and are + * studied in recreational linguistics. A perfect pangram, which uses all 26 + * letters + * of the alphabet exactly once, is a special type of isogram. + * + * Reference from https://en.wikipedia.org/wiki/Heterogram_(literature)#Isograms + */ +public class Isogram { + /** + * Checks if a string is an isogram using boolean array approach. + * + * Time Complexity: O(n) + * Space Complexity: O(1) + * + * @param str the input string + * @return true if the string is an isogram, false otherwise + * @throws IllegalArgumentException if the string contains non-alphabetic + * characters + */ + public static boolean isIsogramByArray(String str) { + if (str == null || str.isEmpty()) { + return true; + } + + String lowerStr = str.toLowerCase(); + boolean[] seenChars = new boolean[26]; + + for (int i = 0; i < lowerStr.length(); i++) { + char ch = lowerStr.charAt(i); + + // Check if character is a letter + if (ch >= 'a' && ch <= 'z') { + int index = ch - 'a'; + if (seenChars[index]) { + return false; // Letter already seen + } + seenChars[index] = true; + } + } + return true; + } + + /** + * Checks if a string is an isogram using length comparison approach. + * Time Complexity: O(n) + * Space Complexity: O(k) where k is the number of unique characters + * + * @param str the input string + * @return true if the string is an isogram, false otherwise + */ + public static boolean isIsogramByLength(String str) { + if (str == null || str.isEmpty()) { + return true; + } + str = str.toLowerCase(); + + Set uniqueChars = new HashSet<>(); + for (char ch : str.toCharArray()) { + uniqueChars.add(ch); + } + return uniqueChars.size() == str.length(); + } +} \ No newline at end of file diff --git a/src/test/java/com/thealgorithms/strings/IsogramTest.java b/src/test/java/com/thealgorithms/strings/IsogramTest.java new file mode 100644 index 000000000000..269c3a7666fb --- /dev/null +++ b/src/test/java/com/thealgorithms/strings/IsogramTest.java @@ -0,0 +1,136 @@ +package com.thealgorithms.strings; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.stream.Stream; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.api.Test; + +public class IsogramTest { + + record IsogramTestCase(String input, boolean expected) { + } + + private static Stream isogramArrayTestData() { + return Stream.of( + // Valid isograms (only checks letters) + new IsogramTestCase("uncopyrightable", true), + new IsogramTestCase("dermatoglyphics", true), + new IsogramTestCase("background", true), + new IsogramTestCase("python", true), + new IsogramTestCase("keyboard", true), + new IsogramTestCase("clipboard", true), + new IsogramTestCase("flowchart", true), + new IsogramTestCase("bankruptcy", true), + new IsogramTestCase("computer", true), + new IsogramTestCase("algorithms", true), + + // Not isograms - letters repeat + new IsogramTestCase("hello", false), + new IsogramTestCase("programming", false), + new IsogramTestCase("java", false), + new IsogramTestCase("coffee", false), + new IsogramTestCase("book", false), + new IsogramTestCase("letter", false), + new IsogramTestCase("mississippi", false), + new IsogramTestCase("google", false), + + // Edge cases + new IsogramTestCase("", true), + new IsogramTestCase("a", true), + new IsogramTestCase("ab", true), + new IsogramTestCase("abc", true), + new IsogramTestCase("aa", false), + new IsogramTestCase("abcdefghijklmnopqrstuvwxyz", true), // All 26 letters + + // Case insensitive + new IsogramTestCase("Python", true), + new IsogramTestCase("BACKGROUND", true), + new IsogramTestCase("Hello", false), + new IsogramTestCase("PROGRAMMING", false)); + } + + private static Stream isogramLengthTestData() { + return Stream.of( + // Valid isograms (checks all characters) + new IsogramTestCase("uncopyrightable", true), + new IsogramTestCase("dermatoglyphics", true), + new IsogramTestCase("background", true), + new IsogramTestCase("python", true), + new IsogramTestCase("keyboard", true), + new IsogramTestCase("clipboard", true), + new IsogramTestCase("flowchart", true), + new IsogramTestCase("bankruptcy", true), + new IsogramTestCase("computer", true), + new IsogramTestCase("algorithms", true), + + // Not isograms - characters repeat + new IsogramTestCase("hello", false), + new IsogramTestCase("programming", false), + new IsogramTestCase("java", false), + new IsogramTestCase("coffee", false), + new IsogramTestCase("book", false), + new IsogramTestCase("letter", false), + new IsogramTestCase("mississippi", false), + new IsogramTestCase("google", false), + + // Edge cases + new IsogramTestCase("", true), + new IsogramTestCase("a", true), + new IsogramTestCase("ab", true), + new IsogramTestCase("abc", true), + new IsogramTestCase("aa", false), + new IsogramTestCase("abcdefghijklmnopqrstuvwxyz", true), // All 26 letters + + // Case insensitive + new IsogramTestCase("Python", true), + new IsogramTestCase("BACKGROUND", true), + new IsogramTestCase("Hello", false), + new IsogramTestCase("PROGRAMMING", false), + + // Strings with symbols and numbers + new IsogramTestCase("abc@def", true), // all characters unique + new IsogramTestCase("test-case", false), // 't', 's', 'e' repeat + new IsogramTestCase("python123", true), // all characters unique + new IsogramTestCase("hello@123", false), // 'l' repeats + new IsogramTestCase("abc123!@#", true), // all characters unique + new IsogramTestCase("test123test", false), // 't', 'e', 's' repeat + new IsogramTestCase("1234567890", true), // all digits unique + new IsogramTestCase("12321", false), // '1' and '2' repeat + new IsogramTestCase("!@#$%^&*()", true) // all special characters unique + ); + } + + @ParameterizedTest + @MethodSource("isogramArrayTestData") + void testIsogramByArray(IsogramTestCase testCase) { + assertEquals(testCase.expected(), Isogram.isIsogramByArray(testCase.input())); + } + + @ParameterizedTest + @MethodSource("isogramLengthTestData") + void testIsogramByLength(IsogramTestCase testCase) { + assertEquals(testCase.expected(), Isogram.isIsogramByLength(testCase.input())); + } + + @Test + void testNullInputByArray() { + assertEquals(true, Isogram.isIsogramByArray(null)); + } + + @Test + void testNullInputByLength() { + assertEquals(true, Isogram.isIsogramByLength(null)); + } + + @Test + void testEmptyStringByArray() { + assertEquals(true, Isogram.isIsogramByArray("")); + } + + @Test + void testEmptyStringByLength() { + assertEquals(true, Isogram.isIsogramByLength("")); + } +} \ No newline at end of file From f153f337f8fee425a290be48ff8a68c8076540cf Mon Sep 17 00:00:00 2001 From: JeevaRamanathan Date: Thu, 2 Oct 2025 22:16:02 +0530 Subject: [PATCH 02/15] checking lint issue Signed-off-by: JeevaRamanathan --- .../com/thealgorithms/strings/Isogram.java | 4 +- .../thealgorithms/strings/IsogramTest.java | 73 ++++++------------- 2 files changed, 26 insertions(+), 51 deletions(-) diff --git a/src/main/java/com/thealgorithms/strings/Isogram.java b/src/main/java/com/thealgorithms/strings/Isogram.java index 99b75210c3af..d97bdb986d66 100644 --- a/src/main/java/com/thealgorithms/strings/Isogram.java +++ b/src/main/java/com/thealgorithms/strings/Isogram.java @@ -17,12 +17,12 @@ * appear multiple times ('l' appears twice in "hello", while 'r', 'm', 'g' * repeat * in "programming"). - * + * * Isograms are particularly valuable in creating substitution ciphers and are * studied in recreational linguistics. A perfect pangram, which uses all 26 * letters * of the alphabet exactly once, is a special type of isogram. - * + * * Reference from https://en.wikipedia.org/wiki/Heterogram_(literature)#Isograms */ public class Isogram { diff --git a/src/test/java/com/thealgorithms/strings/IsogramTest.java b/src/test/java/com/thealgorithms/strings/IsogramTest.java index 269c3a7666fb..d9e87662c8ed 100644 --- a/src/test/java/com/thealgorithms/strings/IsogramTest.java +++ b/src/test/java/com/thealgorithms/strings/IsogramTest.java @@ -3,9 +3,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.stream.Stream; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; -import org.junit.jupiter.api.Test; public class IsogramTest { @@ -15,79 +15,55 @@ record IsogramTestCase(String input, boolean expected) { private static Stream isogramArrayTestData() { return Stream.of( // Valid isograms (only checks letters) - new IsogramTestCase("uncopyrightable", true), - new IsogramTestCase("dermatoglyphics", true), - new IsogramTestCase("background", true), - new IsogramTestCase("python", true), - new IsogramTestCase("keyboard", true), - new IsogramTestCase("clipboard", true), + new IsogramTestCase("uncopyrightable", true), new IsogramTestCase("dermatoglyphics", true), + new IsogramTestCase("background", true), new IsogramTestCase("python", true), + new IsogramTestCase("keyboard", true), new IsogramTestCase("clipboard", true), new IsogramTestCase("flowchart", true), - new IsogramTestCase("bankruptcy", true), - new IsogramTestCase("computer", true), + new IsogramTestCase("bankruptcy", true), new IsogramTestCase("computer", true), new IsogramTestCase("algorithms", true), // Not isograms - letters repeat - new IsogramTestCase("hello", false), - new IsogramTestCase("programming", false), - new IsogramTestCase("java", false), - new IsogramTestCase("coffee", false), - new IsogramTestCase("book", false), - new IsogramTestCase("letter", false), + new IsogramTestCase("hello", false), new IsogramTestCase("programming", false), + new IsogramTestCase("java", false), new IsogramTestCase("coffee", false), + new IsogramTestCase("book", false), new IsogramTestCase("letter", false), new IsogramTestCase("mississippi", false), new IsogramTestCase("google", false), // Edge cases - new IsogramTestCase("", true), - new IsogramTestCase("a", true), - new IsogramTestCase("ab", true), - new IsogramTestCase("abc", true), - new IsogramTestCase("aa", false), + new IsogramTestCase("", true), new IsogramTestCase("a", true), new IsogramTestCase("ab", true), + new IsogramTestCase("abc", true), new IsogramTestCase("aa", false), new IsogramTestCase("abcdefghijklmnopqrstuvwxyz", true), // All 26 letters // Case insensitive - new IsogramTestCase("Python", true), - new IsogramTestCase("BACKGROUND", true), - new IsogramTestCase("Hello", false), - new IsogramTestCase("PROGRAMMING", false)); + new IsogramTestCase("Python", true), new IsogramTestCase("BACKGROUND", true), + new IsogramTestCase("Hello", false), new IsogramTestCase("PROGRAMMING", false)); } private static Stream isogramLengthTestData() { return Stream.of( // Valid isograms (checks all characters) - new IsogramTestCase("uncopyrightable", true), - new IsogramTestCase("dermatoglyphics", true), - new IsogramTestCase("background", true), - new IsogramTestCase("python", true), - new IsogramTestCase("keyboard", true), - new IsogramTestCase("clipboard", true), + new IsogramTestCase("uncopyrightable", true), new IsogramTestCase("dermatoglyphics", true), + new IsogramTestCase("background", true), new IsogramTestCase("python", true), + new IsogramTestCase("keyboard", true), new IsogramTestCase("clipboard", true), new IsogramTestCase("flowchart", true), - new IsogramTestCase("bankruptcy", true), - new IsogramTestCase("computer", true), + new IsogramTestCase("bankruptcy", true), new IsogramTestCase("computer", true), new IsogramTestCase("algorithms", true), // Not isograms - characters repeat - new IsogramTestCase("hello", false), - new IsogramTestCase("programming", false), - new IsogramTestCase("java", false), - new IsogramTestCase("coffee", false), - new IsogramTestCase("book", false), - new IsogramTestCase("letter", false), + new IsogramTestCase("hello", false), new IsogramTestCase("programming", false), + new IsogramTestCase("java", false), new IsogramTestCase("coffee", false), + new IsogramTestCase("book", false), new IsogramTestCase("letter", false), new IsogramTestCase("mississippi", false), new IsogramTestCase("google", false), // Edge cases - new IsogramTestCase("", true), - new IsogramTestCase("a", true), - new IsogramTestCase("ab", true), - new IsogramTestCase("abc", true), - new IsogramTestCase("aa", false), + new IsogramTestCase("", true), new IsogramTestCase("a", true), new IsogramTestCase("ab", true), + new IsogramTestCase("abc", true), new IsogramTestCase("aa", false), new IsogramTestCase("abcdefghijklmnopqrstuvwxyz", true), // All 26 letters // Case insensitive - new IsogramTestCase("Python", true), - new IsogramTestCase("BACKGROUND", true), - new IsogramTestCase("Hello", false), - new IsogramTestCase("PROGRAMMING", false), + new IsogramTestCase("Python", true), new IsogramTestCase("BACKGROUND", true), + new IsogramTestCase("Hello", false), new IsogramTestCase("PROGRAMMING", false), // Strings with symbols and numbers new IsogramTestCase("abc@def", true), // all characters unique @@ -132,5 +108,4 @@ void testEmptyStringByArray() { @Test void testEmptyStringByLength() { assertEquals(true, Isogram.isIsogramByLength("")); - } -} \ No newline at end of file + } \ No newline at end of file From 74df84356d0f9e4720f18f4c75fb41e33d2abd70 Mon Sep 17 00:00:00 2001 From: JeevaRamanathan Date: Thu, 2 Oct 2025 22:34:28 +0530 Subject: [PATCH 03/15] checking lint issue Signed-off-by: JeevaRamanathan --- .../com/thealgorithms/strings/Isogram.java | 2 +- .../thealgorithms/strings/IsogramTest.java | 98 ++++++++----------- 2 files changed, 41 insertions(+), 59 deletions(-) diff --git a/src/main/java/com/thealgorithms/strings/Isogram.java b/src/main/java/com/thealgorithms/strings/Isogram.java index d97bdb986d66..0b54fe0809b5 100644 --- a/src/main/java/com/thealgorithms/strings/Isogram.java +++ b/src/main/java/com/thealgorithms/strings/Isogram.java @@ -80,4 +80,4 @@ public static boolean isIsogramByLength(String str) { } return uniqueChars.size() == str.length(); } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/test/java/com/thealgorithms/strings/IsogramTest.java b/src/test/java/com/thealgorithms/strings/IsogramTest.java index d9e87662c8ed..379bc9bd7854 100644 --- a/src/test/java/com/thealgorithms/strings/IsogramTest.java +++ b/src/test/java/com/thealgorithms/strings/IsogramTest.java @@ -14,67 +14,48 @@ record IsogramTestCase(String input, boolean expected) { private static Stream isogramArrayTestData() { return Stream.of( - // Valid isograms (only checks letters) - new IsogramTestCase("uncopyrightable", true), new IsogramTestCase("dermatoglyphics", true), - new IsogramTestCase("background", true), new IsogramTestCase("python", true), - new IsogramTestCase("keyboard", true), new IsogramTestCase("clipboard", true), - new IsogramTestCase("flowchart", true), - new IsogramTestCase("bankruptcy", true), new IsogramTestCase("computer", true), - new IsogramTestCase("algorithms", true), - - // Not isograms - letters repeat - new IsogramTestCase("hello", false), new IsogramTestCase("programming", false), - new IsogramTestCase("java", false), new IsogramTestCase("coffee", false), - new IsogramTestCase("book", false), new IsogramTestCase("letter", false), - new IsogramTestCase("mississippi", false), - new IsogramTestCase("google", false), - - // Edge cases - new IsogramTestCase("", true), new IsogramTestCase("a", true), new IsogramTestCase("ab", true), - new IsogramTestCase("abc", true), new IsogramTestCase("aa", false), - new IsogramTestCase("abcdefghijklmnopqrstuvwxyz", true), // All 26 letters - - // Case insensitive - new IsogramTestCase("Python", true), new IsogramTestCase("BACKGROUND", true), - new IsogramTestCase("Hello", false), new IsogramTestCase("PROGRAMMING", false)); + // Valid isograms (only checks letters) + new IsogramTestCase("uncopyrightable", true), new IsogramTestCase("dermatoglyphics", true), new IsogramTestCase("background", true), new IsogramTestCase("python", true), new IsogramTestCase("keyboard", true), new IsogramTestCase("clipboard", true), new IsogramTestCase("flowchart", true), + new IsogramTestCase("bankruptcy", true), new IsogramTestCase("computer", true), new IsogramTestCase("algorithms", true), + + // Not isograms - letters repeat + new IsogramTestCase("hello", false), new IsogramTestCase("programming", false), new IsogramTestCase("java", false), new IsogramTestCase("coffee", false), new IsogramTestCase("book", false), new IsogramTestCase("letter", false), new IsogramTestCase("mississippi", false), + new IsogramTestCase("google", false), + + // Edge cases + new IsogramTestCase("", true), new IsogramTestCase("a", true), new IsogramTestCase("ab", true), new IsogramTestCase("abc", true), new IsogramTestCase("aa", false), new IsogramTestCase("abcdefghijklmnopqrstuvwxyz", true), + + // Case insensitive + new IsogramTestCase("Python", true), new IsogramTestCase("BACKGROUND", true), new IsogramTestCase("Hello", false), new IsogramTestCase("PROGRAMMING", false)); } private static Stream isogramLengthTestData() { return Stream.of( - // Valid isograms (checks all characters) - new IsogramTestCase("uncopyrightable", true), new IsogramTestCase("dermatoglyphics", true), - new IsogramTestCase("background", true), new IsogramTestCase("python", true), - new IsogramTestCase("keyboard", true), new IsogramTestCase("clipboard", true), - new IsogramTestCase("flowchart", true), - new IsogramTestCase("bankruptcy", true), new IsogramTestCase("computer", true), - new IsogramTestCase("algorithms", true), - - // Not isograms - characters repeat - new IsogramTestCase("hello", false), new IsogramTestCase("programming", false), - new IsogramTestCase("java", false), new IsogramTestCase("coffee", false), - new IsogramTestCase("book", false), new IsogramTestCase("letter", false), - new IsogramTestCase("mississippi", false), - new IsogramTestCase("google", false), - - // Edge cases - new IsogramTestCase("", true), new IsogramTestCase("a", true), new IsogramTestCase("ab", true), - new IsogramTestCase("abc", true), new IsogramTestCase("aa", false), - new IsogramTestCase("abcdefghijklmnopqrstuvwxyz", true), // All 26 letters - - // Case insensitive - new IsogramTestCase("Python", true), new IsogramTestCase("BACKGROUND", true), - new IsogramTestCase("Hello", false), new IsogramTestCase("PROGRAMMING", false), - - // Strings with symbols and numbers - new IsogramTestCase("abc@def", true), // all characters unique - new IsogramTestCase("test-case", false), // 't', 's', 'e' repeat - new IsogramTestCase("python123", true), // all characters unique - new IsogramTestCase("hello@123", false), // 'l' repeats - new IsogramTestCase("abc123!@#", true), // all characters unique - new IsogramTestCase("test123test", false), // 't', 'e', 's' repeat - new IsogramTestCase("1234567890", true), // all digits unique - new IsogramTestCase("12321", false), // '1' and '2' repeat - new IsogramTestCase("!@#$%^&*()", true) // all special characters unique + // Valid isograms (checks all characters) + new IsogramTestCase("uncopyrightable", true), new IsogramTestCase("dermatoglyphics", true), new IsogramTestCase("background", true), new IsogramTestCase("python", true), new IsogramTestCase("keyboard", true), new IsogramTestCase("clipboard", true), new IsogramTestCase("flowchart", true), + new IsogramTestCase("bankruptcy", true), new IsogramTestCase("computer", true), new IsogramTestCase("algorithms", true), + + // Not isograms - characters repeat + new IsogramTestCase("hello", false), new IsogramTestCase("programming", false), new IsogramTestCase("java", false), new IsogramTestCase("coffee", false), new IsogramTestCase("book", false), new IsogramTestCase("letter", false), new IsogramTestCase("mississippi", false), + new IsogramTestCase("google", false), + + // Edge cases + new IsogramTestCase("", true), new IsogramTestCase("a", true), new IsogramTestCase("ab", true), new IsogramTestCase("abc", true), new IsogramTestCase("aa", false), new IsogramTestCase("abcdefghijklmnopqrstuvwxyz", true), + + // Case insensitive + new IsogramTestCase("Python", true), new IsogramTestCase("BACKGROUND", true), new IsogramTestCase("Hello", false), new IsogramTestCase("PROGRAMMING", false), + + + // Strings with symbols and numbers + new IsogramTestCase("abc@def", true), // all characters unique + new IsogramTestCase("test-case", false), // 't', 's', 'e' repeat + new IsogramTestCase("python123", true), // all characters unique + new IsogramTestCase("hello@123", false), // 'l' repeats + new IsogramTestCase("abc123!@#", true), // all characters unique + new IsogramTestCase("test123test", false), // 't', 'e', 's' repeat + new IsogramTestCase("1234567890", true), // all digits unique + new IsogramTestCase("12321", false), // '1' and '2' repeat + new IsogramTestCase("!@#$%^&*()", true) // all special characters unique ); } @@ -108,4 +89,5 @@ void testEmptyStringByArray() { @Test void testEmptyStringByLength() { assertEquals(true, Isogram.isIsogramByLength("")); - } \ No newline at end of file + } +} \ No newline at end of file From 2d116229cf3aa6821303d150a087caf5c70d5cdb Mon Sep 17 00:00:00 2001 From: JeevaRamanathan Date: Thu, 2 Oct 2025 22:40:06 +0530 Subject: [PATCH 04/15] checking lint issue Signed-off-by: JeevaRamanathan --- src/main/java/com/thealgorithms/strings/Isogram.java | 2 +- src/test/java/com/thealgorithms/strings/IsogramTest.java | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/thealgorithms/strings/Isogram.java b/src/main/java/com/thealgorithms/strings/Isogram.java index 0b54fe0809b5..d97bdb986d66 100644 --- a/src/main/java/com/thealgorithms/strings/Isogram.java +++ b/src/main/java/com/thealgorithms/strings/Isogram.java @@ -80,4 +80,4 @@ public static boolean isIsogramByLength(String str) { } return uniqueChars.size() == str.length(); } - } \ No newline at end of file +} \ No newline at end of file diff --git a/src/test/java/com/thealgorithms/strings/IsogramTest.java b/src/test/java/com/thealgorithms/strings/IsogramTest.java index 379bc9bd7854..48e8394e4019 100644 --- a/src/test/java/com/thealgorithms/strings/IsogramTest.java +++ b/src/test/java/com/thealgorithms/strings/IsogramTest.java @@ -21,7 +21,6 @@ private static Stream isogramArrayTestData() { // Not isograms - letters repeat new IsogramTestCase("hello", false), new IsogramTestCase("programming", false), new IsogramTestCase("java", false), new IsogramTestCase("coffee", false), new IsogramTestCase("book", false), new IsogramTestCase("letter", false), new IsogramTestCase("mississippi", false), new IsogramTestCase("google", false), - // Edge cases new IsogramTestCase("", true), new IsogramTestCase("a", true), new IsogramTestCase("ab", true), new IsogramTestCase("abc", true), new IsogramTestCase("aa", false), new IsogramTestCase("abcdefghijklmnopqrstuvwxyz", true), @@ -89,5 +88,5 @@ void testEmptyStringByArray() { @Test void testEmptyStringByLength() { assertEquals(true, Isogram.isIsogramByLength("")); - } + } } \ No newline at end of file From f3abaf9cdb76dae556c0f3ee07ea0ee15a4c3c7c Mon Sep 17 00:00:00 2001 From: JeevaRamanathan Date: Thu, 2 Oct 2025 22:52:59 +0530 Subject: [PATCH 05/15] checking lint issue Signed-off-by: JeevaRamanathan --- src/main/java/com/thealgorithms/strings/Isogram.java | 2 +- src/test/java/com/thealgorithms/strings/IsogramTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/thealgorithms/strings/Isogram.java b/src/main/java/com/thealgorithms/strings/Isogram.java index d97bdb986d66..0b54fe0809b5 100644 --- a/src/main/java/com/thealgorithms/strings/Isogram.java +++ b/src/main/java/com/thealgorithms/strings/Isogram.java @@ -80,4 +80,4 @@ public static boolean isIsogramByLength(String str) { } return uniqueChars.size() == str.length(); } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/test/java/com/thealgorithms/strings/IsogramTest.java b/src/test/java/com/thealgorithms/strings/IsogramTest.java index 48e8394e4019..8c9ec6e34334 100644 --- a/src/test/java/com/thealgorithms/strings/IsogramTest.java +++ b/src/test/java/com/thealgorithms/strings/IsogramTest.java @@ -21,6 +21,7 @@ private static Stream isogramArrayTestData() { // Not isograms - letters repeat new IsogramTestCase("hello", false), new IsogramTestCase("programming", false), new IsogramTestCase("java", false), new IsogramTestCase("coffee", false), new IsogramTestCase("book", false), new IsogramTestCase("letter", false), new IsogramTestCase("mississippi", false), new IsogramTestCase("google", false), + // Edge cases new IsogramTestCase("", true), new IsogramTestCase("a", true), new IsogramTestCase("ab", true), new IsogramTestCase("abc", true), new IsogramTestCase("aa", false), new IsogramTestCase("abcdefghijklmnopqrstuvwxyz", true), @@ -44,7 +45,6 @@ private static Stream isogramLengthTestData() { // Case insensitive new IsogramTestCase("Python", true), new IsogramTestCase("BACKGROUND", true), new IsogramTestCase("Hello", false), new IsogramTestCase("PROGRAMMING", false), - // Strings with symbols and numbers new IsogramTestCase("abc@def", true), // all characters unique new IsogramTestCase("test-case", false), // 't', 's', 'e' repeat From 70df2ef502deb45d1bb4d8421e340747faa1a867 Mon Sep 17 00:00:00 2001 From: JeevaRamanathan Date: Thu, 2 Oct 2025 22:57:42 +0530 Subject: [PATCH 06/15] checking lint issue Signed-off-by: JeevaRamanathan --- src/main/java/com/thealgorithms/strings/Isogram.java | 2 +- src/test/java/com/thealgorithms/strings/IsogramTest.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/thealgorithms/strings/Isogram.java b/src/main/java/com/thealgorithms/strings/Isogram.java index 0b54fe0809b5..04fffb879756 100644 --- a/src/main/java/com/thealgorithms/strings/Isogram.java +++ b/src/main/java/com/thealgorithms/strings/Isogram.java @@ -80,4 +80,4 @@ public static boolean isIsogramByLength(String str) { } return uniqueChars.size() == str.length(); } - } \ No newline at end of file + } \ No newline at end of file diff --git a/src/test/java/com/thealgorithms/strings/IsogramTest.java b/src/test/java/com/thealgorithms/strings/IsogramTest.java index 8c9ec6e34334..ff18ce13a10b 100644 --- a/src/test/java/com/thealgorithms/strings/IsogramTest.java +++ b/src/test/java/com/thealgorithms/strings/IsogramTest.java @@ -21,7 +21,7 @@ private static Stream isogramArrayTestData() { // Not isograms - letters repeat new IsogramTestCase("hello", false), new IsogramTestCase("programming", false), new IsogramTestCase("java", false), new IsogramTestCase("coffee", false), new IsogramTestCase("book", false), new IsogramTestCase("letter", false), new IsogramTestCase("mississippi", false), new IsogramTestCase("google", false), - + // Edge cases new IsogramTestCase("", true), new IsogramTestCase("a", true), new IsogramTestCase("ab", true), new IsogramTestCase("abc", true), new IsogramTestCase("aa", false), new IsogramTestCase("abcdefghijklmnopqrstuvwxyz", true), @@ -38,7 +38,7 @@ private static Stream isogramLengthTestData() { // Not isograms - characters repeat new IsogramTestCase("hello", false), new IsogramTestCase("programming", false), new IsogramTestCase("java", false), new IsogramTestCase("coffee", false), new IsogramTestCase("book", false), new IsogramTestCase("letter", false), new IsogramTestCase("mississippi", false), new IsogramTestCase("google", false), - + // Edge cases new IsogramTestCase("", true), new IsogramTestCase("a", true), new IsogramTestCase("ab", true), new IsogramTestCase("abc", true), new IsogramTestCase("aa", false), new IsogramTestCase("abcdefghijklmnopqrstuvwxyz", true), From 23e353e6c8b29d1f9be050bf160467ecd223ba7e Mon Sep 17 00:00:00 2001 From: JeevaRamanathan Date: Thu, 2 Oct 2025 23:06:27 +0530 Subject: [PATCH 07/15] checking lint issue Signed-off-by: JeevaRamanathan --- src/main/java/com/thealgorithms/strings/Isogram.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/thealgorithms/strings/Isogram.java b/src/main/java/com/thealgorithms/strings/Isogram.java index 04fffb879756..d97bdb986d66 100644 --- a/src/main/java/com/thealgorithms/strings/Isogram.java +++ b/src/main/java/com/thealgorithms/strings/Isogram.java @@ -80,4 +80,4 @@ public static boolean isIsogramByLength(String str) { } return uniqueChars.size() == str.length(); } - } \ No newline at end of file +} \ No newline at end of file From 241cd75af4af532b76b3309792e1e4c54986039f Mon Sep 17 00:00:00 2001 From: JeevaRamanathan Date: Thu, 2 Oct 2025 23:24:48 +0530 Subject: [PATCH 08/15] checking lint issue Signed-off-by: JeevaRamanathan --- src/main/java/com/thealgorithms/strings/Isogram.java | 2 +- src/test/java/com/thealgorithms/strings/IsogramTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/thealgorithms/strings/Isogram.java b/src/main/java/com/thealgorithms/strings/Isogram.java index d97bdb986d66..0b54fe0809b5 100644 --- a/src/main/java/com/thealgorithms/strings/Isogram.java +++ b/src/main/java/com/thealgorithms/strings/Isogram.java @@ -80,4 +80,4 @@ public static boolean isIsogramByLength(String str) { } return uniqueChars.size() == str.length(); } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/test/java/com/thealgorithms/strings/IsogramTest.java b/src/test/java/com/thealgorithms/strings/IsogramTest.java index ff18ce13a10b..30c4945a0faa 100644 --- a/src/test/java/com/thealgorithms/strings/IsogramTest.java +++ b/src/test/java/com/thealgorithms/strings/IsogramTest.java @@ -89,4 +89,4 @@ void testEmptyStringByArray() { void testEmptyStringByLength() { assertEquals(true, Isogram.isIsogramByLength("")); } -} \ No newline at end of file + } \ No newline at end of file From 52d61c64da45af0a54129816b4c90cf18343d40e Mon Sep 17 00:00:00 2001 From: JeevaRamanathan Date: Thu, 2 Oct 2025 23:29:24 +0530 Subject: [PATCH 09/15] checking lint issue Signed-off-by: JeevaRamanathan --- src/main/java/com/thealgorithms/strings/Isogram.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/thealgorithms/strings/Isogram.java b/src/main/java/com/thealgorithms/strings/Isogram.java index 0b54fe0809b5..e33301112882 100644 --- a/src/main/java/com/thealgorithms/strings/Isogram.java +++ b/src/main/java/com/thealgorithms/strings/Isogram.java @@ -80,4 +80,4 @@ public static boolean isIsogramByLength(String str) { } return uniqueChars.size() == str.length(); } - } \ No newline at end of file +} From 62d373e4d7b9b9ac7bbdd219a5075b8c4b7d5656 Mon Sep 17 00:00:00 2001 From: JeevaRamanathan Date: Thu, 2 Oct 2025 23:30:11 +0530 Subject: [PATCH 10/15] linter fix Signed-off-by: JeevaRamanathan --- src/test/java/com/thealgorithms/strings/IsogramTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/thealgorithms/strings/IsogramTest.java b/src/test/java/com/thealgorithms/strings/IsogramTest.java index 30c4945a0faa..14329375749a 100644 --- a/src/test/java/com/thealgorithms/strings/IsogramTest.java +++ b/src/test/java/com/thealgorithms/strings/IsogramTest.java @@ -89,4 +89,4 @@ void testEmptyStringByArray() { void testEmptyStringByLength() { assertEquals(true, Isogram.isIsogramByLength("")); } - } \ No newline at end of file +} From 348370dcd6aa582fb094c058295901784550edc1 Mon Sep 17 00:00:00 2001 From: JeevaRamanathan Date: Thu, 2 Oct 2025 23:37:42 +0530 Subject: [PATCH 11/15] fix: HideUtilityClassConstructor Signed-off-by: JeevaRamanathan --- src/main/java/com/thealgorithms/strings/Isogram.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/com/thealgorithms/strings/Isogram.java b/src/main/java/com/thealgorithms/strings/Isogram.java index e33301112882..950eb6e37978 100644 --- a/src/main/java/com/thealgorithms/strings/Isogram.java +++ b/src/main/java/com/thealgorithms/strings/Isogram.java @@ -26,6 +26,13 @@ * Reference from https://en.wikipedia.org/wiki/Heterogram_(literature)#Isograms */ public class Isogram { + + /** + * Private constructor to prevent instantiation of utility class. + */ + private Isogram() { + } + /** * Checks if a string is an isogram using boolean array approach. * From 280e6c79539a0f41d62de454396a16bd433f6d88 Mon Sep 17 00:00:00 2001 From: JeevaRamanathan Date: Thu, 2 Oct 2025 23:40:24 +0530 Subject: [PATCH 12/15] linter fix Signed-off-by: JeevaRamanathan --- src/main/java/com/thealgorithms/strings/Isogram.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/thealgorithms/strings/Isogram.java b/src/main/java/com/thealgorithms/strings/Isogram.java index 950eb6e37978..0fd23ad596f9 100644 --- a/src/main/java/com/thealgorithms/strings/Isogram.java +++ b/src/main/java/com/thealgorithms/strings/Isogram.java @@ -26,7 +26,6 @@ * Reference from https://en.wikipedia.org/wiki/Heterogram_(literature)#Isograms */ public class Isogram { - /** * Private constructor to prevent instantiation of utility class. */ From 37761cf621f7c87e43d9826986dc58f07563e777 Mon Sep 17 00:00:00 2001 From: JeevaRamanathan Date: Thu, 2 Oct 2025 23:44:28 +0530 Subject: [PATCH 13/15] updated isogram class to final Signed-off-by: JeevaRamanathan --- src/main/java/com/thealgorithms/strings/Isogram.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/thealgorithms/strings/Isogram.java b/src/main/java/com/thealgorithms/strings/Isogram.java index 0fd23ad596f9..cce55876adb7 100644 --- a/src/main/java/com/thealgorithms/strings/Isogram.java +++ b/src/main/java/com/thealgorithms/strings/Isogram.java @@ -25,7 +25,7 @@ * * Reference from https://en.wikipedia.org/wiki/Heterogram_(literature)#Isograms */ -public class Isogram { +public final class Isogram { /** * Private constructor to prevent instantiation of utility class. */ From c45d3b39d08d2b356a546d213af5a4d4f1cdae27 Mon Sep 17 00:00:00 2001 From: JeevaRamanathan Date: Thu, 2 Oct 2025 23:51:51 +0530 Subject: [PATCH 14/15] pipeline bug fixing Signed-off-by: JeevaRamanathan --- src/test/java/com/thealgorithms/strings/IsogramTest.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/thealgorithms/strings/IsogramTest.java b/src/test/java/com/thealgorithms/strings/IsogramTest.java index 14329375749a..28f20cd87c39 100644 --- a/src/test/java/com/thealgorithms/strings/IsogramTest.java +++ b/src/test/java/com/thealgorithms/strings/IsogramTest.java @@ -1,6 +1,7 @@ package com.thealgorithms.strings; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.stream.Stream; import org.junit.jupiter.api.Test; @@ -72,21 +73,21 @@ void testIsogramByLength(IsogramTestCase testCase) { @Test void testNullInputByArray() { - assertEquals(true, Isogram.isIsogramByArray(null)); + assertTrue(Isogram.isIsogramByArray(null)); } @Test void testNullInputByLength() { - assertEquals(true, Isogram.isIsogramByLength(null)); + assertTrue(Isogram.isIsogramByLength(null)); } @Test void testEmptyStringByArray() { - assertEquals(true, Isogram.isIsogramByArray("")); + assertTrue(Isogram.isIsogramByArray("")); } @Test void testEmptyStringByLength() { - assertEquals(true, Isogram.isIsogramByLength("")); + assertTrue(Isogram.isIsogramByLength("")); } } From 5c1da29f602db4902f15df2cb4b9c17b52389ab3 Mon Sep 17 00:00:00 2001 From: JeevaRamanathan Date: Fri, 3 Oct 2025 16:46:40 +0530 Subject: [PATCH 15/15] renamed function names and few fixes w.r.t to suggestion Signed-off-by: JeevaRamanathan --- .../com/thealgorithms/strings/Isogram.java | 29 ++++++------ .../thealgorithms/strings/IsogramTest.java | 44 ++++++++++++++----- 2 files changed, 50 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/thealgorithms/strings/Isogram.java b/src/main/java/com/thealgorithms/strings/Isogram.java index cce55876adb7..b37f085b075d 100644 --- a/src/main/java/com/thealgorithms/strings/Isogram.java +++ b/src/main/java/com/thealgorithms/strings/Isogram.java @@ -43,25 +43,28 @@ private Isogram() { * @throws IllegalArgumentException if the string contains non-alphabetic * characters */ - public static boolean isIsogramByArray(String str) { + public static boolean isAlphabeticIsogram(String str) { if (str == null || str.isEmpty()) { return true; } - String lowerStr = str.toLowerCase(); - boolean[] seenChars = new boolean[26]; + str = str.toLowerCase(); - for (int i = 0; i < lowerStr.length(); i++) { - char ch = lowerStr.charAt(i); + for (int i = 0; i < str.length(); i++) { + char ch = str.charAt(i); + if (ch < 'a' || ch > 'z') { + throw new IllegalArgumentException("Input contains non-alphabetic character: '" + ch + "'"); + } + } - // Check if character is a letter - if (ch >= 'a' && ch <= 'z') { - int index = ch - 'a'; - if (seenChars[index]) { - return false; // Letter already seen - } - seenChars[index] = true; + boolean[] seenChars = new boolean[26]; + for (int i = 0; i < str.length(); i++) { + char ch = str.charAt(i); + int index = ch - 'a'; + if (seenChars[index]) { + return false; } + seenChars[index] = true; } return true; } @@ -74,7 +77,7 @@ public static boolean isIsogramByArray(String str) { * @param str the input string * @return true if the string is an isogram, false otherwise */ - public static boolean isIsogramByLength(String str) { + public static boolean isFullIsogram(String str) { if (str == null || str.isEmpty()) { return true; } diff --git a/src/test/java/com/thealgorithms/strings/IsogramTest.java b/src/test/java/com/thealgorithms/strings/IsogramTest.java index 28f20cd87c39..9dd844dc7cf9 100644 --- a/src/test/java/com/thealgorithms/strings/IsogramTest.java +++ b/src/test/java/com/thealgorithms/strings/IsogramTest.java @@ -1,6 +1,8 @@ package com.thealgorithms.strings; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.stream.Stream; @@ -13,7 +15,7 @@ public class IsogramTest { record IsogramTestCase(String input, boolean expected) { } - private static Stream isogramArrayTestData() { + private static Stream isAlphabeticIsogram() { return Stream.of( // Valid isograms (only checks letters) new IsogramTestCase("uncopyrightable", true), new IsogramTestCase("dermatoglyphics", true), new IsogramTestCase("background", true), new IsogramTestCase("python", true), new IsogramTestCase("keyboard", true), new IsogramTestCase("clipboard", true), new IsogramTestCase("flowchart", true), @@ -30,7 +32,7 @@ private static Stream isogramArrayTestData() { new IsogramTestCase("Python", true), new IsogramTestCase("BACKGROUND", true), new IsogramTestCase("Hello", false), new IsogramTestCase("PROGRAMMING", false)); } - private static Stream isogramLengthTestData() { + private static Stream isFullIsogram() { return Stream.of( // Valid isograms (checks all characters) new IsogramTestCase("uncopyrightable", true), new IsogramTestCase("dermatoglyphics", true), new IsogramTestCase("background", true), new IsogramTestCase("python", true), new IsogramTestCase("keyboard", true), new IsogramTestCase("clipboard", true), new IsogramTestCase("flowchart", true), @@ -60,34 +62,56 @@ private static Stream isogramLengthTestData() { } @ParameterizedTest - @MethodSource("isogramArrayTestData") + @MethodSource("isAlphabeticIsogram") void testIsogramByArray(IsogramTestCase testCase) { - assertEquals(testCase.expected(), Isogram.isIsogramByArray(testCase.input())); + assertEquals(testCase.expected(), Isogram.isAlphabeticIsogram(testCase.input())); } @ParameterizedTest - @MethodSource("isogramLengthTestData") + @MethodSource("isFullIsogram") void testIsogramByLength(IsogramTestCase testCase) { - assertEquals(testCase.expected(), Isogram.isIsogramByLength(testCase.input())); + assertEquals(testCase.expected(), Isogram.isFullIsogram(testCase.input())); } @Test void testNullInputByArray() { - assertTrue(Isogram.isIsogramByArray(null)); + assertTrue(Isogram.isAlphabeticIsogram(null)); } @Test void testNullInputByLength() { - assertTrue(Isogram.isIsogramByLength(null)); + assertTrue(Isogram.isFullIsogram(null)); } @Test void testEmptyStringByArray() { - assertTrue(Isogram.isIsogramByArray("")); + assertTrue(Isogram.isAlphabeticIsogram("")); } @Test void testEmptyStringByLength() { - assertTrue(Isogram.isIsogramByLength("")); + assertTrue(Isogram.isFullIsogram("")); + } + + @Test + void testAlphabeticIsogramThrowsException() { + // Test that IllegalArgumentException is thrown for non-alphabetic characters + assertThrows(IllegalArgumentException.class, () -> Isogram.isAlphabeticIsogram("1")); + assertThrows(IllegalArgumentException.class, () -> Isogram.isAlphabeticIsogram("@")); + assertThrows(IllegalArgumentException.class, () -> Isogram.isAlphabeticIsogram("python!")); + assertThrows(IllegalArgumentException.class, () -> Isogram.isAlphabeticIsogram("123algorithm")); + assertThrows(IllegalArgumentException.class, () -> Isogram.isAlphabeticIsogram("hello123")); + assertThrows(IllegalArgumentException.class, () -> Isogram.isAlphabeticIsogram("!@@#$%^&*()")); + } + + @Test + void testFullIsogramWithMixedCharacters() { + // Test that full isogram method handles all character types without exceptions + assertTrue(Isogram.isFullIsogram("abc123")); + assertFalse(Isogram.isFullIsogram("test@email")); // 'e' repeats + assertFalse(Isogram.isFullIsogram("hello123")); // 'l' repeats + assertTrue(Isogram.isFullIsogram("1234567890")); + assertFalse(Isogram.isFullIsogram("12321")); // '1' and '2' repeat + assertTrue(Isogram.isFullIsogram("!@#$%^&*()")); } }