-
Notifications
You must be signed in to change notification settings - Fork 2
feat(math): power of three #200
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| # Power of I | ||
|
|
||
| iii is the imaginary unit, it is defined by i²=−1i² = -1i²=−1, therefore it is a solution to x²+1=0x² + 1 = 0x²+1=0. | ||
| i is the imaginary unit, defined by i² = −1; thus it is a solution to x² + 1 = 0. | ||
|
|
||
| Your Task Complete the function pofi that returns iii to the power of a given non-negative integer in its simplest form, | ||
| as a string (answer may contain iii). | ||
| Your Task Complete the function pofi that returns i to the power of a given non-negative integer in its simplest form, | ||
| as a string (answer may contain i). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,135 @@ | ||
| # Power Of Three | ||
|
|
||
| Given an integer n, return `true` if it is a power of three. Otherwise, return `false`. | ||
|
|
||
| An integer n is a power of three, if there exists an integer x such that `n == 3^x`. | ||
|
|
||
| ## Examples | ||
|
|
||
| Example 1: | ||
|
|
||
| ```text | ||
| Input: n = 27 | ||
| Output: true | ||
| Explanation: 27 = 33 | ||
| ``` | ||
|
|
||
| Example 2: | ||
| ```text | ||
| Input: n = 0 | ||
| Output: false | ||
| Explanation: There is no x where 3x = 0.` | ||
| ``` | ||
|
|
||
| Example 3: | ||
| ```text | ||
| Input: n = -1 | ||
| Output: false | ||
| Explanation: There is no x where 3x = (-1). | ||
| ``` | ||
|
|
||
| ## Constraints | ||
|
|
||
| - -2^31 <= n <= 2^31 - 1 | ||
|
|
||
| ## Topics | ||
|
|
||
| - Math | ||
| - Recursion | ||
|
|
||
| ## Solution | ||
|
|
||
| ### Using Modulo | ||
|
|
||
| The key insight is that since 3 is a prime number, any power of 3 will only have 3 as its prime factor. The largest power | ||
| of 3 that fits within a 32-bit signed integer range is `3^19 = 1162261467`. If `n` is a power of 3, then n must be a | ||
| divisor of `1162261467`. Because 3 is prime, the only divisors of 3^19 are 3^0, 3^1, 3^2,...3^19, which are exactly all | ||
| the powers of 3 in range. Therefore, we simply check whether n is positive and whether `1162261467` is evenly divisible | ||
| by `n`. This approach requires no loops or recursion. | ||
|
|
||
| Now, let’s look at the solution steps below: | ||
|
|
||
| 1. Check if n is greater than 0. Any power of 3 must be a positive integer, so if n is 0 or negative, return false | ||
| immediately. | ||
| 2. Compute 1162261467 % n, where 1162261467 is 3^19, the largest power of three within the 32-bit signed integer range. | ||
| - If the remainder equals 0, then n is a divisor of 3^19, meaning n is itself a power of 3. Return true. | ||
| - If the remainder is not 0, then n is not a power of 3. Return false. | ||
|
|
||
| #### Time Complexity | ||
|
|
||
| The time complexity of the solution is O(1) because we perform a single comparison and a single modulo operation, both | ||
| of which take constant time regardless of the input. | ||
|
|
||
| #### Space Complexity | ||
|
|
||
| The space complexity of the solution is O(1) because we use only a fixed amount of space (no additional data structures) | ||
| and the constant 1162261467 is stored as a single integer. | ||
|
|
||
| ### Using Loops | ||
|
|
||
| To check if a number is a power of three, we need to think about what it means mathematically. If n = 3^x, then we can | ||
| keep dividing n by 3 exactly x times until we reach 1. This is the key insight. | ||
|
|
||
| Think of it like peeling layers off an onion. If we have 27 = 3^3, we can divide by 3 three times: 27 ÷ 3 = 9, then | ||
| 9 ÷ 3 = 3, then 3 ÷ 3 = 1. We end up with exactly 1, confirming that 27 is indeed a power of three. | ||
|
|
||
| On the other hand, if we try this with a non-power like 45: 45 ÷ 3 = 15, then 15 ÷ 3 = 5. Now 5 is not divisible by 3 | ||
| (it gives remainder 2), so we know 45 cannot be a power of three. | ||
|
|
||
| The pattern becomes clear: a power of three should be repeatedly divisible by 3 until we reach 1, with no remainders | ||
| along the way. If at any point during our division we get a remainder (checked using n % 3), we immediately know the | ||
| number isn't a power of three. | ||
|
|
||
| The algorithm naturally emerges from this observation: keep dividing by 3 while checking for remainders. If we | ||
| successfully reduce the number to 1 through repeated division by 3, it's a power of three. If we encounter a remainder | ||
| or end up with a number other than 1, it's not. | ||
|
|
||
| The solution implements the trial division method to determine if a number is a power of three. Let's walk through the | ||
| implementation step by step: | ||
|
|
||
| - Main Loop Condition: The algorithm starts with a while loop that continues as long as n > 2. This is because the | ||
| smallest power of three greater than 2 is 3^1 = 3. Any power of three will be at least 3, so we can stop when n | ||
| becomes 2 or less. | ||
| - Divisibility Check: Inside the loop, we check if n % 3 is non-zero. The modulo operation n % 3 returns the remainder | ||
| when n is divided by 3. If there's any remainder (meaning n % 3 evaluates to true), then n is not perfectly divisible | ||
| by 3, which means it cannot be a power of three. We immediately return False. | ||
| - Division Step: If n is divisible by 3 (passes the modulo check), we perform integer division: n //= 3. This reduces n | ||
| by a factor of 3 and continues the process. The integer division operator // ensures we're working with whole numbers | ||
| throughout. | ||
| - Final Check: After the loop exits (when n <= 2), we check if n == 1. If we've successfully divided a power of three by | ||
| 3 repeatedly, we should end up with exactly 1. For example: | ||
| - 27 → 9 → 3 → 1 (returns True) | ||
| - 18 → 6 → 2 (returns False since 2 ≠ 1) | ||
|
|
||
| #### Time Complexity | ||
|
|
||
| The algorithm uses a while loop that repeatedly divides n by 3 until n becomes less than or equal to 2. In each iteration, | ||
| we perform: | ||
|
|
||
| - A modulo operation n % 3 to check divisibility | ||
| - An integer division n //= 3 to reduce n | ||
|
|
||
| The number of iterations is determined by how many times we can divide n by 3 before it becomes less than or equal to 2. | ||
| This is equivalent to finding the largest integer k such that 3^k ≤ n, which gives us k ≤ log₃n. Therefore, the loop | ||
| runs at most ⌊log₃n⌋ times, resulting in a time complexity of O(log₃n). | ||
|
|
||
| #### Space Complexity | ||
|
|
||
| The algorithm only uses a constant amount of extra space: | ||
|
|
||
| - The input variable n is modified in place | ||
| - No additional data structures are created | ||
| - The space used does not depend on the size of the input | ||
|
|
||
| Therefore, the space complexity is O(1). | ||
|
|
||
| ### Using Logarithms | ||
|
|
||
| A common loop-free math check (for positive integers n): | ||
|
|
||
| - Compute x = log₃n = ln(n)/ln(3) | ||
| - Check whether x is an integer: x ≈ k for some integer k (e.g., ∣x−round(x)∣<ε like 10^−10) | ||
| - If yes, then n = 3^k; otherwise it isn’t. | ||
|
|
||
| Alternative integer-only (no loops) via factorization: compute whether n has any prime factors other than 3, and whether | ||
| the exponent of 3 is ≥ 0; but that typically requires some factoring method. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| from math import log | ||
|
|
||
|
|
||
| def is_power_of_three_with_log(n: int) -> bool: | ||
| if n < 1: | ||
| return False | ||
|
|
||
| k = log(n, 3) | ||
| k_round = int(round(k)) | ||
| return 3**k_round == n | ||
|
|
||
|
|
||
| def is_power_of_three_with_mod(n: int) -> bool: | ||
| # The largest power of 3 within 32-bit signed integer range is 3^19 = 1162261467 | ||
| # If n is a power of 3, then 1162261467 % n must equal 0 | ||
| # We also need n to be positive since negative numbers and zero can't be powers of 3 | ||
| return n > 0 and 1162261467 % n == 0 | ||
|
|
||
|
|
||
| def is_power_of_three_with_loop(n: int) -> bool: | ||
| # Keep dividing by 3 while n is greater than 2 | ||
| while n > 2: | ||
| # If n is not divisible by 3, it's not a power of 3 | ||
| if n % 3 != 0: | ||
| return False | ||
| # Divide n by 3 using integer division | ||
| n //= 3 | ||
|
|
||
| # After the loop, n should be 1 if it was a power of 3 | ||
| # (since 3^0 = 1) | ||
| return n == 1 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| import unittest | ||
| from parameterized import parameterized | ||
| from utils.test_utils import custom_test_name_func | ||
| from pymath.power_of_three import ( | ||
| is_power_of_three_with_log, | ||
| is_power_of_three_with_mod, | ||
| is_power_of_three_with_loop, | ||
| ) | ||
|
|
||
| POWER_OF_THREE_TEST_CASES = [ | ||
| (27, True), | ||
| (0, False), | ||
| (-1, False), | ||
| (9, True), | ||
| (11, False), | ||
| (45, False), | ||
| (243, True), | ||
| (10, False), | ||
| ] | ||
|
|
||
|
|
||
| class PowerOfThreeTestCases(unittest.TestCase): | ||
| @parameterized.expand(POWER_OF_THREE_TEST_CASES, name_func=custom_test_name_func) | ||
| def test_power_of_three_using_logs(self, n: int, expected: bool): | ||
| actual = is_power_of_three_with_log(n) | ||
| self.assertEqual(expected, actual) | ||
|
|
||
| @parameterized.expand(POWER_OF_THREE_TEST_CASES, name_func=custom_test_name_func) | ||
| def test_power_of_three_using_mod(self, n: int, expected: bool): | ||
| actual = is_power_of_three_with_mod(n) | ||
| self.assertEqual(expected, actual) | ||
|
|
||
| @parameterized.expand(POWER_OF_THREE_TEST_CASES, name_func=custom_test_name_func) | ||
| def test_power_of_three_using_loop(self, n: int, expected: bool): | ||
| actual = is_power_of_three_with_loop(n) | ||
| self.assertEqual(expected, actual) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| unittest.main() |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix mathematical notation and punctuation in the examples.
Line 14 (
27 = 33) and Lines 21/28 (3x) should use exponent notation (e.g.,3^3,3^x), and Line 21 has a stray trailing backtick.Also applies to: 21-21, 28-28
🤖 Prompt for AI Agents