diff --git a/src/main/java/org/nintynine/problems/BTree54.java b/src/main/java/org/nintynine/problems/BTree54.java index 3bb43eb..7840802 100644 --- a/src/main/java/org/nintynine/problems/BTree54.java +++ b/src/main/java/org/nintynine/problems/BTree54.java @@ -2,212 +2,212 @@ import java.util.Objects; -/** - * P54A: Check whether a given expression represents a binary tree - */ +/** P54A: Check whether a given expression represents a binary tree */ public class BTree54 { + /** Represents a node in the binary tree expression */ + public static class BTree54Node { + private final String value; + private final BTree54Node left; + private final BTree54Node right; + /** - * Represents a node in the binary tree expression + * Constructs a binary tree node + * + * @param value The value at this node + * @param left Left child node or null + * @param right Right child node or null */ - public static class BTree54Node { - private final String value; - private final BTree54Node left; - private final BTree54Node right; - - /** - * Constructs a binary tree node - * @param value The value at this node - * @param left Left child node or null - * @param right Right child node or null - */ - public BTree54Node(String value, BTree54Node left, BTree54Node right) { - this.value = Objects.requireNonNull(value, "Node value cannot be null"); - this.left = left; - this.right = right; - } - - /** - * Creates a leaf node with no children - * @param value The value at this node - */ - public BTree54Node(String value) { - this(value, null, null); - } + public BTree54Node(String value, BTree54Node left, BTree54Node right) { + this.value = Objects.requireNonNull(value, "Node value cannot be null"); + this.left = left; + this.right = right; + } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof BTree54Node bTree54Node)) return false; - return Objects.equals(value, bTree54Node.value) && - Objects.equals(left, bTree54Node.left) && - Objects.equals(right, bTree54Node.right); - } + /** + * Creates a leaf node with no children + * + * @param value The value at this node + */ + public BTree54Node(String value) { + this(value, null, null); + } - @Override - public int hashCode() { - return Objects.hash(value, left, right); - } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof BTree54Node bTree54Node)) return false; + return Objects.equals(value, bTree54Node.value) + && Objects.equals(left, bTree54Node.left) + && Objects.equals(right, bTree54Node.right); + } - @Override - public String toString() { - if (left == null && right == null) { - if (value.startsWith("(")) { - return value; - } - return String.format("(%s nil nil)", value); - } - return String.format("(%s %s %s)", - value, - left == null ? "nil" : left.toString(), - right == null ? "nil" : right.toString() - ); - } + @Override + public int hashCode() { + return Objects.hash(value, left, right); + } + @Override + public String toString() { + if (left == null && right == null) { + if (value.startsWith("(")) { + return value; + } + return String.format("(%s nil nil)", value); + } + return String.format( + "(%s %s %s)", + value, left == null ? "nil" : left.toString(), right == null ? "nil" : right.toString()); } + } - private BTree54() {} // Prevent instantiation + private BTree54() {} // Prevent instantiation -private static boolean isValidValue(String value) { + private static boolean isValidValue(String value) { // Check for any special characters or improper formatting - return value != null && !value.isEmpty() && - !value.contains("(") && !value.contains(")") && - !value.contains(",") && !value.contains(" ") && - !"nil".equals(value); -} - -public static boolean isTree(String expression) { + return value != null + && !value.isEmpty() + && !value.contains("(") + && !value.contains(")") + && !value.contains(",") + && !value.contains(" ") + && !"nil".equals(value); + } + + public static boolean isTree(String expression) { if (expression == null || expression.trim().isEmpty()) { - return false; + return false; } // Pre-validate the expression format String trimmed = expression.trim(); - + // Check for invalid formatting patterns - if (trimmed.contains(")(") || // Multiple expressions - trimmed.contains(",") || // Commas - trimmed.matches(".*\\w\\(.*") || // No space before opening parenthesis - trimmed.matches(".*\\)\\w.*")) { // No space after closing parenthesis - return false; + if (trimmed.contains(")(") + || // Multiple expressions + trimmed.contains(",") + || // Commas + trimmed.matches(".*\\w\\(.*") + || // No space before opening parenthesis + trimmed.matches(".*\\)\\w.*")) { // No space after closing parenthesis + return false; } try { - // Handle single value case - if (!trimmed.startsWith("(")) { - return isValidValue(trimmed); - } - - // For expressions in parentheses, try parsing - parseTree(trimmed); - return true; - } catch (IllegalArgumentException _) { - return false; + // Handle single value case + if (!trimmed.startsWith("(")) { + return isValidValue(trimmed); + } + + // For expressions in parentheses, try parsing + parseTree(trimmed); + return true; + } catch (IllegalArgumentException e) { + return false; + } + } + + /** + * Parses a string expression into a binary tree. + * + * @param expression The string expression to parse + * @return The root node of the parsed tree + * @throws IllegalArgumentException if the expression is invalid + */ + public static BTree54Node parseTree(String expression) { + if (expression == null) { + throw new IllegalArgumentException("Expression cannot be null"); } -} - /** - * Parses a string expression into a binary tree. - * - * @param expression The string expression to parse - * @return The root node of the parsed tree - * @throws IllegalArgumentException if the expression is invalid - */ - public static BTree54Node parseTree(String expression) { - if (expression == null) { - throw new IllegalArgumentException("Expression cannot be null"); - } + expression = expression.trim(); - expression = expression.trim(); - - // Handle single value case - if (!expression.startsWith("(")) { - if (isValidValue(expression)) { - return new BTree54Node(expression); - } - throw new IllegalArgumentException("Invalid value: " + expression); - } + // Handle single value case + if (!expression.startsWith("(")) { + if (isValidValue(expression)) { + return new BTree54Node(expression); + } + throw new IllegalArgumentException("Invalid value: " + expression); + } - // Remove outer parentheses - if (!expression.endsWith(")")) { - throw new IllegalArgumentException("Missing closing parenthesis"); - } - expression = expression.substring(1, expression.length() - 1).trim(); + // Remove outer parentheses + if (!expression.endsWith(")")) { + throw new IllegalArgumentException("Missing closing parenthesis"); + } + expression = expression.substring(1, expression.length() - 1).trim(); - // Split into value and subtrees - String[] parts = splitExpression(expression); - if (parts.length != 3) { - throw new IllegalArgumentException("Invalid node format"); - } + // Split into value and subtrees + String[] parts = splitExpression(expression); + if (parts.length != 3) { + throw new IllegalArgumentException("Invalid node format"); + } - String value = parts[0]; - String leftExpr = parts[1]; - String rightExpr = parts[2]; + String value = parts[0]; + String leftExpr = parts[1]; + String rightExpr = parts[2]; - if (!isValidValue(value)) { - throw new IllegalArgumentException("Invalid node value"); - } + if (!isValidValue(value)) { + throw new IllegalArgumentException("Invalid node value"); + } - BTree54Node left = "nil".equals(leftExpr) ? null : parseTree(leftExpr); - BTree54Node right = "nil".equals(rightExpr) ? null : parseTree(rightExpr); + BTree54Node left = "nil".equals(leftExpr) ? null : parseTree(leftExpr); + BTree54Node right = "nil".equals(rightExpr) ? null : parseTree(rightExpr); - return new BTree54Node(value, left, right); - } + return new BTree54Node(value, left, right); + } -@SuppressWarnings("java:S5852") -private static String[] splitExpression(String expr) { + @SuppressWarnings("java:S5852") + private static String[] splitExpression(String expr) { // Add space validation if (expr.contains(")(") || expr.matches(".*\\w\\(.*") || expr.matches(".*\\)\\w.*")) { - throw new IllegalArgumentException("Invalid expression format"); + throw new IllegalArgumentException("Invalid expression format"); } String[] result = new String[3]; int idx = 0; - StringBuilder current = new StringBuilder(); - int parenthesesCount = 0; - - for (char c : expr.toCharArray()) { - if (c == '(') { - parenthesesCount++; - current.append(c); - } else if (c == ')') { - parenthesesCount--; - current.append(c); - if (parenthesesCount < 0) { - throw new IllegalArgumentException("Unmatched parentheses"); - } - } else if (c == ' ' && parenthesesCount == 0 && !current.isEmpty()) { - // Only split on space when not inside parentheses - if (idx >= 3) { - throw new IllegalArgumentException("Too many parts in expression"); - } - result[idx++] = current.toString(); - current = new StringBuilder(); - } else if (c != ' ' || parenthesesCount > 0) { - current.append(c); - } - } - - if (!current.isEmpty()) { - if (idx >= 3) { - throw new IllegalArgumentException("Too many parts in expression"); - } - result[idx] = current.toString(); - } + StringBuilder current = new StringBuilder(); + int parenthesesCount = 0; + + for (char c : expr.toCharArray()) { + if (c == '(') { + parenthesesCount++; + current.append(c); + } else if (c == ')') { + parenthesesCount--; + current.append(c); + if (parenthesesCount < 0) { + throw new IllegalArgumentException("Unmatched parentheses"); + } + } else if (c == ' ' && parenthesesCount == 0 && !current.isEmpty()) { + // Only split on space when not inside parentheses + if (idx >= 3) { + throw new IllegalArgumentException("Too many parts in expression"); + } + result[idx++] = current.toString(); + current = new StringBuilder(); + } else if (c != ' ' || parenthesesCount > 0) { + current.append(c); + } + } - // Must have exactly three parts - if (idx != 2 || result[0] == null || result[1] == null || result[2] == null) { - throw new IllegalArgumentException("Invalid expression format"); - } + if (!current.isEmpty()) { + if (idx >= 3) { + throw new IllegalArgumentException("Too many parts in expression"); + } + result[idx] = current.toString(); + } - // Validate "nil" tokens - if (!"nil".equals(result[1]) && !result[1].startsWith("(")) { - throw new IllegalArgumentException("Invalid left child format"); - } - if (!"nil".equals(result[2]) && !result[2].startsWith("(")) { - throw new IllegalArgumentException("Invalid right child format"); - } + // Must have exactly three parts + if (idx != 2 || result[0] == null || result[1] == null || result[2] == null) { + throw new IllegalArgumentException("Invalid expression format"); + } - return result; + // Validate "nil" tokens + if (!"nil".equals(result[1]) && !result[1].startsWith("(")) { + throw new IllegalArgumentException("Invalid left child format"); + } + if (!"nil".equals(result[2]) && !result[2].startsWith("(")) { + throw new IllegalArgumentException("Invalid right child format"); } + return result; + } } diff --git a/src/main/java/org/nintynine/problems/MathP40.java b/src/main/java/org/nintynine/problems/MathP40.java index b21b310..c76218a 100644 --- a/src/main/java/org/nintynine/problems/MathP40.java +++ b/src/main/java/org/nintynine/problems/MathP40.java @@ -4,149 +4,142 @@ import java.util.Optional; /** - * P40: Goldbach's conjecture implementation. - * Finds two prime numbers that sum up to a given even number. + * P40: Goldbach's conjecture implementation. Finds two prime numbers that sum up to a given even + * number. */ public class MathP40 { - /** - * Finds a pair of prime numbers that sum up to the given even number. - * Returns the first such pair found (typically with the smallest first prime). - * - * @param n the even number to decompose (must be > 2) - * @return Optional containing the Goldbach pair if found - * @throws IllegalArgumentException if n ≤ 2 or n is odd - */ - public static Optional goldbach(long n) { - if (n <= 2) { - throw new IllegalArgumentException("Number must be greater than 2"); - } - if (n % 2 != 0) { - throw new IllegalArgumentException("Number must be even"); - } - - BitSet sieve = sieveOfEratosthenes(n); - - for (long p = 2; p <= n / 2; p++) { - if (sieve.get((int) p)) { - long q = n - p; - if (q < n && sieve.get((int) q)) { - return Optional.of(new GoldbachPair(p, q)); - } - } - } - - return Optional.empty(); + /** + * Finds a pair of prime numbers that sum up to the given even number. Returns the first such pair + * found (typically with the smallest first prime). + * + * @param n the even number to decompose (must be > 2) + * @return Optional containing the Goldbach pair if found + * @throws IllegalArgumentException if n ≤ 2 or n is odd + */ + public static Optional goldbach(long n) { + if (n <= 2) { + throw new IllegalArgumentException("Number must be greater than 2"); + } + if (n % 2 != 0) { + throw new IllegalArgumentException("Number must be even"); } - /** - * Finds all pairs of prime numbers that sum up to the given even number. - * - * @param n the even number to decompose (must be > 2) - * @return array of GoldbachPairs, ordered by first prime - * @throws IllegalArgumentException if n ≤ 2 or n is odd - */ - public static GoldbachPair[] goldbachAll(long n) { - if (n <= 2) { - throw new IllegalArgumentException("Number must be greater than 2"); - } - if (n % 2 != 0) { - throw new IllegalArgumentException("Number must be even"); - } + BitSet sieve = sieveOfEratosthenes(n); - BitSet sieve = sieveOfEratosthenes(n); - int pairCount = 0; - for (long p = 2; p <= n / 2; p++) { - if (sieve.get((int) p) && sieve.get((int) (n - p))) { - pairCount++; - } + for (long p = 2; p <= n / 2; p++) { + if (sieve.get((int) p)) { + long q = n - p; + if (q < n && sieve.get((int) q)) { + return Optional.of(new GoldbachPair(p, q)); } + } + } - GoldbachPair[] pairs = new GoldbachPair[pairCount]; - int index = 0; - for (long p = 2; p <= n / 2; p++) { - if (sieve.get((int) p)) { - long q = n - p; - if (q < n && sieve.get((int) q)) { - pairs[index++] = new GoldbachPair(p, q); - } - } - } + return Optional.empty(); + } + + /** + * Finds all pairs of prime numbers that sum up to the given even number. + * + * @param n the even number to decompose (must be > 2) + * @return array of GoldbachPairs, ordered by first prime + * @throws IllegalArgumentException if n ≤ 2 or n is odd + */ + public static GoldbachPair[] goldbachAll(long n) { + if (n <= 2) { + throw new IllegalArgumentException("Number must be greater than 2"); + } + if (n % 2 != 0) { + throw new IllegalArgumentException("Number must be even"); + } - return pairs; + BitSet sieve = sieveOfEratosthenes(n); + int pairCount = 0; + for (long p = 2; p <= n / 2; p++) { + if (sieve.get((int) p) && sieve.get((int) (n - p))) { + pairCount++; + } } - /** - * Verifies Goldbach's conjecture for all even numbers up to n. - * - * @param n upper limit to check (must be > 2) - * @return true if conjecture holds for all even numbers in range - * @throws IllegalArgumentException if n ≤ 2 - */ - public static boolean verifyGoldbachUpTo(long n) { - if (n <= 2) { - throw new IllegalArgumentException("Number must be greater than 2"); + GoldbachPair[] pairs = new GoldbachPair[pairCount]; + int index = 0; + for (long p = 2; p <= n / 2; p++) { + if (sieve.get((int) p)) { + long q = n - p; + if (q < n && sieve.get((int) q)) { + pairs[index++] = new GoldbachPair(p, q); } + } + } - BitSet sieve = sieveOfEratosthenes(n); + return pairs; + } + + /** + * Verifies Goldbach's conjecture for all even numbers up to n. + * + * @param n upper limit to check (must be > 2) + * @return true if conjecture holds for all even numbers in range + * @throws IllegalArgumentException if n ≤ 2 + */ + public static boolean verifyGoldbachUpTo(long n) { + if (n <= 2) { + throw new IllegalArgumentException("Number must be greater than 2"); + } - for (long i = 4; i <= n; i += 2) { - boolean found = false; + BitSet sieve = sieveOfEratosthenes(n); - for (long p = 2; p <= i / 2; p++) { - if (sieve.get((int) p)) { - long q = i - p; - if (q < i && sieve.get((int) q)) { - found = true; - break; - } - } - } + for (long i = 4; i <= n; i += 2) { + boolean found = false; - if (!found) { - return false; - } + for (long p = 2; p <= i / 2; p++) { + if (sieve.get((int) p)) { + long q = i - p; + if (q < i && sieve.get((int) q)) { + found = true; + break; + } } + } - return true; + if (!found) { + return false; + } } - /** - * Generates prime number sieve up to n. - * Uses BitSet for efficient storage and lookup. - */ - private static BitSet sieveOfEratosthenes(long n) { - BitSet sieve = new BitSet((int) n + 1); - sieve.set(2, (int) n + 1); - - for (int i = 2; (long) i * i <= n; i++) { - if (sieve.get(i)) { - for (int j = i * i; j <= n; j += i) { - sieve.clear(j); - } - } - } + return true; + } + + /** Generates prime number sieve up to n. Uses BitSet for efficient storage and lookup. */ + private static BitSet sieveOfEratosthenes(long n) { + BitSet sieve = new BitSet((int) n + 1); + sieve.set(2, (int) n + 1); - return sieve; + for (int i = 2; (long) i * i <= n; i++) { + if (sieve.get(i)) { + for (int j = i * i; j <= n; j += i) { + sieve.clear(j); + } + } } + return sieve; + } + + /** Represents a pair of prime numbers that sum to a given even number. */ + public record GoldbachPair(long prime1, long prime2) { /** - * Represents a pair of prime numbers that sum to a given even number. + * Verifies that this is a valid Goldbach pair. + * + * @return true if both numbers are prime and sum to an even number */ - public record GoldbachPair(long prime1, long prime2) { - /** - * Verifies that this is a valid Goldbach pair. - * - * @return true if both numbers are prime and sum to an even number - */ - public boolean isValid() { - return MathP31.isPrime(prime1) && - MathP31.isPrime(prime2) && - (prime1 + prime2) % 2 == 0; - } + public boolean isValid() { + return MathP31.isPrime(prime1) && MathP31.isPrime(prime2) && (prime1 + prime2) % 2 == 0; + } - @Override - public String toString() { - return String.format("(%d %d)", prime1, prime2); - } + @Override + public String toString() { + return String.format("(%d %d)", prime1, prime2); } + } }