diff --git a/challenge_11/java/zmiller91/BST.java b/challenge_11/java/zmiller91/BST.java new file mode 100644 index 000000000..74c1b55b0 --- /dev/null +++ b/challenge_11/java/zmiller91/BST.java @@ -0,0 +1,205 @@ +import java.lang.Integer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * @author zmiller + */ +class Node { + public int data; + public Node left; + public Node right; + public Node parent; + + public Node(int data) { + this.data = data; + } +} + +class BST extends YOP { + + /** + * Inserts a value into a BST. + * + * @param data - what to insert + * @param head - where to insert + * @return insert node + */ + public Node insert (int data, Node head) { + + if (head == null) { + return new Node(data); + } + + if (data < head.data) { + if (head.left != null) { + return insert(data, head.left); + } + + head.left = new Node(data); + head.left.parent = head; + return head; + } + + if (data > head.data) { + if (head.right != null) { + return insert(data, head.right); + } + + head.right = new Node(data); + head.right.parent = head; + return head; + } + + // Ignore duplicates + return null; + } + + /** + * Removes an element from the list; `n` will remain the head + * after removal; + * + * @param data - value to delete + * @param n - head of subtree + */ + public void remove(int data, Node n) { + remove(search(data, n), n); + } + + /** + * Removes an element from the list; `n` will remain the head + * after removal; + * + * @param data - value to delete + * @param n - head of subtree + * @param head - a reference to the head of the tree + */ + protected void remove(Node remove, Node n) { + + if (remove == null){ + return; + } + + // Get the smallest on the right or largest on the left, depending on + // what children are set + Node swap = remove.right != null ? smallest(remove.right) : + remove.left != null ? largest(remove.left) : null; + + // Not a leaf node, recurse + if (swap != null) { + remove.data = swap.data; + remove(swap, remove); + } + + // Leaf node, unset the reference + else { + Node parent = remove.parent; + parent.left = parent.left != remove ? parent.left : null; + parent.right = parent.right != remove ? parent.right : null; + } + } + + /** + * Returns the object containing the provided data point + * + * @param data - value to be deleted + * @param n - tree to look at + */ + protected Node search(int data, Node n) { + + // Not found + if (n == null) { + return null; + } + + // Found, return the node + if (data == n.data) { + return n; + } + + // Search the next tree + Node next = data < n.data ? n.left : n.right; + return search(data, next); + } + + /** + * Finds the smallest element in a BST + * + * @param n - root of the tree + * @return the smallest node in the tree + */ + private Node smallest(Node n) { + + if (n != null) { + while (n.left != null) { + n = n.left; + } + } + return n; + } + + /** + * Finds the largest element in a BST + * + * @param n - root of the tree + * @return the largest node in the tree + */ + private Node largest(Node n) { + + if (n != null) { + while (n.right != null) { + n = n.right; + } + } + + return n; + } + + /** + * Prints a tree in pre-order DFS. + * + * @param head - tree to print + */ + public void print(Node head) { + + if (head == null) { + return; + } + + System.out.println(head.data); + print(head.left); + print(head.right); + } + + /** + * Executes the problem's solution + * + * @param input + */ + @Override + protected void run(String input) { + + // Create the BST + String[] split = input.split("\\|"); + int remove = Integer.parseInt(split[1].trim()); + Node head = null; + for (int i : csvToIntArray(split[0])) { + if (head == null) { + head = new Node(i); + continue; + } + + insert(i, head); + } + + print(head); + remove(remove, head); + System.out.println(); + print(head); + } + + public static void main(String args[]) { + launch(new BST()); + } +} \ No newline at end of file diff --git a/challenge_11/java/zmiller91/README.md b/challenge_11/java/zmiller91/README.md new file mode 100644 index 000000000..9e539a8af --- /dev/null +++ b/challenge_11/java/zmiller91/README.md @@ -0,0 +1,20 @@ +# Binary Search Tree + +This solution contains a BST implementation that can add and remove +elements from a tree; all functions run in O(log(n)) time. + +## How To Run + +``` +javac BST.java +java BST +``` + +# Input + +Input is accepted in the following format: + +``` +csv_of_elements | element_to_delete +1,2,3,4 | 3 +``` \ No newline at end of file diff --git a/challenge_11/java/zmiller91/YOP.java b/challenge_11/java/zmiller91/YOP.java new file mode 100644 index 000000000..8c818bd33 --- /dev/null +++ b/challenge_11/java/zmiller91/YOP.java @@ -0,0 +1,49 @@ +import java.lang.Integer; +import java.lang.String; +import java.util.Scanner; + +/** + * @author zmiller + */ +public abstract class YOP { + + protected int[] csvToIntArray(String csv) { + String[] strings = csv.split(","); + int[] ints = new int[strings.length]; + for (int i = 0; i < strings.length; i++) { + ints[i] = Integer.parseInt(strings[i].trim()); + } + + return ints; + } + + /** + * Executes the life cycle of the solution. + * + * @param yop - class to execute + */ + protected static void launch(YOP yop) { + + String input; + Scanner scan = new Scanner(System.in); + + System.out.println("Type 'done' to terminate.\n"); + while(true) { + System.out.print("Input: "); + input = scan.nextLine(); + if(input.toLowerCase().equals("done")) { + return; + } + + yop.run(input); + } + } + + /** + * Executes the solution + * + * @param input - command line input + */ + protected abstract void run(String input); + +} diff --git a/challenge_12/java/zmiller91/Compression.java b/challenge_12/java/zmiller91/Compression.java new file mode 100644 index 000000000..ddd50efac --- /dev/null +++ b/challenge_12/java/zmiller91/Compression.java @@ -0,0 +1,130 @@ + +import java.util.Arrays; + +/** + * @author zmiller + */ +public class Compression extends YOP{ + + /** + * Compresses a alphabetic string + * + * @param input - string to compress + * @return - compressed string + */ + public String compress(String input) { + + StringBuilder retval = new StringBuilder(); + StringBuilder sequence = new StringBuilder(); + for(char c : input.toCharArray()) { + + // Found the end of a sequence + if (sequence.length() > 0 && sequence.charAt(0) != c) { + retval.append(formatForCompression(sequence)); + sequence = new StringBuilder(); + } + + // Add to the sequence + sequence.append(c); + } + + // Don't forget the leftovers + return retval.append(formatForCompression(sequence)).toString(); + } + + /** + * Decompresses an alphabetic string + * + * @param input - string to decompress + * @return - decompressed string + */ + public String decompress(String input) { + StringBuilder retval = new StringBuilder(); + for(int i = 0; i < input.length(); i++) { + + // Compressed sequence, uncompress it + if(input.charAt(i) == '#') { + i++; + + // Find the number of repeated characters + StringBuilder count = new StringBuilder(); + while(i < input.length() && isInt(input.charAt(i))) { + count.append(input.charAt(i)); + i++; + } + + // Append a string with the correct number of repeated characters + retval.append(formatForDecompression( + retval.charAt(retval.length() - 1), + Integer.parseInt(count.toString()) - 1)); + + // Terminate if the string has been exhausted + if(i == input.length()) { + break; + } + } + + retval.append(input.charAt(i)); + } + + return retval.toString(); + } + + /** + * Checks if a character is an integer + * + * @param i + * @return + */ + private boolean isInt(char i) { + try { + Integer.parseInt(Character.toString(i)); + return true; + } + catch (Exception e) { + return false; + } + } + + /** + * Creates a string with repeated characters + * + * @param fillWith - characters to repeat + * @param size - number of repetitions + * @return repeated character string + */ + private String formatForDecompression(char fillWith, int size) { + char[] chars = new char[size]; + Arrays.fill(chars, fillWith); + return new String(chars); + } + + /** + * Takes a string with repeated characters and compresses it to the + * proper format + * + * @param sequence + * @return + */ + private String formatForCompression(StringBuilder sequence) { + if(sequence.length() > 3) { + return Character.toString(sequence.charAt(0))+ "#" + + Integer.toString(sequence.length()); + } + + return sequence.toString(); + } + + @Override + protected void run(String input) { + String compressed = compress(input); + System.out.println("Compressed: " + compressed); + String decompressed = decompress(compressed); + System.out.println("Decompressed: " + decompressed); + System.out.println("Decompressed == Input? " + decompressed.equals(input)); + } + + public static void main(String[] args) { + launch(new Compression()); + } +} diff --git a/challenge_12/java/zmiller91/README.md b/challenge_12/java/zmiller91/README.md new file mode 100644 index 000000000..fcdd056ec --- /dev/null +++ b/challenge_12/java/zmiller91/README.md @@ -0,0 +1,22 @@ +# Compression and Decompression + +This solution compresses and decompresses a string of alphabetic characters +by turning a repeating sequence into `character#repeated`, assuming the sequence +is repeated more than 3 times. + +## How To Run + +``` +javac Compression.java +java Compression +``` + +## Discussion + +* Space: O(N) +* Time: O(N) + +The solution builds a new string as it's compressed; if that space isn't +considered in the space complexity, then the solution would use O(1) space. This +solution works with empty strings and builds the compressed and decompressed +strings with a single pass. \ No newline at end of file diff --git a/challenge_12/java/zmiller91/YOP.java b/challenge_12/java/zmiller91/YOP.java new file mode 100644 index 000000000..8c818bd33 --- /dev/null +++ b/challenge_12/java/zmiller91/YOP.java @@ -0,0 +1,49 @@ +import java.lang.Integer; +import java.lang.String; +import java.util.Scanner; + +/** + * @author zmiller + */ +public abstract class YOP { + + protected int[] csvToIntArray(String csv) { + String[] strings = csv.split(","); + int[] ints = new int[strings.length]; + for (int i = 0; i < strings.length; i++) { + ints[i] = Integer.parseInt(strings[i].trim()); + } + + return ints; + } + + /** + * Executes the life cycle of the solution. + * + * @param yop - class to execute + */ + protected static void launch(YOP yop) { + + String input; + Scanner scan = new Scanner(System.in); + + System.out.println("Type 'done' to terminate.\n"); + while(true) { + System.out.print("Input: "); + input = scan.nextLine(); + if(input.toLowerCase().equals("done")) { + return; + } + + yop.run(input); + } + } + + /** + * Executes the solution + * + * @param input - command line input + */ + protected abstract void run(String input); + +}