From b00116bbbb057402b95331b8228cc6a7af929e71 Mon Sep 17 00:00:00 2001 From: MagicExists Date: Fri, 4 Aug 2023 22:00:36 +0700 Subject: [PATCH] Added jUnit test and fixed 2 bugs --- .../com/rampatra/strings/IntegerToString.java | 16 ++- .../com/rampatra/strings/StringToInteger.java | 13 +- .../com/rampatra/strings/SubStringCheck.java | 4 + .../rampatra/strings/TestIntegerToString.java | 60 +++++++++ .../rampatra/strings/TestStringToInteger.java | 104 +++++++++++++++ .../rampatra/strings/TestSubStringCheck.java | 126 ++++++++++++++++++ 6 files changed, 317 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/rampatra/strings/TestIntegerToString.java create mode 100644 src/main/java/com/rampatra/strings/TestStringToInteger.java create mode 100644 src/main/java/com/rampatra/strings/TestSubStringCheck.java diff --git a/src/main/java/com/rampatra/strings/IntegerToString.java b/src/main/java/com/rampatra/strings/IntegerToString.java index 08d27131..ad01c478 100644 --- a/src/main/java/com/rampatra/strings/IntegerToString.java +++ b/src/main/java/com/rampatra/strings/IntegerToString.java @@ -1,15 +1,22 @@ package com.rampatra.strings; /** - * @author rampatra + * @author rampatra, magicExists * @since 2019-04-01 */ + +/* + * Fix the negative case for this function. The problem is that when you modulo the number, it's a negative remainder, thus, making the assigning at char[i] wrong. For example, with number 2, your modulo operation gives -2, and when converted into the char, it's (-2 + '0') = (-2 + 48) = 46 (not 50) + * + * My solution is that I use absolute method before finding our remainder in order to find the positive value + */ + public class IntegerToString { private static final int[] sizeTable = {9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999, Integer.MAX_VALUE}; - private static String getStringFromInteger(int num) { + public static String getStringFromInteger(int num) { boolean isNegative = num < 0; num = isNegative ? -num : num; int size = getStringSize(num); @@ -18,7 +25,8 @@ private static String getStringFromInteger(int num) { int rem; for (int i = size - 1; isNegative ? i > 0 : i >= 0; i--) { - rem = num % 10; + //Changed here + rem = Math.abs(num % 10); num = num / 10; chars[i] = (char) (rem + '0'); } @@ -31,7 +39,7 @@ private static String getStringFromInteger(int num) { } private static int getStringSize(int num) { - if (num == Integer.MAX_VALUE) return 10; + if (num == Integer.MAX_VALUE || num == Integer.MIN_VALUE) return 10; // Not recommend this magic number at all for (int i = 0; ; i++) { if (num < sizeTable[i]) { diff --git a/src/main/java/com/rampatra/strings/StringToInteger.java b/src/main/java/com/rampatra/strings/StringToInteger.java index 53b386e7..6b449ae7 100644 --- a/src/main/java/com/rampatra/strings/StringToInteger.java +++ b/src/main/java/com/rampatra/strings/StringToInteger.java @@ -13,7 +13,7 @@ public class StringToInteger { * @param str the input string, for example, 0, 123, +123, -123, etc. * @return the equivalent integer. */ - private static int getIntegerFromString(String str) { + public static int getIntegerFromString(String str) { int number = 0; int digit; char ch; @@ -43,7 +43,15 @@ private static int getIntegerFromString(String str) { number += digit * (Math.pow(10, weight++)); } - return isNegative ? -number : number; + + //Make sure to check this case, when we give the number MIN_VALUE inside this function, first the number that converted will be positive, thus can only handle up to 2^31 - 1 value, so 1 value is offseted. So I check for the case if the value is negative, and the current value equals MAX_VALUE, to return the MIN_VALUE thoroughly + if (number == Integer.MAX_VALUE && isNegative) { + return -number - 1; + }else { + return isNegative ? -number : number; + } + + } public static void main(String[] args) { @@ -61,4 +69,5 @@ public static void main(String[] args) { System.out.println(getIntegerFromString(" ")); System.out.println(getIntegerFromString("123L")); } + } \ No newline at end of file diff --git a/src/main/java/com/rampatra/strings/SubStringCheck.java b/src/main/java/com/rampatra/strings/SubStringCheck.java index 63786967..d0f72757 100644 --- a/src/main/java/com/rampatra/strings/SubStringCheck.java +++ b/src/main/java/com/rampatra/strings/SubStringCheck.java @@ -19,6 +19,10 @@ public class SubStringCheck { * @return */ public static boolean isSubString(String s1, String s2) { + if (s1 == null || s2 == null) { + return false; //Since null doesn't present in any string, we can return false on such cases + } + char[] c1 = s1.toCharArray(), c2 = s2.toCharArray(); int l1 = c1.length, diff --git a/src/main/java/com/rampatra/strings/TestIntegerToString.java b/src/main/java/com/rampatra/strings/TestIntegerToString.java new file mode 100644 index 00000000..4cfe2f2f --- /dev/null +++ b/src/main/java/com/rampatra/strings/TestIntegerToString.java @@ -0,0 +1,60 @@ +package com.rampatra.strings; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + + +public class TestIntegerToString { + + @Test + static void integerCases(){ + //Positive, small number, expected: true + int a1 = 123; + String a2 = "123"; + + //Negative, small number, expected: true + int b1 = -123; + String b2 = "-123"; + + //0, expected: true + int c1 = 0; + String c2 = "0"; + + boolean resultA = a2.equals(IntegerToString.getStringFromInteger(a1)); + boolean resultB = b2.equals(IntegerToString.getStringFromInteger(b1)); + boolean resultC = c2.equals(IntegerToString.getStringFromInteger(c1)); + + assertTrue(resultA); + assertTrue(resultB); + assertTrue(resultB); + } + + @Test + static void boundaryCases() { + //INT_MAX + int a1 = Integer.MAX_VALUE; + String a2 = "2147483647"; + + //INT_MIN + int b1 = Integer.MIN_VALUE; + String b2 = "-2147483648"; + + //Trailing zero + int c1 = 000000000000; + String c2 = "0"; + + boolean resultA = a2.equals(IntegerToString.getStringFromInteger(a1)); + boolean resultB = b2.equals(IntegerToString.getStringFromInteger(b1)); + boolean resultC = c2.equals(IntegerToString.getStringFromInteger(c1)); + + assertTrue(resultA); + assertTrue(resultB); + assertTrue(resultC); + } + + public static void main(String args[]){ + integerCases(); + boundaryCases(); + } +} \ No newline at end of file diff --git a/src/main/java/com/rampatra/strings/TestStringToInteger.java b/src/main/java/com/rampatra/strings/TestStringToInteger.java new file mode 100644 index 00000000..dbfedf12 --- /dev/null +++ b/src/main/java/com/rampatra/strings/TestStringToInteger.java @@ -0,0 +1,104 @@ +package com.rampatra.strings; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +public class TestStringToInteger { + //It assumes the {@code string} contains ASCII characters only. + + @Test + public static void AllTestCases() { + //Empty cases + String test1 = ""; + int retVal = -1; + //In this case, we're expected to be thrown the numberFormatException + try { + retVal = StringToInteger.getIntegerFromString(test1); + }catch (NumberFormatException e) { + System.out.println("Exception case for \" Empty cases \" executed successfully."); + }finally { + System.out.println("End exception case. Return value: " + retVal); + } + + + //Positive number + String test2 = "2147483647"; + retVal = Integer.MAX_VALUE; + + assertEquals(StringToInteger.getIntegerFromString(test2), retVal); + + //Negative number + String test3 = "-2147483648"; + retVal = Integer.MIN_VALUE; + + assertEquals(retVal, StringToInteger.getIntegerFromString(test3)); + + //Zero leading + String test4 = "00000000000000000000000123123123"; + retVal = 123123123; + + assertEquals(StringToInteger.getIntegerFromString(test4), retVal); + + + //Zero leading and minus sign + String test5 = "00000-213"; + retVal = 0; + + //In this case, we're expected to be thrown the numberFormatException + try { + retVal = StringToInteger.getIntegerFromString(test5); + }catch (NumberFormatException e) { + System.out.println("Exception case for \" Zero leading and minus sign \" executed successfully."); + }finally { + System.out.println("End exception case. Return value: " + retVal); + } + + + //Ascii string + String test6 = "QWERTYUIOPASDFGHJKLZXCVBNM 1234567890 qwertyuiopasdfghjklzxcvbnm -=+!@#$%^&*() >:{ }|\\\\]"; + + //In this case, we're expected to be thrown the numberFormatException + try { + retVal = StringToInteger.getIntegerFromString(test6); + }catch (NumberFormatException e) { + System.out.println("Exception case for \" Ascii string \" executed successfully."); + }finally { + System.out.println("End exception case. Return value: " + retVal); + } + + + //Trailing ASCII character, positive value + String test7 = "123AAABBB"; + retVal = 123; + + //In this case, we're expected to be thrown the numberFormatException + try { + retVal = StringToInteger.getIntegerFromString(test7); + }catch (NumberFormatException e) { + System.out.println("Exception case for \" Trailing ASCII character, positive value \" executed successfully."); + }finally { + System.out.println("End exception case. Return value: " + retVal); + } + + + //Trailing ASCII character, negative value + String test8 = "-123AAABBB"; + retVal = 123; + + //In this case, we're expected to be thrown the numberFormatException + try { + retVal = StringToInteger.getIntegerFromString(test8); + }catch (NumberFormatException e) { + System.out.println("Exception case for \" Trailing ASCII character, negative value \" executed successfully."); + }finally { + System.out.println("End exception case. Return value: " + retVal); + } + + + } + + public static void main(String[] args) { + AllTestCases(); + } +} diff --git a/src/main/java/com/rampatra/strings/TestSubStringCheck.java b/src/main/java/com/rampatra/strings/TestSubStringCheck.java new file mode 100644 index 00000000..57cf4d56 --- /dev/null +++ b/src/main/java/com/rampatra/strings/TestSubStringCheck.java @@ -0,0 +1,126 @@ +package com.rampatra.strings; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + + +public class TestSubStringCheck { + static String assumedFilledString = "QWERTYUIOPASDFGHJKLZXCVBNM 1234567890 qwertyuiopasdfghjklzxcvbnm -=+!@#$%^&*() >:{ }|\\]"; + static String assumedFilledSubString = "QWERTYUIOPASDFGHJKLZXCVBNM"; + static String emptyString = ""; + static String nullString = null; + static String nonASCIIString = "Ă Â Ô Ơ Ư Ê ⏩ ☕ ☝ ♈ ぁ あ ぃ い ぅ う ぇ え ぉ お ؀ ؄ ç ù"; + static String nonASCIISubString = "ぁ あ ぃ い ぅ う ぇ え ぉ お ؀ ؄ ç ù"; + static String spaceString = " "; + + + @Test + static void happyCases() { + //First slot is main string + boolean resultA = SubStringCheck.isSubString(assumedFilledString, assumedFilledSubString); + + //Second slot is main string + boolean resultB = SubStringCheck.isSubString(assumedFilledSubString, assumedFilledString); + + //Both slot is the same + boolean resultC = SubStringCheck.isSubString(assumedFilledSubString, assumedFilledSubString); + + + //Assertion + assertTrue(resultA); + assertFalse(resultB); + assertTrue(resultC); + } + + @Test + static void emptyCases() { + + //First slot is empty + boolean resultA = SubStringCheck.isSubString(emptyString, assumedFilledString); + + //Second slot is empty + boolean resultB = SubStringCheck.isSubString(assumedFilledString, emptyString); + + //Both slot is empty + boolean resultC = SubStringCheck.isSubString(emptyString, emptyString); + + + //Assertion + assertFalse(resultA); + assertTrue(resultB); + assertTrue(resultC); + } + + @Test + static void nullCases() { + //First slot is null + boolean resultA = SubStringCheck.isSubString(nullString, assumedFilledString); + + //Second slot is null + boolean resultB = SubStringCheck.isSubString(assumedFilledString, nullString); + + //Both slot is null + boolean resultC = SubStringCheck.isSubString(nullString, nullString); + + //First slot is null and second slot is empty + boolean resultD = SubStringCheck.isSubString(nullString, emptyString); + + //First slot is empty and second slot is null + boolean resultE = SubStringCheck.isSubString(emptyString, nullString); + + //Assertion + assertFalse(resultA); + assertFalse(resultB); + assertFalse(resultC); + assertFalse(resultD); + assertFalse(resultE); + } + + @Test + static void spaceCases() { + //First slot is full of spaces + boolean resultA = SubStringCheck.isSubString(spaceString, assumedFilledString); + + + //Second slot is full of spaces + boolean resultB = SubStringCheck.isSubString(assumedFilledString, spaceString); + + + //Both slot is full of spaces + boolean resultC = SubStringCheck.isSubString(spaceString, spaceString); + + //Assertion + assertFalse(resultA); + assertFalse(resultB); + assertTrue(resultC); + } + + @Test + static void nonASCIICases() { + //Good case + boolean resultA = SubStringCheck.isSubString(nonASCIIString, nonASCIISubString); + + + //Second slot is empty + boolean resultB = SubStringCheck.isSubString(nonASCIIString, emptyString); + + + //Second slot is null + boolean resultC = SubStringCheck.isSubString(nonASCIIString, nullString); + + //Assertion + assertTrue(resultA); + assertTrue(resultB); + assertFalse(resultC); + } + + public static void main(String[] args) { + happyCases(); + emptyCases(); + nullCases(); + spaceCases(); + nonASCIICases(); + } +}