diff --git a/src/medium/Division.java b/src/medium/Division.java
new file mode 100644
index 0000000..83bb28a
--- /dev/null
+++ b/src/medium/Division.java
@@ -0,0 +1,41 @@
+package medium;
+
+/**
+ * Have the function Division(num1,num2) take both parameters being passed
+ * and return the Greatest Common Factor.
+ * That is, return the greatest number that evenly goes into both numbers
+ * with no remainder.
+ * ---
+ * For example: 12 and 16 both are divisible by 1, 2, and 4 so the output should be 4.
+ * The range for both parameters will be from 1 to 10^3.
+ */
+public class Division {
+
+ /**
+ * Division function.
+ *
+ * @param num1 input number 1
+ * @param num2 input number 2
+ * @return the GCF
+ */
+ private static int division(int num1, int num2) {
+ if (num1 == 0 || num2 == 0) {
+ return num1 + num2;
+ }
+
+ return division(num2, num1 % num2);
+ }
+
+ /**
+ * Entry point.
+ *
+ * @param args command line arguments
+ */
+ public static void main(String[] args) {
+ int result1 = division(20, 40);
+ System.out.println(result1);
+ int result2 = division(12, 16);
+ System.out.println(result2);
+ }
+
+}
diff --git a/src/medium/EvenPairs.java b/src/medium/EvenPairs.java
new file mode 100644
index 0000000..c4c939b
--- /dev/null
+++ b/src/medium/EvenPairs.java
@@ -0,0 +1,99 @@
+package medium;
+
+/**
+ * Have the function EvenPairs(str) take the str parameter being passed
+ * and determine if a pair of adjacent even numbers exists anywhere
+ * in the string. If a pair exists, return the string true,
+ * otherwise return false.
+ * ---
+ * For example: if str is "f178svg3k19k46"
+ * then there are two even numbers at the end of the string, "46"
+ * so your program should return the string true.
+ * ---
+ * Another example: if str is "7r5gg812" then the pair is "812" (8 and 12)
+ * so your program should return the string true.
+ */
+public class EvenPairs {
+
+ /**
+ * Strips a string from non-numerical characters
+ * and splits the chunks into the array of strings
+ * e.g."5678dd12y" -> ["5678, "12"]
+ *
+ * @param str input string
+ * @return an array containing number groups
+ */
+ private static String[] splitNumbers(String str) {
+ return str
+ .toLowerCase()
+ .replaceAll("([^0-9])", " ")
+ .replaceAll(" +", " ")
+ .trim().split(" ");
+ }
+
+ /**
+ * Appends N following zeroes to 1 where N = number of digits
+ * e.g. 1 -> 1, 2 -> 100, 3 -> 1000
+ *
+ * @param digits number of digits
+ * @return expanded number
+ */
+ private static int addFollowingZeroes(int digits) {
+ int result = 1;
+ if (digits == 1) {
+ return result;
+ }
+ for (int i = 0; i < digits; i++) {
+ result *= 10;
+ }
+ return result;
+ }
+
+ /**
+ * Parses a number to determine if digits can form a pair of even number.
+ *
+ * @param num input number
+ * @return true if it's a pair of even numbers
+ */
+ private static boolean isEvenPair(Integer num) {
+ // get a number of digits
+ int len = (int) (Math.log10(num) + 1);
+ for (int i = len - 1; i > 0; i--) {
+ int num1 = num / addFollowingZeroes(i);
+ int num2 = num - num1;
+ if (num1 % 2 == 0 && num2 % 2 == 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Even Pairs function.
+ *
+ * @param str input string
+ * @return "true" if a pair exists
+ */
+ public static String evenPairs(String str) {
+ String[] coll = splitNumbers(str);
+ for (String item : coll) {
+ if (item.length() > 1 && isEvenPair(Integer.parseInt(item))) {
+ return "true";
+ }
+ }
+ return "false";
+ }
+
+ /**
+ * Entry point.
+ *
+ * @param args command line arguments
+ */
+ public static void main(String[] args) {
+ String result1 = evenPairs("7r5gg812");
+ System.out.println(result1);
+ String result2 = evenPairs("f178svg3k19k46");
+ System.out.println(result2);
+ }
+
+}
diff --git a/src/medium/HtmlElements.java b/src/medium/HtmlElements.java
new file mode 100644
index 0000000..12e51de
--- /dev/null
+++ b/src/medium/HtmlElements.java
@@ -0,0 +1,119 @@
+package medium;
+
+import java.util.Stack;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Have the function HTMLElements(str) read the str parameter being passed
+ * which will be a string of HTML DOM elements and plain text.
+ * ---
+ * The elements that will be used are: b, i, em, div, p.
+ * For example: if str is "
" then this string of DOM elements
+ * is nested correctly so your program should return the string true.
+ * ---
+ * If a string is not nested correctly, return the first element encountered where,
+ * if changed into a different element, would result in a properly formatted string.
+ * ---
+ * If the string is not formatted properly,
+ * then it will only be one element that needs to be changed.
+ * For example: if str is "helloworld"
+ * then your program should return the string div
+ * because if the first
element were changed into a
,
+ * the string would be properly formatted.
+ */
+public class HtmlElements {
+
+ /**
+ * A stack helps to determine if elements are nested correctly.
+ */
+ private static final Stack stack = new Stack<>();
+
+ /**
+ * Process a string to prepare for further inspection.
+ * 1. convert to lowercase
+ * 2. remove text content between tags
+ * 3. add spaces between tags
+ * 4. remove multiple spaces
+ * 5. trim (remove leading and trailing spaces)
+ * 6. split to array of strings
+ *
+ * @param str input string
+ * @return parsed string
+ */
+ private static String[] parseElements(String str) {
+ return str
+ .toLowerCase()
+ .replaceAll(">[^<]+", ">")
+ .replaceAll("([>])(?=[<])", "$1 ")
+ .replaceAll(" +", " ")
+ .trim().split(" ");
+ }
+
+ /**
+ * Checks if a string is an opening tag.
+ *
+ * @param tag a string to check
+ * @return true if a string is an opening tag
+ */
+ private static boolean isOpeningTag(String tag) {
+ Pattern pattern = Pattern.compile("<[a-z]>|<[a-z][a-z1-9]+>");
+ Matcher matcher = pattern.matcher(tag);
+ return matcher.find();
+ }
+
+ /**
+ * Checks if a string is an closing tag.
+ *
+ * @param tag a string to check
+ * @return true if a string is a closing tag
+ */
+ private static boolean isClosingTag(String tag) {
+ Pattern pattern = Pattern.compile("[a-z]>|[a-z][a-z1-9]+>");
+ Matcher matcher = pattern.matcher(tag);
+ return matcher.find();
+ }
+
+ /**
+ * Get an enclosed value.
+ *
+ * @param tag input tag with angle brackets
+ * @return the enclosed value of a tag
+ */
+ private static String getTagValue(String tag) {
+ return tag.replaceAll("[>]", "");
+ }
+
+ /**
+ * HTML Elements function.
+ *
+ * @param str input string
+ * @return "true" if elements are nested correctly, or an enclosed tag value if not.
+ */
+ private static String htmlElements(String str) {
+ String[] parsedTags = parseElements(str);
+ for (String tag : parsedTags) {
+ if (isOpeningTag(tag)) {
+ stack.push(tag);
+ } else if (isClosingTag(tag) && !stack.isEmpty()) {
+ if (getTagValue(stack.peek()).equals(getTagValue(tag))) {
+ stack.pop();
+ }
+ }
+ }
+ return stack.isEmpty() ? "true" : getTagValue(stack.peek());
+ }
+
+ /**
+ * Entry point.
+ *
+ * @param args command line arguments
+ */
+ public static void main(String[] args) {
+ String result1 = htmlElements("");
+ System.out.println(result1);
+ String result2 = htmlElements("");
+ System.out.println(result2);
+ }
+
+}
diff --git a/src/medium/PalindromeTwo.java b/src/medium/PalindromeTwo.java
new file mode 100644
index 0000000..883c6cd
--- /dev/null
+++ b/src/medium/PalindromeTwo.java
@@ -0,0 +1,57 @@
+package medium;
+
+/**
+ * Have the function PalindromeTwo(str) take the str parameter being passed
+ * and return the string true if the parameter is a palindrome,
+ * (the string is the same forward as it is backward)
+ * otherwise return the string false.
+ * ---
+ * The parameter entered may have punctuation and symbols,
+ * but they should not affect whether the string is in fact a palindrome.
+ * For example: "Anne, I vote more cars race Rome-to-Vienna" should return true.
+ */
+public class PalindromeTwo {
+
+ /**
+ * Check if a string is a palindrome.
+ *
+ * @param str input string
+ * @return true if a string is a palindrome
+ */
+ private static boolean isPalindrome(String str) {
+ char[] strArr = str.toCharArray();
+ int len = strArr.length;
+ for (int i = 0; i < len / 2; i++) {
+ if (strArr[i] != strArr[len - i - 1]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Palindrome Two function.
+ *
+ * @param str input string
+ * @return "true" if a string is a palindrome
+ */
+ public static String palindromeTwo(String str) {
+ String parsed = str.toLowerCase().replaceAll("[^a-z$]", "");
+ return isPalindrome(parsed) ? "true" : "false";
+ }
+
+ /**
+ * Entry point.
+ *
+ * @param args command line arguments
+ */
+ public static void main(String[] args) {
+ String result1 = palindromeTwo("Noel - sees Leon");
+ System.out.println(result1);
+ String result2 = palindromeTwo("A man, a plan, a canal – Panama.");
+ System.out.println(result2);
+ String result3 = palindromeTwo("No lemon, no melon!");
+ System.out.println(result3);
+ }
+
+}
diff --git a/src/medium/PrimeChecker.java b/src/medium/PrimeChecker.java
new file mode 100644
index 0000000..8dc551a
--- /dev/null
+++ b/src/medium/PrimeChecker.java
@@ -0,0 +1,115 @@
+package medium;
+
+import java.util.ArrayList;
+
+/**
+ * Have the function PrimeChecker(num) take num and return 1
+ * if any arrangement of num comes out to be a prime number, otherwise return 0.
+ * For example: if num is 910, the output should be 1
+ * because 910 can be arranged into 109 or 019, both of which are primes
+ */
+public class PrimeChecker {
+
+ /**
+ * Collection of permutations.
+ * E.g. [5, 9, 1, 2, 1, 5] -> 591521, 591512, 591251, 591215, ...
+ */
+ private static final ArrayList permutations = new ArrayList<>();
+
+ /**
+ * Check if a given number is a prime number.
+ *
+ * @param num input number
+ * @return true if is a prime number
+ */
+ private static boolean isPrime(int num) {
+ // prime numbers are greater than 1
+ if (num <= 1) {
+ return false;
+ }
+ // 2 is an only even prime number
+ // http://mathworld.wolfram.com/EvenPrime.html
+ if (num == 2) {
+ return true;
+ }
+ // eliminate all even numbers to reduce time complexity
+ // (cannot be a prime number if is divisible by 2)
+ if (num % 2 == 0) {
+ return false;
+ }
+ // no need to check the entire range from 0 to num
+ // (square root of num) + 1 is the sufficient upper limit
+ // which greatly reduces time complexity
+ double upper = Math.sqrt(num) + 1;
+ // since the even numbers are eliminated, we can check the odd numbers only
+ for (int i = 3; i < upper; i += 2) {
+ if (num % i == 0) {
+ // not a prime number
+ return false;
+ }
+ }
+ // must be a prime number!
+ return true;
+ }
+
+ /**
+ * Swap two elements in array.
+ *
+ * @param coll array of characters
+ * @param i number 1
+ * @param j number 2
+ */
+ private static void swap(char[] coll, int i, int j) {
+ char temp = coll[i];
+ coll[i] = coll[j];
+ coll[j] = temp;
+ }
+
+ /**
+ * Produce permutations of elements in a given array.
+ *
+ * @param coll array of characters
+ * @param index start index
+ */
+ private static void getPermutations(char[] coll, int index) {
+ if (index == coll.length - 1) {
+ permutations.add(Integer.parseInt(String.valueOf(coll)));
+ }
+ for (int i = index; i < coll.length; i++) {
+ swap(coll, index, i);
+ getPermutations(coll, index + 1);
+ swap(coll, index, i);
+ }
+ }
+
+ /**
+ * Prime Checker function.
+ *
+ * @param num input number
+ * @return 1 if permutations include a prime number
+ */
+ private static int primeChecker(int num) {
+ getPermutations(String.valueOf(num).toCharArray(), 0);
+ for (int i : permutations) {
+ if (isPrime(i)) {
+ // prime number is found in permutation
+ return 1;
+ }
+ }
+ // permutations do not include a prime number
+ return 0;
+ }
+
+ /**
+ * Entry point.
+ *
+ * @param args command line arguments
+ */
+ public static void main(String[] args) {
+ int result1 = primeChecker(591521);
+ System.out.println(result1);
+ int result2 = primeChecker(910);
+ System.out.println(result2);
+ }
+
+}
diff --git a/src/medium/PrimeMover.java b/src/medium/PrimeMover.java
new file mode 100644
index 0000000..cbe5ed5
--- /dev/null
+++ b/src/medium/PrimeMover.java
@@ -0,0 +1,77 @@
+package medium;
+
+/**
+ * Have the function PrimeMover(num) return the numth prime number.
+ * The range will be from 1 to 10^4.
+ * ---
+ * For example: if num is 16 the output should be 53 as 53 is the 16th prime number.
+ */
+public class PrimeMover {
+
+ /**
+ * Check if a given number is a prime number.
+ *
+ * @param num input number
+ * @return true if is a prime number
+ */
+ private static boolean isPrimeNumber(int num) {
+ // prime numbers are greater than 1
+ if (num <= 1) {
+ return false;
+ }
+ // 2 is an only even prime number
+ // http://mathworld.wolfram.com/EvenPrime.html
+ if (num == 2) {
+ return true;
+ }
+ // eliminate all even numbers to reduce time complexity
+ // (cannot be a prime number if is divisible by 2)
+ if (num % 2 == 0) {
+ return false;
+ }
+ // no need to check the entire range from 0 to num
+ // (square root of num) + 1 is the sufficient upper limit
+ // which greatly reduces time complexity
+ double upper = Math.sqrt(num) + 1;
+ // since the even numbers are eliminated, we can check the odd numbers only
+ for (int i = 3; i < upper; i += 2) {
+ if (num % i == 0) {
+ // not a prime number
+ return false;
+ }
+ }
+ // must be a prime number!
+ return true;
+ }
+
+ /**
+ * Prime Mover function.
+ *
+ * @param num input number
+ * @return Nth prime number where N = num
+ */
+ private static int primeMover(int num) {
+ int i = 1;
+ int primes = 0;
+ while (primes < num) {
+ if (isPrimeNumber(i)) {
+ primes++;
+ }
+ i++;
+ }
+ return i - 1;
+ }
+
+ /**
+ * Entry point.
+ *
+ * @param args command line arguments
+ */
+ public static void main(String[] args) {
+ int result1 = primeMover(9);
+ System.out.println(result1);
+ int result2 = primeMover(100);
+ System.out.println(result2);
+ }
+
+}
diff --git a/src/medium/PrimeTime.java b/src/medium/PrimeTime.java
new file mode 100644
index 0000000..e03f792
--- /dev/null
+++ b/src/medium/PrimeTime.java
@@ -0,0 +1,58 @@
+package medium;
+
+/**
+ * Have the function PrimeTime(num) take the num parameter being passed
+ * and return the string true if the parameter is a prime number,
+ * otherwise return the string false. The range will be between 1 and 2^16.
+ */
+public class PrimeTime {
+
+ /**
+ * Prime Time function.
+ *
+ * @param num input number
+ * @return "true" if a number is a prime number
+ */
+ private static boolean primeTime(int num) {
+ // prime numbers are greater than 1
+ if (num <= 1) {
+ return false;
+ }
+ // 2 is an only even prime number
+ // http://mathworld.wolfram.com/EvenPrime.html
+ if (num == 2) {
+ return true;
+ }
+ // eliminate all even numbers to reduce time complexity
+ // (cannot be a prime number if is divisible by 2)
+ if (num % 2 == 0) {
+ return false;
+ }
+ // no need to check the entire range from 0 to num
+ // (square root of num) + 1 is the sufficient upper limit
+ // which greatly reduces time complexity
+ double upper = Math.sqrt(num) + 1;
+ // since the even numbers are eliminated, we can check the odd numbers only
+ for (int i = 3; i < upper; i += 2) {
+ if (num % i == 0) {
+ // not a prime number
+ return false;
+ }
+ }
+ // must be a prime number!
+ return true;
+ }
+
+ /**
+ * Entry point.
+ *
+ * @param args command line arguments
+ */
+ public static void main(String[] args) {
+ var result1 = primeTime(199);
+ System.out.println(result1);
+ var result2 = primeTime(2129);
+ System.out.println(result2);
+ }
+
+}
diff --git a/src/medium/Primes.java b/src/medium/Primes.java
new file mode 100644
index 0000000..f737e0e
--- /dev/null
+++ b/src/medium/Primes.java
@@ -0,0 +1,62 @@
+package medium;
+
+/**
+ * Have the function Primes(num) take the num parameter being passed
+ * and return the string true if the parameter is a prime number,
+ * otherwise return the string false. The range will be between 1 and 2^16.
+ */
+public class Primes {
+
+ private static boolean isPrime(int num) {
+ // prime numbers are greater than 1
+ if (num <= 1) {
+ return false;
+ }
+ // 2 is an only even prime number
+ // http://mathworld.wolfram.com/EvenPrime.html
+ if (num == 2) {
+ return true;
+ }
+ // eliminate all even numbers to reduce time complexity
+ // (cannot be a prime number if is divisible by 2)
+ if (num % 2 == 0) {
+ return false;
+ }
+ // no need to check the entire range from 0 to num
+ // (square root of num) + 1 is the sufficient upper limit
+ // which greatly reduces time complexity
+ double upper = Math.sqrt(num) + 1;
+ // since the even numbers are eliminated, we can check the odd numbers only
+ for (int i = 3; i < upper; i += 2) {
+ if (num % i == 0) {
+ // not a prime number
+ return false;
+ }
+ }
+ // must be a prime number!
+ return true;
+ }
+
+ /**
+ * Primes function.
+ *
+ * @param num input number
+ * @return "true" if is a prime number
+ */
+ private static String primes(int num) {
+ return isPrime(num) ? "true" : "false";
+ }
+
+ /**
+ * Entry point.
+ *
+ * @param args command line arguments
+ */
+ public static void main(String[] args) {
+ String result1 = primes(195);
+ System.out.println(result1);
+ String result2 = primes(197);
+ System.out.println(result2);
+ }
+
+}
diff --git a/src/medium/RunLength.java b/src/medium/RunLength.java
new file mode 100644
index 0000000..bbb57db
--- /dev/null
+++ b/src/medium/RunLength.java
@@ -0,0 +1,50 @@
+package medium;
+
+/**
+ * Have the function RunLength(str) take the str parameter being passed
+ * and return a compressed version of the string using the Run-length encoding algorithm.
+ * ---
+ * This algorithm works by taking the occurrence of each repeating character
+ * and outputting that number along with a single character of the repeating sequence.
+ * ---
+ * For example: "wwwggopp" would return 3w2g1o2p.
+ * The string will not contain any numbers, punctuation, or symbols.
+ */
+public class RunLength {
+
+ /**
+ * Run Length function.
+ *
+ * @param str input string
+ * @return a compressed version of the string
+ */
+ private static String runLength(String str) {
+ StringBuilder output = new StringBuilder();
+ int count = 0;
+ char prev = str.charAt(0);
+ for (int i = 0; i < str.length(); i++) {
+ if (str.charAt(i) == prev) {
+ count++;
+ } else {
+ output.append(count).append(prev);
+ count = 1;
+ prev = str.charAt(i);
+ }
+ }
+ output.append(count).append(prev);
+ return output.toString();
+ }
+
+ /**
+ * Entry point.
+ *
+ * @param args command line arguments
+ */
+ public static void main(String[] args) {
+ var result1 = runLength("ultrarevolutionaries");
+ System.out.println(result1);
+ var result2 = runLength("underworld");
+ System.out.println(result2);
+ }
+
+}
diff --git a/src/medium/StringCalculate.java b/src/medium/StringCalculate.java
new file mode 100644
index 0000000..d2a4ba7
--- /dev/null
+++ b/src/medium/StringCalculate.java
@@ -0,0 +1,272 @@
+package medium;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Stack;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Have the function StringCalculate(str)
+ * take the str parameter being passed and evaluate
+ * the mathematical expression within in.
+ * The double asterisks (**) represent exponentiation.
+ * ---
+ * For example, if str were "(2+(3-1)*3)**3" the output should be 512.
+ * Another example: if str is "(2-0)(6/2)" the output should be 6.
+ * There can be parenthesis within the string, so you must evaluate
+ * it properly according to the rules of arithmetic.
+ * The string will contain the operators: +, -, /, *, (, ), and **.
+ * If you have a string like this: #/#*# or #+#(#)/#, then evaluate from left to right.
+ * So divide then multiply, and for the second one multiply, divide, then add.
+ * The evaluations will be such that there will not be any decimal operations,
+ * so you do not need to account for rounding.
+ */
+public class StringCalculate {
+
+ // evaluate the Postfix expression
+ private static final Stack posStack = new Stack<>();
+
+ /**
+ * Cleaning, parsing and splitting the input string into the array of tokens.
+ *
+ * @param str input string
+ * @return String array with parsed operators and operands
+ */
+ private static String[] parseConsoleInput(String str) {
+ // 1. convert to lowercase
+ // 2. replace exponent symbol ** with ^
+ // 3. replace (a)(b) with (a) * (b)
+ // 4. replace a(b) with a * (b)
+ // 5. split two bundled characters (but only when the second character is not a digit)
+ // 6. split bundled command/operator and a digit. Excl. minus to keep negative numbers intact.
+ // 7. remove multiple spaces
+ // 8. trim (remove leading and trailing spaces)
+ // 9. split to array of strings
+ return str
+ .toLowerCase()
+ .replaceAll("(\\*\\*)", "^")
+ .replaceAll("(\\)\\()", ")*(")
+ .replaceAll("([0-9])(?=[(])", "$1 *")
+ .replaceAll("([\\p{P}\\p{S}a-z0-9])(?=[\\p{P}\\p{S}a-z])", "$1 ")
+ .replaceAll("([^0-9])(?=[0-9])", "$1 ")
+ .replaceAll(" +", " ")
+ .trim().split(" ");
+ }
+
+ /**
+ * Prints out a message to the console if the user input is invalid.
+ *
+ * @param op single element of the input string
+ */
+ private static void printInputError(String op) {
+ System.out.println("Unrecognised operator or operand: \"" + op + "\".");
+ }
+
+ /**
+ * Reduces two operands to a single result
+ * by performing an arithmetical operation.
+ *
+ * @param a operand A
+ * @param b operand B
+ * @param operator denotes operation type (addition, substraction, division etc.)
+ * @return result of the arithmetical operation
+ * @throws ArithmeticException if divisor is 0
+ */
+ public static long reduceOperands(long a, long b, String operator) {
+ switch (operator) {
+ case "+":
+ return a + b;
+ case "-":
+ return a - b;
+ case "*":
+ return a * b;
+ case "/":
+ if (b == 0) {
+ System.out.println("Divide by 0.");
+ throw new ArithmeticException();
+ }
+ return a / b;
+ case "^":
+ return (long) Math.pow(a, b);
+ default:
+ return 0;
+ }
+ }
+
+ /**
+ * Checks if the token is an operand (0-9).
+ *
+ * @param op a single token from the input string
+ * @return true if the token is an operand, false if not
+ */
+ private static boolean isOperand(String op) {
+ Pattern pattern = Pattern.compile("^[\\d]|^-[\\d]");
+ Matcher matcher = pattern.matcher(op);
+ return matcher.find();
+ }
+
+ /**
+ * Checks if the token is an operator + - * / : ^ ( ) etc.
+ *
+ * @param op a single token from the input string
+ * @return true if the token is an operator, false if not
+ */
+ private static boolean isOperator(String op) {
+ Pattern pattern = Pattern.compile("^[+\\-*/^%]");
+ Matcher matcher = pattern.matcher(op);
+ return matcher.find();
+ }
+
+ /**
+ * Converts the Infix expression to Postfix.
+ *
+ * @param tokens expression tokens that are already parsed and split
+ * @return a postfix expression
+ */
+ private static String[] convertToPostfix(String[] tokens) {
+ Stack infStack = new Stack<>();
+ String terminating = "#";
+ Dictionary precedence = new Hashtable<>() {
+ {
+ put(terminating, 0);
+ put("(", 0);
+ put(")", 0);
+ put("+", 1);
+ put("-", 1);
+ put("*", 2);
+ put("/", 2);
+ put("^", 3);
+ }
+ };
+ ArrayList output = new ArrayList<>();
+ infStack.push(terminating);
+ for (String token : tokens) {
+ // token is an operand, add to output and move on
+ if (isOperand(token)) {
+ output.add(token);
+ continue;
+ }
+ // left parenthesis, push it to stack and move on
+ if (token.equals("(")) {
+ infStack.push(token);
+ continue;
+ }
+ // right parenthesis, keep popping until the left parenthesis is found
+ if (token.equals(")")) {
+ while (true) {
+ String op = infStack.pop();
+ if (op.equals("(")) {
+ break;
+ } else {
+ output.add(op);
+ }
+ }
+ continue;
+ }
+ // token is an operator
+ if (isOperator(token)) {
+ int cmp1 = precedence.get(token);
+ while (true) {
+ int cmp2 = precedence.get(infStack.peek());
+ // operand has higher precedence than item on the top of stack
+ if (cmp1 > cmp2) {
+ infStack.push(token);
+ break;
+ } else {
+ output.add(infStack.pop());
+ }
+ }
+ }
+ }
+ // pop the remaining items until the terminating symbol is reached (complete)
+ while (!infStack.empty() && !infStack.peek().equals(terminating)) {
+ output.add(infStack.pop());
+ }
+ return output.toArray(new String[0]);
+ }
+
+ /**
+ * Takes two operands from stack and perform the operation with a provider operator.
+ *
+ * @param operator denotes operation type (addition, substraction, division etc.)
+ * @return result of the evaluation
+ */
+ private static String performArithOperation(String operator) {
+ if (posStack.size() >= 2) {
+ // Safe to evaluate
+ String elementB = posStack.pop();
+ String elementA = posStack.pop();
+ long opB = Long.parseLong(elementB);
+ long opA = Long.parseLong(elementA);
+ long result = reduceOperands(opA, opB, operator);
+ return Long.toString(result);
+ } else {
+ // Stack underflow since at least one element is null
+ return null;
+ }
+ }
+
+ /**
+ * Computes the entire expression in Reverse Polish Notation.
+ *
+ * @param tokens expression tokens that are already parsed and split to Array of Strings
+ * @return result of the evaluation
+ */
+ private static Long evaluateExpression(String[] tokens) {
+ for (String token : tokens) {
+ // token is an operand, push it to stack and move on
+ if (isOperand(token)) {
+ posStack.push(token);
+ continue;
+ }
+ // token is an operator, evaluate
+ if (isOperator(token)) {
+ String result = performArithOperation(token);
+ if (result != null) {
+ posStack.push(result);
+ }
+ continue;
+ }
+ // token is illegal
+ printInputError(token);
+ }
+ // all tokens have been processed
+ if (posStack.isEmpty()) {
+ return null;
+ }
+ return Long.parseLong(posStack.peek());
+ }
+
+ /**
+ * String Calculate function.
+ *
+ * @param expression input string to evaluate
+ * @return a result as a string
+ */
+ public static String stringCalculate(String expression) {
+ String[] tokens = parseConsoleInput(expression);
+ String[] postfix = convertToPostfix(tokens);
+ Long result = evaluateExpression(postfix);
+ return result == null ? "" : result.toString();
+ }
+
+ /**
+ * Entry point.
+ *
+ * @param args command line arguments
+ */
+ public static void main(String[] args) {
+ String expression1 = "7-4-1+8(3)/2";
+ String result1 = stringCalculate(expression1);
+ System.out.println(result1);
+ String expression2 = "(2+2)*2";
+ String result2 = stringCalculate(expression2);
+ System.out.println(result2);
+ String expression3 = "2+2*2";
+ String result3 = stringCalculate(expression3);
+ System.out.println(result3);
+ }
+
+}
diff --git a/src/medium/StringScramble.java b/src/medium/StringScramble.java
new file mode 100644
index 0000000..97272e7
--- /dev/null
+++ b/src/medium/StringScramble.java
@@ -0,0 +1,55 @@
+package medium;
+
+import java.util.HashMap;
+
+/**
+ * Have the function StringScramble(str1,str2) take both parameters
+ * being passed and return the string true. if a portion of str1 characters
+ * can be rearranged to match str2, otherwise return the string false.
+ * For example: if str1 is "rkqodlw" and str2 is "world"
+ * the output should return true.
+ * Punctuation and symbols will not be entered with the parameters.
+ */
+public class StringScramble {
+
+ /**
+ * String Scramble function.
+ *
+ * @param str1 input string 1
+ * @param str2 input string 2
+ * @return "true" if rearranged string matches input string 2
+ */
+ private static String stringScramble(String str1, String str2) {
+ HashMap freq = new HashMap<>();
+ String[] arr1 = str1.replaceAll("([^" + str2 + "])", "").split("");
+ String[] arr2 = str2.split("");
+ for (String letter : arr1) {
+ if (freq.containsKey(letter)) {
+ freq.put(letter, freq.get(letter) + 1);
+ } else {
+ freq.put(letter, 1);
+ }
+ }
+ for (String letter : arr2) {
+ if (freq.containsKey(letter) && freq.get(letter) > 0) {
+ freq.put(letter, freq.get(letter) - 1);
+ } else {
+ return "false";
+ }
+ }
+ return "true";
+ }
+
+ /**
+ * Entry point.
+ *
+ * @param args command line arguments
+ */
+ public static void main(String[] args) {
+ String result1 = stringScramble("win33er", "winner");
+ System.out.println(result1);
+ String result2 = stringScramble("rkqodlw", "world");
+ System.out.println(result2);
+ }
+
+}
diff --git a/src/medium/ThreeFiveMultiples.java b/src/medium/ThreeFiveMultiples.java
new file mode 100644
index 0000000..19f1585
--- /dev/null
+++ b/src/medium/ThreeFiveMultiples.java
@@ -0,0 +1,60 @@
+package medium;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Have the function ThreeFiveMultiples(num) return the sum
+ * of all the multiples of 3 and 5 that are below num.
+ * For example: if num is 10, the multiples of 3 and 5
+ * that are below 10 are 3, 5, 6, and 9,
+ * and adding them up you get 23, so your program should return 23.
+ * The integer being passed will be between 1 and 100.
+ */
+public class ThreeFiveMultiples {
+
+ private static final Set freq = new HashSet<>();
+
+ /**
+ * Count Multiples.
+ *
+ * @param num input number
+ * @param mp a factor (multiplier)
+ */
+ private static void countMultiples(int num, int mp) {
+ for (int i = mp; i < num; i += mp) {
+ if (i % mp == 0) {
+ freq.add(i);
+ }
+ }
+ }
+
+ /**
+ * Three Five Multiples function.
+ *
+ * @param num input number
+ * @return a result
+ */
+ private static int threeFiveMultiples(int num) {
+ int total = 0;
+ countMultiples(num, 3);
+ countMultiples(num, 5);
+ for (int i : freq) {
+ total += i;
+ }
+ return total;
+ }
+
+ /**
+ * Entry point.
+ *
+ * @param args command line arguments
+ */
+ public static void main(String[] args) {
+ var result1 = threeFiveMultiples(17);
+ System.out.println(result1);
+ var result2 = threeFiveMultiples(117);
+ System.out.println(result2);
+ }
+
+}