From 68ea2b2f927fa57537a0ad69bda57ec1018e7ef4 Mon Sep 17 00:00:00 2001 From: silkycode Date: Thu, 15 Jun 2023 00:32:04 -0700 Subject: [PATCH] Replaced skeleton code with assignment code --- src/main/java/StringManipulation.java | 97 ++++++++++- .../java/StringManipulationInterface.java | 6 +- src/test/java/StringManipulationTest.java | 153 ++++++++++++++---- 3 files changed, 211 insertions(+), 45 deletions(-) diff --git a/src/main/java/StringManipulation.java b/src/main/java/StringManipulation.java index 4deb6f1..ab8fcb7 100644 --- a/src/main/java/StringManipulation.java +++ b/src/main/java/StringManipulation.java @@ -1,33 +1,116 @@ +// Nick Cudd +// CS 410 Spring 2023 +// JUnit Testing Assignment + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.regex.Pattern; + public class StringManipulation implements StringManipulationInterface { + private String myString; + @Override public String getString() { - return null; + return myString; } @Override public void setString(String string) { + myString = string; } @Override public int count() { - return 0; + if (myString == null || myString.length() == 0) { + return 0; + } + int wordCount = 0; + // Use both whitespace and half thin-space characters to slice strings + String[] tokens = myString.split(" | "); + for (String i : tokens) { + if (Pattern.matches("^[A-Za-z]+$", i)) { + wordCount++; + } + } + return wordCount; } @Override public String removeNthCharacter(int n, boolean maintainSpacing) { - return null; + if (n <= 0) { + throw new IllegalArgumentException("n is invalid: n > 0"); + } else if (myString == null) { + throw new NullPointerException("String has not been initialized yet, or is null"); + } else if (n > myString.length()) { + throw new IndexOutOfBoundsException("n cannot exceed length of parameter String"); + } + + ArrayList characters = new ArrayList(); + for (char c : myString.toCharArray()) { + characters.add(c); + } + + for (int position = n, k = 2; position <= myString.length(); position = k * n, k++) { + if (maintainSpacing) { + characters.set((position - 1), ' '); + } else + characters.set((position - 1), null); + } + + String newString = ""; + for (Character c: characters) { + if (c != null) { + newString += c; + } + } + return newString; } @Override public String[] getSubStrings(int startWord, int endWord) { - return null; + if (myString == null) { + throw new NullPointerException("String has not been initialized yet, or is null"); + } else if (startWord <= 0 || endWord <= 0) { + throw new IllegalArgumentException("startWord and endWord cannot be less than 1"); + } else if (endWord < startWord) { + throw new IndexOutOfBoundsException("index of endWord cannot be prior to index of startWord"); + } + + int numberOfWords = (endWord - startWord) + 1; + String[] words = myString.split(" | "); + String[] subWords = new String[numberOfWords]; + for (int i = 0, j = startWord - 1; i < numberOfWords; i++, j++) { + subWords[i] = words[j]; + } + return subWords; } @Override public String restoreString(int[] indices) { - return null; + if (myString == null) { + throw new NullPointerException("String has not been initialized yet, or is null"); + } + // Examine passed indices array for validity + if (indices.length != myString.length()) { + throw new IllegalArgumentException("passed index array must be same length as current String"); + } + for (int i = 0; i < indices.length - 1; i++) { + if (indices[i] < 0 || indices[i] > myString.length()) { + throw new IndexOutOfBoundsException("Array of indices cannot contain negative integers or integers greater than the length of the current String"); + } + // Check for duplicate integers + for (int j = i + 1; j < indices.length; j++) { + if (indices[i] == indices[j]) { + throw new IllegalArgumentException("passed index array must contain unique integer values"); + } + } + } + char[] charString = myString.toCharArray(); + char[] referenceString = myString.toCharArray(); + for (int i = 0; i < charString.length; i++) { + charString[i] = referenceString[indices[i]]; + } + return new String(charString); } - - } diff --git a/src/main/java/StringManipulationInterface.java b/src/main/java/StringManipulationInterface.java index 87127e7..cc81e80 100644 --- a/src/main/java/StringManipulationInterface.java +++ b/src/main/java/StringManipulationInterface.java @@ -79,10 +79,10 @@ public interface StringManipulationInterface { * The string s will be shuffled such that the character at the ith position moves to indices[i] in the shuffled string. * Return the shuffled string. * example: - * Input: string = "UnitTest", indices = [4,5,6,7,0,1,2,3] + * Input: string = "UnitTest", indices = [4,5,6,7,0,2,1,3] * Output: "TestUnit" * Explanation: - * indices: 4 5 6 7 0 1 2 3 + * indices: 4 5 6 7 0 2 1 3 * String: U n i t T e s t * Actions to Shuffle: Shift U to 4th position, n to 5th position, i to 6th position ...... * Output: T e s t U n i t @@ -95,7 +95,7 @@ public interface StringManipulationInterface { * indices length is the same as the string length. * * throws IllegalArgumentException if not s.length == indices.length == n - * throws IndexOutOfBoundsException if indices[i]< 0 or indices[i]>= string length + * throws IndexOutOfBoundsException if indices[i]< 0 or indices[i]> string length * * @param indices is an integer array for shuffled string new indices positions * the character at the ith position moves to indices[i] in the shuffled string. diff --git a/src/test/java/StringManipulationTest.java b/src/test/java/StringManipulationTest.java index 6692c2c..4fc244b 100644 --- a/src/test/java/StringManipulationTest.java +++ b/src/test/java/StringManipulationTest.java @@ -1,6 +1,11 @@ +// Nick Cudd +// CS 410 Spring 2023 +// JUnit Testing Assignment + import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.platform.commons.util.StringUtils; import static org.junit.jupiter.api.Assertions.*; @@ -19,6 +24,7 @@ public void tearDown() { manipulatedstring = null; } + // test to ensure that StringManipulation.count() returns 4 when input string contains 4 alphabetical tokens @Test public void testCount1() { manipulatedstring.setString("This is my string"); @@ -26,124 +32,201 @@ public void testCount1() { assertEquals(4, length); } + // test to ensure that StringManipulation.count() does not increase count when parsing non-alphabetical tokens + // assumes that "words" are comprised of only alphabetic characters @Test public void testCount2() { - fail("Not yet implemented"); + manipulatedstring.setString("1-4/3* +1.,2 12']--3 word helo34"); + int length = manipulatedstring.count(); + assertEquals(1, length); } + // test to ensure that StringManipulation.count() returns 0 when given empty string @Test public void testCount3() { - fail("Not yet implemented"); + manipulatedstring.setString(" "); + int length = manipulatedstring.count(); + assertEquals(0, length); } + // test to ensure that half-space character (U+2009) slices string correctly (avoid potential issue when copy-pasting strings) @Test public void testCount4() { - fail("Not yet implemented"); + manipulatedstring.setString("This is my string"); + int length = manipulatedstring.count(); + assertEquals(4, length); } + // test to ensure that removeNthCharacter() concatenates string when spacing is to be ignored @Test public void testRemoveNthCharacter1() { manipulatedstring.setString("I'd b3tt3r put s0me d161ts in this 5tr1n6, right?"); assertEquals("I' bttr uts0e 16tsinths trn6 rgh?", manipulatedstring.removeNthCharacter(3, false)); } + // test to ensure that removeNthCharacter() preserves whitespace when spacing is to be maintained @Test public void testRemoveNthCharacter2() { manipulatedstring.setString("I'd b3tt3r put s0me d161ts in this 5tr1n6, right?"); assertEquals("I' b tt r ut s0 e 16 ts in th s tr n6 r gh ?", manipulatedstring.removeNthCharacter(3, true)); } + // test to ensure removeNthCharacter() throws an IllegalArgumentException when passed n <= 0 @Test public void testRemoveNthCharacter3() { - fail("Not yet implemented"); + manipulatedstring.setString("test"); + IllegalArgumentException testException = assertThrows(IllegalArgumentException.class, () -> { + manipulatedstring.removeNthCharacter(-3, true); + }); + assertEquals("n is invalid: n > 0", testException.getMessage()); } + // test to ensure removeNthCharacter() throws an IndexOutOfBoundsException when passed n is greater than length of string @Test public void testRemoveNthCharacter4() { - fail("Not yet implemented"); + manipulatedstring.setString("test"); + IndexOutOfBoundsException testException = assertThrows(IndexOutOfBoundsException.class, () -> { + manipulatedstring.removeNthCharacter(10, true); + }); + assertEquals("n cannot exceed length of parameter String", testException.getMessage()); } + // test to ensure removeNthCharacter returns an empty string in the edge case of n = 1 when spacing is not maintained @Test public void testRemoveNthCharacter5() { - fail("Not yet implemented"); + manipulatedstring.setString("test"); + assertEquals("", manipulatedstring.removeNthCharacter(1, false)); } + /* test to ensure removeNthCharacter returns a string in the edge case of n = 1 + with exactly as the same count of whitespace as the count of original characters when spacing is maintained */ @Test public void testRemoveNthCharacter6() { - fail("Not yet implemented"); + manipulatedstring.setString("11111"); + assertEquals(" ".length(), manipulatedstring.removeNthCharacter(1, true).length()); } + // test to ensure removeNthCharacter can process a null string by throwing a NullPointerException @Test public void testRemoveNthCharacter7() { - fail("Not yet implemented"); + manipulatedstring.setString(null); + NullPointerException testException = assertThrows(NullPointerException.class, () -> { + manipulatedstring.removeNthCharacter(3, true); + }); + assertEquals("String has not been initialized yet, or is null", testException.getMessage()); } @Test public void testGeSubStrings1() { manipulatedstring.setString("This is my string"); - String [] sStings = manipulatedstring.getSubStrings(3, 4); + String[] sStrings = manipulatedstring.getSubStrings(3, 4); - assertEquals(sStings[0], "my"); - assertEquals(sStings[1], "string"); + assertEquals(sStrings[0], "my"); + assertEquals(sStrings[1], "string"); } + // test to ensure getSubStrings() throws an IllegalArgumentException when endWord or startWord indices <= 0 @Test public void testGeSubStrings2() { - fail("Not yet implemented"); + manipulatedstring.setString("test string with spaces"); + IllegalArgumentException testException = assertThrows(IllegalArgumentException.class, () -> { + manipulatedstring.getSubStrings(-3, 5); + }); + assertEquals("startWord and endWord cannot be less than 1", testException.getMessage()); } + + // test to ensure getSubStrings() throws an IndexOutOfBoundsException when startWord index > endWord index @Test public void testGeSubStrings3() { - fail("Not yet implemented"); + manipulatedstring.setString("test string with spaces"); + IndexOutOfBoundsException testException = assertThrows(IndexOutOfBoundsException.class, () -> { + manipulatedstring.getSubStrings(13, 5); + }); + assertEquals("index of endWord cannot be prior to index of startWord", testException.getMessage()); } + + /* because getSubStrings() is inclusive, + test to ensure that getSubStrings() returns a + String array of a single word in unique case where startWord = endWord */ @Test public void testGeSubStrings4() { - fail("Not yet implemented"); + manipulatedstring.setString("This is my string"); + String [] sStrings = manipulatedstring.getSubStrings(3, 3); + assertEquals(sStrings[0], "my"); } + + // test to ensure getSubString() can handle a null string by throwing a NullPointerException @Test public void testGeSubStrings5() { - fail("Not yet implemented"); + manipulatedstring.setString(null); + NullPointerException testException = assertThrows(NullPointerException.class, () -> { + manipulatedstring.getSubStrings(3, 4); + }); + assertEquals("String has not been initialized yet, or is null", testException.getMessage()); } + + /* test to ensure that getSubString() can handle half-space character (U+2009) and + slices string correctly (avoids potential issue when copy-pasting strings) */ @Test public void testGeSubStrings6() { - fail("Not yet implemented"); + manipulatedstring.setString("This is my string"); + String[] sStrings = manipulatedstring.getSubStrings(1, 3); + assertEquals("This", sStrings[0]); + assertEquals("my", sStrings[2]); } @Test public void testRestoreString1() { manipulatedstring.setString("art"); - int [] array; - array=new int[]{1,0,2}; + int[] array; + array = new int[]{1,0,2}; String restoreString = manipulatedstring.restoreString(array); assertEquals(restoreString, "rat"); } + // test to ensure that restoreString() throws an IllegalArgumentException when passed index array length != string length @Test - public void testRestoreString2() - { - fail("Not yet implemented"); - + public void testRestoreString2() { + int[] array = new int[]{1,0,2,3}; + manipulatedstring.setString("art"); + IllegalArgumentException testException = assertThrows(IllegalArgumentException.class, () -> { + manipulatedstring.restoreString(array); + }); + assertEquals("passed index array must be same length as current String", testException.getMessage()); } + // test to ensure that restoreString() throws an IllegalArgumentException when passed index array contains duplicates @Test - public void testRestoreString3() - { - fail("Not yet implemented"); - + public void testRestoreString3() { + int[] array = new int[]{1,1,2}; + manipulatedstring.setString("art"); + IllegalArgumentException testException = assertThrows(IllegalArgumentException.class, () -> { + manipulatedstring.restoreString(array); + }); + assertEquals("passed index array must contain unique integer values", testException.getMessage()); } + // test to ensure that restoreString() throws a NullPointerException when current string is null @Test - public void testRestoreString4() - { - fail("Not yet implemented"); - + public void testRestoreString4() { + int[] array = new int[]{1,0,2}; + manipulatedstring.setString(null); + NullPointerException testException = assertThrows(NullPointerException.class, () -> { + manipulatedstring.restoreString(array); + }); + assertEquals("String has not been initialized yet, or is null", testException.getMessage()); } + // test to ensure that restoreString() throws an IndexOutOfBoundsException when passed index array contains integers beyond length of String @Test - public void testRestoreString5() - { - fail("Not yet implemented"); - + public void testRestoreString5() { + int[] array = new int[]{1,2,7,4,5,3}; + manipulatedstring.setString("string"); + IndexOutOfBoundsException testException = assertThrows(IndexOutOfBoundsException.class, () -> { + manipulatedstring.restoreString(array); + }); + assertEquals("Array of indices cannot contain negative integers or integers greater than the length of the current String", testException.getMessage()); } - } +