From 0e6f0480d17473014f21860d854dc69410e14992 Mon Sep 17 00:00:00 2001 From: 2025mohseni Date: Thu, 4 Jun 2026 12:33:00 +0330 Subject: [PATCH] All tests passing --- src/main/java/BonusExercises.java | 100 +++++++++----------- src/main/java/MainExercises.java | 150 ++++++++++++------------------ 2 files changed, 107 insertions(+), 143 deletions(-) diff --git a/src/main/java/BonusExercises.java b/src/main/java/BonusExercises.java index d02a746..3c18452 100644 --- a/src/main/java/BonusExercises.java +++ b/src/main/java/BonusExercises.java @@ -5,72 +5,64 @@ import java.util.regex.Pattern; public class BonusExercises { - /* - complete the method below, so it will validate an email address - 1. Must have exactly one @ (no more, no less) - 2. Split into local-part and domain (before @ and after @) - 3. Local-part rules: - - Can't be empty - - Can't start or end with dot - - Can't have two dots in a row - 4. Domain rules: - - Can't be empty - - Can't start or end with hyphen - - Can't have underscores - - Each segment (between dots) must follow same hyphen rules - */ public boolean validateEmail(String email) { - String regex = ""; // todo - Pattern pattern = Pattern.compile(regex); - Matcher matcher = pattern.matcher(email); - - return matcher.matches(); + if (email == null) return false; + // بررسی قوانین ایمیل: یک @، عدم شروع/پایان با دات، عدم دات متوالی + String regex = "^[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?$"; + return email.matches(regex); } - /* - This method should find and return the first date in a string. - - Supported formats: - - American: MM/DD/YYYY (e.g., 12/09/2023) - - British: DD/MM/YYYY (e.g., 12/09/2023 — same pattern, context matters) - - ISO: YYYY-MM-DD (e.g., 2024-07-15) - - Slash variant: YYYY/MM/DD (e.g., 2025/01/01) - - If no match for a date is found in the string, return null. - */ public String findDate(String string) { - // todo - return null; + if (string == null) return null; + // بررسی تاریخ با فیلتر ماه‌ها و روزهای نامعتبر + String regex = "\\b(0[1-9]|[12]\\d|3[01])/(0[1-9]|1[0-2])/\\d{4}\\b|\\b(0[1-9]|1[0-2])/(0[1-9]|[12]\\d|3[01])/\\d{4}\\b|\\b\\d{4}[-/](0[1-9]|1[0-2])[-/](0[1-9]|[12]\\d|3[01])\\b"; + Matcher matcher = Pattern.compile(regex).matcher(string); + return matcher.find() ? matcher.group() : null; } - /* - given a string, implement the method to detect all valid passwords - then, it should return the count of them - - a valid password has the following properties: - - at least 8 characters - - has to include at least one uppercase letter, and at least a lowercase - - at least one number and at least a special char "!@#$%^&*" - - has no white-space in it - */ public int findValidPasswords(String string) { - // todo - return -1; + if (string == null || string.isEmpty()) return 0; + + int count = 0; + // تغییر استراتژی: به جای split با فضا، کلماتی را پیدا می‌کنیم که کاراکترهای مجاز دارند + // این ریجکس کلماتی را پیدا می‌کند که حداقل ۸ کاراکترند و فاصله ندارند + Pattern wordPattern = Pattern.compile("\\S{8,}"); + Matcher wordMatcher = wordPattern.matcher(string); + + // ریجکسِ سخت‌گیرانه برای تایید شرط‌های پسورد (حرف بزرگ، کوچک، عدد، کاراکتر خاص) + String passwordRegex = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[!@#$%^&*]).*$"; + Pattern validator = Pattern.compile(passwordRegex); + + while (wordMatcher.find()) { + String token = wordMatcher.group(); + // حالا علائم نگارشی اطراف را حذف می‌کنیم + String cleanToken = token.replaceAll("^[^a-zA-Z0-9!@#$%^&*]+|[^a-zA-Z0-9!@#$%^&*]+$", ""); + + // چک می‌کنیم آیا پس از تمیزکاری هنوز حداقل ۸ کاراکتر است و شرط‌های پیچیده را دارد + if (cleanToken.length() >= 8 && validator.matcher(cleanToken).matches()) { + count++; + } + } + + return count; } - /* - you should return a list of *words* which are palindromic - by word we mean at least 3 letters with no whitespace in it - - note: your implementation should be case-insensitive, e.g. Aba -> is palindrome - */ public List findPalindromes(String string) { List list = new ArrayList<>(); - // todo + if (string == null || string.isEmpty()) return list; + String[] words = string.split("[^a-zA-Z0-9]+"); + for (String word : words) { + if (word.length() >= 3 && isPalindrome(word)) list.add(word); + } return list; } - public static void main(String[] args) { - // you can test your code here + private boolean isPalindrome(String word) { + String clean = word.toLowerCase(); + int left = 0, right = clean.length() - 1; + while (left < right) { + if (clean.charAt(left++) != clean.charAt(right--)) return false; + } + return true; } -} +} \ No newline at end of file diff --git a/src/main/java/MainExercises.java b/src/main/java/MainExercises.java index 21581ea..48ac807 100644 --- a/src/main/java/MainExercises.java +++ b/src/main/java/MainExercises.java @@ -1,103 +1,75 @@ -public class MainExercises -{ - /* - you should create a triangle with "*" and return a two-dimensional array of characters based on that - the triangle's area is empty, which means some characters should be " " +import java.util.*; - example 1, input = 3: - * - ** - *** +public class MainExercises { - example 2, input = 5: - * - ** - * * - * * - ***** - - the output has to be a two-dimensional array of characters, so don't just print the triangle! - */ + // اصلاح متد برای ایجاد مثلث به صورت آرایه دو بعدی Jagged public char[][] generateTriangle(int n) { - - // todo - return null; - + char[][] triangle = new char[n][]; + for (int i = 0; i < n; i++) { + triangle[i] = new char[i + 1]; + for (int j = 0; j <= i; j++) { + // شرط قرارگیری ستاره: ستون اول، ستون آخر یا ردیف آخر + if (j == 0 || j == i || i == n - 1) { + triangle[i][j] = '*'; + } else { + triangle[i][j] = ' '; + } + } + } + return triangle; } - - - /* - SPIRAL TRAVERSAL OF A RECTANGULAR MATRIX - - Given a rectangular matrix (2D array) of integers, this method traverses - it in a spiral order (clockwise from outside to inside) and returns - the elements as a 1D array. - - EXAMPLE: - Input matrix: - 1 2 3 - 4 5 6 - 7 8 9 - - Spiral order: start at top-left (1), go right →, then down ↓, - then left ←, then up ↑, then repeat inward. - - Result: {1, 2, 3, 6, 9, 8, 7, 4, 5} - - so you should walk in that matrix in a curl and then add the numbers in order you've seen them in a 1D array - - RECTANGULAR MATRIX ASSUMPTION: - This method assumes the input matrix is RECTANGULAR (all rows have - the same number of columns). In Java, we can verify this because - 2D arrays might be jagged (rows of different lengths). - - IMPORTANT: In Java, we do NOT need to pass rows and cols! - The 2D array 'matrix' knows its own dimensions: - - Number of rows: matrix.length - - Number of columns: matrix[0].length (if rectangular) - */ + // متد پیمایش مارپیچی ماتریس public int[] spiralTraversal(int[][] matrix) { - // todo - return null; + if (matrix == null || matrix.length == 0) return new int[0]; + int rows = matrix.length; + int cols = matrix[0].length; + int[] result = new int[rows * cols]; + int top = 0, bottom = rows - 1, left = 0, right = cols - 1; + int index = 0; + + while (top <= bottom && left <= right) { + for (int i = left; i <= right; i++) result[index++] = matrix[top][i]; + top++; + for (int i = top; i <= bottom; i++) result[index++] = matrix[i][right]; + right--; + if (top <= bottom) { + for (int i = right; i >= left; i--) result[index++] = matrix[bottom][i]; + bottom--; + } + if (left <= right) { + for (int i = bottom; i >= top; i--) result[index++] = matrix[i][left]; + left++; + } + } + return result; } - /* - integer partitioning is a combinatorics problem in discreet maths - the problem is to generate sum numbers which their summation is the input number - - e.g. 1 -> all partitions of integer 3 are: - 3 - 2, 1 - 1, 1, 1 - - e.g. 2 -> for number 4 goes as: - 4 - 3, 1 - 2, 2 - 2, 1, 1 - 1, 1, 1, 1 - - Note: As you can see in the examples, we want to generate distinct partitions, - which means 1,2 and 2,1 are not different — they count as the same combination. - - You should generate all partitions of the input number. - - Hint: You can determine the size and order of the arrays by finding the pattern - of partitions and their count. Trust me, this one's fun and easy :) - - If you're familiar with Lists and ArrayLists, you can also edit the method's - body to use them instead of arrays. - */ - + // متد افراز عدد (Integer Partitioning) public int[][] intPartitions(int n) { - // todo - return null; + List> results = new ArrayList<>(); + generatePartitions(n, n, new ArrayList<>(), results); + + int[][] res = new int[results.size()][]; + for (int i = 0; i < results.size(); i++) { + res[i] = results.get(i).stream().mapToInt(Integer::intValue).toArray(); + } + return res; } + private void generatePartitions(int target, int max, List current, List> results) { + if (target == 0) { + results.add(new ArrayList<>(current)); + return; + } + for (int i = Math.min(target, max); i >= 1; i--) { + current.add(i); + generatePartitions(target - i, i, current, results); + current.remove(current.size() - 1); + } + } - public static void main() - { - + public static void main(String[] args) { + // تست دستی در صورت نیاز } } \ No newline at end of file -- 2.54.0