diff --git a/src/main/java/g3601_3700/s3673_find_zombie_sessions/readme.md b/src/main/java/g3601_3700/s3673_find_zombie_sessions/readme.md new file mode 100644 index 000000000..fabadfdb9 --- /dev/null +++ b/src/main/java/g3601_3700/s3673_find_zombie_sessions/readme.md @@ -0,0 +1,105 @@ +3673\. Find Zombie Sessions + +Hard + +Table: `app_events` + + +------------------+----------+ + | Column Name | Type | + +------------------+----------+ + | event_id | int | + | user_id | int | + | event_timestamp | datetime | + | event_type | varchar | + | session_id | varchar | + | event_value | int | + +------------------+----------+ + event_id is the unique identifier for this table. + event_type can be app_open, click, scroll, purchase, or app_close. + session_id groups events within the same user session. + event_value represents: for purchase - amount in dollars, for scroll - pixels scrolled, for others - NULL. + +Write a solution to identify **zombie sessions, **sessions where users appear active but show abnormal behavior patterns. A session is considered a **zombie session** if it meets ALL the following criteria: + +* The session duration is **more than** `30` minutes. +* Has **at least** `5` scroll events. +* The **click-to-scroll ratio** is less than `0.20` . +* **No purchases** were made during the session. + +Return _the result table ordered by_ `scroll_count` _in **descending** order, then by_ `session_id` _in **ascending** order_. + +The result format is in the following example. + +**Example:** + +**Input:** + +app\_events table: + + +----------+---------+---------------------+------------+------------+-------------+ + | event_id | user_id | event_timestamp | event_type | session_id | event_value | + +----------+---------+---------------------+------------+------------+-------------+ + | 1 | 201 | 2024-03-01 10:00:00 | app_open | S001 | NULL | + | 2 | 201 | 2024-03-01 10:05:00 | scroll | S001 | 500 | + | 3 | 201 | 2024-03-01 10:10:00 | scroll | S001 | 750 | + | 4 | 201 | 2024-03-01 10:15:00 | scroll | S001 | 600 | + | 5 | 201 | 2024-03-01 10:20:00 | scroll | S001 | 800 | + | 6 | 201 | 2024-03-01 10:25:00 | scroll | S001 | 550 | + | 7 | 201 | 2024-03-01 10:30:00 | scroll | S001 | 900 | + | 8 | 201 | 2024-03-01 10:35:00 | app_close | S001 | NULL | + | 9 | 202 | 2024-03-01 11:00:00 | app_open | S002 | NULL | + | 10 | 202 | 2024-03-01 11:02:00 | click | S002 | NULL | + | 11 | 202 | 2024-03-01 11:05:00 | scroll | S002 | 400 | + | 12 | 202 | 2024-03-01 11:08:00 | click | S002 | NULL | + | 13 | 202 | 2024-03-01 11:10:00 | scroll | S002 | 350 | + | 14 | 202 | 2024-03-01 11:15:00 | purchase | S002 | 50 | + | 15 | 202 | 2024-03-01 11:20:00 | app_close | S002 | NULL | + | 16 | 203 | 2024-03-01 12:00:00 | app_open | S003 | NULL | + | 17 | 203 | 2024-03-01 12:10:00 | scroll | S003 | 1000 | + | 18 | 203 | 2024-03-01 12:20:00 | scroll | S003 | 1200 | + | 19 | 203 | 2024-03-01 12:25:00 | click | S003 | NULL | + | 20 | 203 | 2024-03-01 12:30:00 | scroll | S003 | 800 | + | 21 | 203 | 2024-03-01 12:40:00 | scroll | S003 | 900 | + | 22 | 203 | 2024-03-01 12:50:00 | scroll | S003 | 1100 | + | 23 | 203 | 2024-03-01 13:00:00 | app_close | S003 | NULL | + | 24 | 204 | 2024-03-01 14:00:00 | app_open | S004 | NULL | + | 25 | 204 | 2024-03-01 14:05:00 | scroll | S004 | 600 | + | 26 | 204 | 2024-03-01 14:08:00 | scroll | S004 | 700 | + | 27 | 204 | 2024-03-01 14:10:00 | click | S004 | NULL | + | 28 | 204 | 2024-03-01 14:12:00 | app_close | S004 | NULL | + +----------+---------+---------------------+------------+------------+-------------+ + +**Output:** + + +------------+---------+--------------------------+--------------+ + | session_id | user_id | session_duration_minutes | scroll_count | + +------------+---------+--------------------------+--------------+ + | S001 | 201 | 35 | 6 | + +------------+---------+--------------------------+--------------+ + +**Explanation:** + +* **Session S001 (User 201)**: + * Duration: 10:00:00 to 10:35:00 = 35 minutes (more than 30) + * Scroll events: 6 (at least 5) + * Click events: 0 + * Click-to-scroll ratio: 0/6 = 0.00 (less than 0.20) + * Purchases: 0 (no purchases) + * S001 is a zombie session (meets all criteria) +* **Session S002 (User 202)**: + * Duration: 11:00:00 to 11:20:00 = 20 minutes (less than 30) + * Has a purchase event + * S002 is not a zombie session +* **Session S003 (User 203)**: + * Duration: 12:00:00 to 13:00:00 = 60 minutes (more than 30) + * Scroll events: 5 (at least 5) + * Click events: 1 + * Click-to-scroll ratio: 1/5 = 0.20 (not less than 0.20) + * Purchases: 0 (no purchases) + * S003 is not a zombie session (click-to-scroll ratio equals 0.20, needs to be less) +* **Session S004 (User 204)**: + * Duration: 14:00:00 to 14:12:00 = 12 minutes (less than 30) + * Scroll events: 2 (less than 5) + * S004 is not a zombie session + +The result table is ordered by scroll\_count in descending order, then by session\_id in ascending order. \ No newline at end of file diff --git a/src/main/java/g3601_3700/s3673_find_zombie_sessions/script.sql b/src/main/java/g3601_3700/s3673_find_zombie_sessions/script.sql new file mode 100644 index 000000000..87f371710 --- /dev/null +++ b/src/main/java/g3601_3700/s3673_find_zombie_sessions/script.sql @@ -0,0 +1,23 @@ +# Write your MySQL query statement below +# #Hard #Database #2025_09_07_Time_278_ms_(100.00%)_Space_0.0_MB_(100.00%) +SELECT + session_id, + user_id, + TIMESTAMPDIFF(MINUTE, MIN(event_timestamp), MAX(event_timestamp)) AS session_duration_minutes, + SUM(CASE WHEN event_type = 'scroll' THEN 1 ELSE 0 END) AS scroll_count -- NOSONAR +FROM + app_events +GROUP BY + session_id, + user_id +HAVING + TIMESTAMPDIFF(MINUTE, MIN(event_timestamp), MAX(event_timestamp)) > 30 + AND SUM(CASE WHEN event_type = 'scroll' THEN 1 ELSE 0 END) > 4 -- NOSONAR + AND ( + CAST(SUM(CASE WHEN event_type = 'click' THEN 1 ELSE 0 END) AS DOUBLE) / + NULLIF(SUM(CASE WHEN event_type = 'scroll' THEN 1 ELSE 0 END), 0) -- NOSONAR + ) < 0.2 + AND SUM(CASE WHEN event_type = 'purchase' THEN 1 ELSE 0 END) = 0 +ORDER BY + scroll_count DESC, + session_id ASC; diff --git a/src/main/java/g3601_3700/s3674_minimum_operations_to_equalize_array/Solution.java b/src/main/java/g3601_3700/s3674_minimum_operations_to_equalize_array/Solution.java new file mode 100644 index 000000000..a563dd98f --- /dev/null +++ b/src/main/java/g3601_3700/s3674_minimum_operations_to_equalize_array/Solution.java @@ -0,0 +1,14 @@ +package g3601_3700.s3674_minimum_operations_to_equalize_array; + +// #Easy #Weekly_Contest_466 #2025_09_07_Time_1_ms_(100.00%)_Space_43.98_MB_(100.00%) + +public class Solution { + public int minOperations(int[] nums) { + for (int num : nums) { + if (num != nums[0]) { + return 1; + } + } + return 0; + } +} diff --git a/src/main/java/g3601_3700/s3674_minimum_operations_to_equalize_array/readme.md b/src/main/java/g3601_3700/s3674_minimum_operations_to_equalize_array/readme.md new file mode 100644 index 000000000..ccdd19737 --- /dev/null +++ b/src/main/java/g3601_3700/s3674_minimum_operations_to_equalize_array/readme.md @@ -0,0 +1,36 @@ +3674\. Minimum Operations to Equalize Array + +Easy + +You are given an integer array `nums` of length `n`. + +In one operation, choose any subarray `nums[l...r]` (`0 <= l <= r < n`) and **replace** each element in that subarray with the **bitwise AND** of all elements. + +Return the **minimum** number of operations required to make all elements of `nums` equal. + +A **subarray** is a contiguous **non-empty** sequence of elements within an array. + +**Example 1:** + +**Input:** nums = [1,2] + +**Output:** 1 + +**Explanation:** + +Choose `nums[0...1]`: `(1 AND 2) = 0`, so the array becomes `[0, 0]` and all elements are equal in 1 operation. + +**Example 2:** + +**Input:** nums = [5,5,5] + +**Output:** 0 + +**Explanation:** + +`nums` is `[5, 5, 5]` which already has all elements equal, so 0 operations are required. + +**Constraints:** + +* `1 <= n == nums.length <= 100` +* 1 <= nums[i] <= 105 \ No newline at end of file diff --git a/src/main/java/g3601_3700/s3675_minimum_operations_to_transform_string/Solution.java b/src/main/java/g3601_3700/s3675_minimum_operations_to_transform_string/Solution.java new file mode 100644 index 000000000..dc48c84e7 --- /dev/null +++ b/src/main/java/g3601_3700/s3675_minimum_operations_to_transform_string/Solution.java @@ -0,0 +1,23 @@ +package g3601_3700.s3675_minimum_operations_to_transform_string; + +// #Medium #Weekly_Contest_466 #2025_09_14_Time_5_ms_(100.00%)_Space_47.93_MB_(95.06%) + +public class Solution { + public int minOperations(String s) { + int n = s.length(); + int ans = 0; + for (int i = 0; i < n; i++) { + final char c = s.charAt(i); + if (c != 'a') { + int ops = 'z' - c + 1; + if (ops > ans) { + ans = ops; + } + if (ops == 25) { + break; + } + } + } + return ans; + } +} diff --git a/src/main/java/g3601_3700/s3675_minimum_operations_to_transform_string/readme.md b/src/main/java/g3601_3700/s3675_minimum_operations_to_transform_string/readme.md new file mode 100644 index 000000000..7ce2dabe7 --- /dev/null +++ b/src/main/java/g3601_3700/s3675_minimum_operations_to_transform_string/readme.md @@ -0,0 +1,41 @@ +3675\. Minimum Operations to Transform String + +Medium + +You are given a string `s` consisting only of lowercase English letters. + +You can perform the following operation any number of times (including zero): + +* Choose any character `c` in the string and replace **every** occurrence of `c` with the **next** lowercase letter in the English alphabet. + + +Return the **minimum** number of operations required to transform `s` into a string consisting of **only** `'a'` characters. + +**Note:** Consider the alphabet as circular, thus `'a'` comes after `'z'`. + +**Example 1:** + +**Input:** s = "yz" + +**Output:** 2 + +**Explanation:** + +* Change `'y'` to `'z'` to get `"zz"`. +* Change `'z'` to `'a'` to get `"aa"`. +* Thus, the answer is 2. + +**Example 2:** + +**Input:** s = "a" + +**Output:** 0 + +**Explanation:** + +* The string `"a"` only consists of `'a'` characters. Thus, the answer is 0. + +**Constraints:** + +* 1 <= s.length <= 5 * 105 +* `s` consists only of lowercase English letters. \ No newline at end of file diff --git a/src/main/java/g3601_3700/s3676_count_bowl_subarrays/Solution.java b/src/main/java/g3601_3700/s3676_count_bowl_subarrays/Solution.java new file mode 100644 index 000000000..20ddace66 --- /dev/null +++ b/src/main/java/g3601_3700/s3676_count_bowl_subarrays/Solution.java @@ -0,0 +1,25 @@ +package g3601_3700.s3676_count_bowl_subarrays; + +// #Medium #Weekly_Contest_466 #2025_09_14_Time_2_ms_(100.00%)_Space_58.91_MB_(69.85%) + +public class Solution { + public long bowlSubarrays(int[] nums) { + int n = nums.length; + int res = n; + int pre = 0; + for (int a : nums) { + if (a > pre) { + res--; + pre = a; + } + } + pre = 0; + for (int i = n - 1; i >= 0; i--) { + if (nums[i] > pre) { + res--; + pre = nums[i]; + } + } + return res + 1L; + } +} diff --git a/src/main/java/g3601_3700/s3676_count_bowl_subarrays/readme.md b/src/main/java/g3601_3700/s3676_count_bowl_subarrays/readme.md new file mode 100644 index 000000000..99488aa3f --- /dev/null +++ b/src/main/java/g3601_3700/s3676_count_bowl_subarrays/readme.md @@ -0,0 +1,51 @@ +3676\. Count Bowl Subarrays + +Medium + +You are given an integer array `nums` with **distinct** elements. + +A subarray `nums[l...r]` of `nums` is called a **bowl** if: + +* The subarray has length at least 3. That is, `r - l + 1 >= 3`. +* The **minimum** of its two ends is **strictly greater** than the **maximum** of all elements in between. That is, `min(nums[l], nums[r]) > max(nums[l + 1], ..., nums[r - 1])`. + +Return the number of **bowl** subarrays in `nums`. + +**Example 1:** + +**Input:** nums = [2,5,3,1,4] + +**Output:** 2 + +**Explanation:** + +The bowl subarrays are `[3, 1, 4]` and `[5, 3, 1, 4]`. + +* `[3, 1, 4]` is a bowl because `min(3, 4) = 3 > max(1) = 1`. +* `[5, 3, 1, 4]` is a bowl because `min(5, 4) = 4 > max(3, 1) = 3`. + +**Example 2:** + +**Input:** nums = [5,1,2,3,4] + +**Output:** 3 + +**Explanation:** + +The bowl subarrays are `[5, 1, 2]`, `[5, 1, 2, 3]` and `[5, 1, 2, 3, 4]`. + +**Example 3:** + +**Input:** nums = [1000000000,999999999,999999998] + +**Output:** 0 + +**Explanation:** + +No subarray is a bowl. + +**Constraints:** + +* 3 <= nums.length <= 105 +* 1 <= nums[i] <= 109 +* `nums` consists of distinct elements. \ No newline at end of file diff --git a/src/main/java/g3601_3700/s3677_count_binary_palindromic_numbers/Solution.java b/src/main/java/g3601_3700/s3677_count_binary_palindromic_numbers/Solution.java new file mode 100644 index 000000000..e95f26586 --- /dev/null +++ b/src/main/java/g3601_3700/s3677_count_binary_palindromic_numbers/Solution.java @@ -0,0 +1,37 @@ +package g3601_3700.s3677_count_binary_palindromic_numbers; + +// #Hard #Weekly_Contest_466 #2025_09_07_Time_1_ms_(100.00%)_Space_40.86_MB_(100.00%) + +public class Solution { + private long makePalin(long left, boolean odd) { + long ans = left; + if (odd) { + left = left >> 1; + } + while (left > 0) { + ans = (ans << 1) | (left & 1); + left = left >> 1; + } + return ans; + } + + public int countBinaryPalindromes(long n) { + if (n == 0) { + return 1; + } + int len = 64 - Long.numberOfLeadingZeros(n); + long count = 1; + for (int i = 1; i < len; i++) { + int half = (i + 1) / 2; + count += 1L << (half - 1); + } + int half = (len + 1) / 2; + long prefix = n >> (len - half); + long palin = makePalin(prefix, len % 2 == 1); + count += (prefix - (1L << (half - 1))); + if (palin <= n) { + ++count; + } + return (int) count; + } +} diff --git a/src/main/java/g3601_3700/s3677_count_binary_palindromic_numbers/readme.md b/src/main/java/g3601_3700/s3677_count_binary_palindromic_numbers/readme.md new file mode 100644 index 000000000..5966abe4e --- /dev/null +++ b/src/main/java/g3601_3700/s3677_count_binary_palindromic_numbers/readme.md @@ -0,0 +1,44 @@ +3677\. Count Binary Palindromic Numbers + +Hard + +You are given a **non-negative** integer `n`. + +A **non-negative** integer is called **binary-palindromic** if its binary representation (written without leading zeros) reads the same forward and backward. + +Return the number of integers `k` such that `0 <= k <= n` and the binary representation of `k` is a palindrome. + +**Note:** The number 0 is considered binary-palindromic, and its representation is `"0"`. + +**Example 1:** + +**Input:** n = 9 + +**Output:** 6 + +**Explanation:** + +The integers `k` in the range `[0, 9]` whose binary representations are palindromes are: + +* `0 → "0"` +* `1 → "1"` +* `3 → "11"` +* `5 → "101"` +* `7 → "111"` +* `9 → "1001"` + +All other values in `[0, 9]` have non-palindromic binary forms. Therefore, the count is 6. + +**Example 2:** + +**Input:** n = 0 + +**Output:** 1 + +**Explanation:** + +Since `"0"` is a palindrome, the count is 1. + +**Constraints:** + +* 0 <= n <= 1015 \ No newline at end of file diff --git a/src/test/java/g3601_3700/s3673_find_zombie_sessions/MysqlTest.java b/src/test/java/g3601_3700/s3673_find_zombie_sessions/MysqlTest.java new file mode 100644 index 000000000..65f5ed694 --- /dev/null +++ b/src/test/java/g3601_3700/s3673_find_zombie_sessions/MysqlTest.java @@ -0,0 +1,86 @@ +package g3601_3700.s3673_find_zombie_sessions; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.stream.Collectors; +import javax.sql.DataSource; +import org.junit.jupiter.api.Test; +import org.zapodot.junit.db.annotations.EmbeddedDatabase; +import org.zapodot.junit.db.annotations.EmbeddedDatabaseTest; +import org.zapodot.junit.db.common.CompatibilityMode; + +@EmbeddedDatabaseTest( + compatibilityMode = CompatibilityMode.MySQL, + initialSqls = + "CREATE TABLE app_events (" + + " event_id INT PRIMARY KEY," + + " user_id INT NOT NULL," + + " event_timestamp TIMESTAMP NOT NULL," + + " event_type VARCHAR(50) NOT NULL," + + " session_id VARCHAR(50) NOT NULL," + + " event_value INT" + + ");" + + "INSERT INTO app_events (event_id, user_id, event_timestamp, " + + "event_type, session_id, event_value) VALUES" + + "(1, 201, '2024-03-01 10:00:00', 'app_open', 'S001', NULL)," + + "(2, 201, '2024-03-01 10:05:00', 'scroll', 'S001', 500)," + + "(3, 201, '2024-03-01 10:10:00', 'scroll', 'S001', 750)," + + "(4, 201, '2024-03-01 10:15:00', 'scroll', 'S001', 600)," + + "(5, 201, '2024-03-01 10:20:00', 'scroll', 'S001', 800)," + + "(6, 201, '2024-03-01 10:25:00', 'scroll', 'S001', 550)," + + "(7, 201, '2024-03-01 10:30:00', 'scroll', 'S001', 900)," + + "(8, 201, '2024-03-01 10:35:00', 'app_close', 'S001', NULL)," + + "(9, 202, '2024-03-01 11:00:00', 'app_open', 'S002', NULL)," + + "(10, 202, '2024-03-01 11:02:00', 'click', 'S002', NULL)," + + "(11, 202, '2024-03-01 11:05:00', 'scroll', 'S002', 400)," + + "(12, 202, '2024-03-01 11:08:00', 'click', 'S002', NULL)," + + "(13, 202, '2024-03-01 11:10:00', 'scroll', 'S002', 350)," + + "(14, 202, '2024-03-01 11:15:00', 'purchase', 'S002', 50)," + + "(15, 202, '2024-03-01 11:20:00', 'app_close','S002', NULL)," + + "(16, 203, '2024-03-01 12:00:00', 'app_open', 'S003', NULL)," + + "(17, 203, '2024-03-01 12:10:00', 'scroll', 'S003', 1000)," + + "(18, 203, '2024-03-01 12:20:00', 'scroll', 'S003', 1200)," + + "(19, 203, '2024-03-01 12:25:00', 'click', 'S003', NULL)," + + "(20, 203, '2024-03-01 12:30:00', 'scroll', 'S003', 800)," + + "(21, 203, '2024-03-01 12:40:00', 'scroll', 'S003', 900)," + + "(22, 203, '2024-03-01 12:50:00', 'scroll', 'S003', 1100)," + + "(23, 203, '2024-03-01 13:00:00', 'app_close','S003', NULL)," + + "(24, 204, '2024-03-01 14:00:00', 'app_open', 'S004', NULL)," + + "(25, 204, '2024-03-01 14:05:00', 'scroll', 'S004', 600)," + + "(26, 204, '2024-03-01 14:08:00', 'scroll', 'S004', 700)," + + "(27, 204, '2024-03-01 14:10:00', 'click', 'S004', NULL)," + + "(28, 204, '2024-03-01 14:12:00', 'app_close','S004', NULL);") +class MysqlTest { + @Test + void testScript(@EmbeddedDatabase DataSource dataSource) + throws SQLException, FileNotFoundException { + try (final Connection connection = dataSource.getConnection()) { + try (final Statement statement = connection.createStatement(); + final ResultSet resultSet = + statement.executeQuery( + new BufferedReader( + new FileReader( + "src/main/java/g3601_3700/" + + "s3673_find_zombie_sessions/" + + "script.sql")) + .lines() + .collect(Collectors.joining("\n")) + .replaceAll("#.*?\\r?\\n", ""))) { + assertThat(resultSet.next(), equalTo(true)); + assertThat(resultSet.getNString(1), equalTo("S001")); + assertThat(resultSet.getNString(2), equalTo("201")); + assertThat(resultSet.getNString(3), equalTo("35")); + assertThat(resultSet.getNString(4), equalTo("6")); + assertThat(resultSet.next(), equalTo(false)); + } + } + } +} diff --git a/src/test/java/g3601_3700/s3674_minimum_operations_to_equalize_array/SolutionTest.java b/src/test/java/g3601_3700/s3674_minimum_operations_to_equalize_array/SolutionTest.java new file mode 100644 index 000000000..ea27151c7 --- /dev/null +++ b/src/test/java/g3601_3700/s3674_minimum_operations_to_equalize_array/SolutionTest.java @@ -0,0 +1,18 @@ +package g3601_3700.s3674_minimum_operations_to_equalize_array; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void minOperations() { + assertThat(new Solution().minOperations(new int[] {1, 2}), equalTo(1)); + } + + @Test + void minOperations2() { + assertThat(new Solution().minOperations(new int[] {5, 5, 5}), equalTo(0)); + } +} diff --git a/src/test/java/g3601_3700/s3675_minimum_operations_to_transform_string/SolutionTest.java b/src/test/java/g3601_3700/s3675_minimum_operations_to_transform_string/SolutionTest.java new file mode 100644 index 000000000..3f58950ef --- /dev/null +++ b/src/test/java/g3601_3700/s3675_minimum_operations_to_transform_string/SolutionTest.java @@ -0,0 +1,18 @@ +package g3601_3700.s3675_minimum_operations_to_transform_string; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void minOperations() { + assertThat(new Solution().minOperations("yz"), equalTo(2)); + } + + @Test + void minOperations2() { + assertThat(new Solution().minOperations("a"), equalTo(0)); + } +} diff --git a/src/test/java/g3601_3700/s3676_count_bowl_subarrays/SolutionTest.java b/src/test/java/g3601_3700/s3676_count_bowl_subarrays/SolutionTest.java new file mode 100644 index 000000000..1cf9838fd --- /dev/null +++ b/src/test/java/g3601_3700/s3676_count_bowl_subarrays/SolutionTest.java @@ -0,0 +1,25 @@ +package g3601_3700.s3676_count_bowl_subarrays; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void bowlSubarrays() { + assertThat(new Solution().bowlSubarrays(new int[] {2, 5, 3, 1, 4}), equalTo(2L)); + } + + @Test + void bowlSubarrays2() { + assertThat(new Solution().bowlSubarrays(new int[] {5, 1, 2, 3, 4}), equalTo(3L)); + } + + @Test + void bowlSubarrays3() { + assertThat( + new Solution().bowlSubarrays(new int[] {1000000000, 999999999, 999999998}), + equalTo(0L)); + } +} diff --git a/src/test/java/g3601_3700/s3677_count_binary_palindromic_numbers/SolutionTest.java b/src/test/java/g3601_3700/s3677_count_binary_palindromic_numbers/SolutionTest.java new file mode 100644 index 000000000..c1f99d111 --- /dev/null +++ b/src/test/java/g3601_3700/s3677_count_binary_palindromic_numbers/SolutionTest.java @@ -0,0 +1,59 @@ +package g3601_3700.s3677_count_binary_palindromic_numbers; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void countBinaryPalindromes() { + assertThat(new Solution().countBinaryPalindromes(9L), equalTo(6)); + } + + @Test + void countBinaryPalindromes2() { + assertThat(new Solution().countBinaryPalindromes(9L), equalTo(6)); + } + + @Test + void countBinaryPalindromes3() { + // Branch: n == 0 → returns 1 immediately + assertThat(new Solution().countBinaryPalindromes(0), equalTo(1)); + } + + @Test + void countBinaryPalindromes4() { + // n = 1 ("1") → palindrome + // Expected palindromes: 1 (0) + 1 (1) = 2 + assertThat(new Solution().countBinaryPalindromes(1), equalTo(2)); + } + + @Test + void countBinaryPalindromes5() { + // n = 6 ("110"), length = 3 (odd) + // Palindromes up to 6: 0,1,3,5 + assertThat(new Solution().countBinaryPalindromes(6), equalTo(4)); + } + + @Test + void countBinaryPalindromes6() { + // n = 9 ("1001"), palindrome itself + // Palindromes up to 9: 0,1,3,5,7,9 + assertThat(new Solution().countBinaryPalindromes(9), equalTo(6)); + } + + @Test + void countBinaryPalindromes7() { + // n = 10 ("1010") → next palindrome = 9 (smaller) → branch where palin <= n + // Palindromes up to 10: 0,1,3,5,7,9 + assertThat(new Solution().countBinaryPalindromes(10), equalTo(6)); + } + + @Test + void countBinaryPalindromes8() { + // 1023 = "1111111111" + long n = (1L << 10) - 1; + assertThat(new Solution().countBinaryPalindromes(n), equalTo(63)); + } +}