Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -1061,6 +1061,8 @@
* [Test Perfect Squares](https://github.com/BrianLusina/PythonSnips/blob/master/pymath/perfect_square/test_perfect_squares.py)
* Power Of I
* [Test Power Of I](https://github.com/BrianLusina/PythonSnips/blob/master/pymath/power_of_i/test_power_of_i.py)
* Power Of Three
* [Test Power Of Three](https://github.com/BrianLusina/PythonSnips/blob/master/pymath/power_of_three/test_power_of_three.py)
* Power Of Two
* [Test Power Of Two](https://github.com/BrianLusina/PythonSnips/blob/master/pymath/power_of_two/test_power_of_two.py)
* Rectangle Area
Expand Down
6 changes: 3 additions & 3 deletions pymath/power_of_i/README.md
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).
135 changes: 135 additions & 0 deletions pymath/power_of_three/README.md
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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

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
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pymath/power_of_three/README.md` at line 14, The mathematical expressions in
the README.md file use incorrect notation for exponents. Replace `33` with `3^3`
on line 14 to properly show three raised to the power of three. Replace `3x`
with `3^x` on lines 21 and 28 to use correct exponent notation throughout.
Additionally, remove the stray trailing backtick on line 21 that appears after
one of the expressions. These changes ensure consistent and correct mathematical
notation across all examples in the file.

```

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.
31 changes: 31 additions & 0 deletions pymath/power_of_three/__init__.py
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
40 changes: 40 additions & 0 deletions pymath/power_of_three/test_power_of_three.py
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()
Loading