# 009 — Power of 10 Check

> 003-এ তুমি বারবার `// 10` করে digit গুনেছিলে। আজ একই peeling loop, কিন্তু এবার গোনা নয় — আমরা দেখব সংখ্যাটা ঠিক **10-এর কোনো power** কিনা (1, 10, 100, 1000...)। মূল মজা একটা প্রশ্নে: "10 দিয়ে বারবার ভাগ করতে করতে কি ঠিক 1-এ গিয়ে থামে, নাকি মাঝপথে কোনো অবাঞ্ছিত digit বেরিয়ে আসে?" এই চিন্তাটা পরে "power of 2", "power of 3" — সব power-check-এ ফিরবে।

<div class="problem-source" markdown="1">

<p class="source-label" id="source">Problem link ও উৎস</p>

- Original source: Classic beginner exercise
- Platform: Classic exercise
- Topic: Math-based programming fundamentals → Level 0: Absolute Basics
- Difficulty: Easy
- Pattern: repeated division
- Basic idea inherited from: 003 (Count Digits)

</div>

## প্রশ্ন ও উদাহরণ {#problem}

### সহজ করে প্রশ্ন {#1-problem-in-simple-words}

একটা positive integer `n` দেওয়া আছে। বলতে হবে সেটা **10-এর কোনো power** কিনা — মানে `1, 10, 100, 1000, 10000, ...` এই তালিকায় পড়ে কিনা।

মনে করিয়ে দিই: `10^0 = 1`, `10^1 = 10`, `10^2 = 100` — তাই **1-ও** 10-এর power (অনেকে এটা ভুলে যায়)।

উত্তর হবে `True` বা `False`।

### Input ও output {#6-example-input-and-output}

```text
input   ->  output   (কেন)
---------------------------
    1   ->  True      (10^0 = 1 — সাবধান, 1-ও power!)
   10   ->  True      (10^1)
  100   ->  True      (10^2)
 1000   ->  True      (10^3)
  120   ->  False     (12-এ গিয়ে digit 2 বেরোল)
   50   ->  False     (5-এ থামে, 1 নয়)
    0   ->  False     (0 কখনো power নয়)
   -10  ->  False     (negative power নয়)
```

সবচেয়ে দামি দুটো পরীক্ষা: **1 → True** (অনেকে ভুলে False ভাবে), আর **0 → False** (0-কে বারবার ভাগ করলেও 1-এ পৌঁছায় না)।

### চেনা উদাহরণে বোঝা {#4-real-life-analogy}

ভাবো একটা **পেঁয়াজ**, আর তুমি একটা একটা করে খোসা ছাড়াচ্ছ। কিন্তু এই পেঁয়াজের নিয়ম অদ্ভুত — প্রতিটা খোসা যদি **পরিষ্কার** (শূন্য digit) হয় আর শেষে যদি ঠিক **একটাই ছোট্ট কুঁড়ি** (1) পড়ে থাকে, তবেই বলব "এটা খাঁটি 10-পেঁয়াজ"।

- প্রতিবার এক খোসা ছাড়ানো = `n //= 10`
- খোসাটা পরিষ্কার কিনা দেখা = `n % 10 == 0` কিনা
- মাঝপথে নোংরা খোসা (যেমন digit 2) পেলে = "ভেজাল, এটা 10-এর power না" → False
- শেষে ঠিক 1 কুঁড়ি = খাঁটি 10-এর power

`100` খোসা ছাড়ালে: `100 → 10 → 1` — সব খোসা পরিষ্কার, শেষে 1। `120` ছাড়ালে প্রথম খোসাতেই 2 বেরোল — ভেজাল।

## ভিত্তির ধারণা {#idea}

### আগের কোন ধারণাটি লাগবে {#3-which-basic-idea-does-this-inherit-from}

সরাসরি **003 (Count Digits)** থেকে।

003-এ আমরা peeling loop (`n //= 10` দিয়ে এক-একটা digit ফেলা) চালিয়ে **গুনতাম** কতবার ফেললাম। 009-এ হুবহু সেই peeling loop, শুধু গোনার বদলে প্রতি ধাপে একটা **শর্ত যাচাই** করছি — "এই digit-টা কি 0?"

```
003 (count):  while n > 0:  count += 1            ;  n //= 10
009 (pow10):  while n > 1:  if n % 10 != 0: False  ;  n //= 10
                            ^^^^^^^^^^^^^^^^^^^^^^
                          গোনার বদলে শর্ত পরীক্ষা
```

মানে আবারও সেই inheritance-এর সুর: peeling loop একই, শুধু "প্রতি ধাপে কী করব" বদলায়। 002-এ যোগ, 003-এ গোনা, 009-এ যাচাই।

### ভেতরের অঙ্ক {#2-what-is-the-math-idea}

মূল idea — **repeated division by 10**। যদি `n` সত্যিই 10-এর power হয়, তবে তাকে বারবার 10 দিয়ে ভাগ করতে থাকলে শেষে ঠিক **1**-এ পৌঁছাবে, আর প্রতিবার ভাগটা **নিঃশেষে** (remainder 0) হবে।

```
যতক্ষণ n > 1:
    যদি n % 10 != 0:   -> মাঝপথে শূন্য-নয় digit বেরোল -> 10-এর power না
        return False
    n //= 10
শেষে n == 1 হলে -> হ্যাঁ, 10-এর power
```

মূল শর্ত দুটো: (ক) প্রতিবার last digit `0` হতে হবে, (খ) শেষে ঠিক `1` থাকতে হবে। যেমন `100 → 10 → 1` (সব ধাপে last digit 0, শেষে 1) ✓; কিন্তু `120 → 12`, এখানে `12 % 10 = 2 ≠ 0` → থামো, **False**।

## ধাপে ধাপে সমাধান {#walkthrough}

### প্রথম সরল উপায় {#7-brute-force-thinking}

প্রথমে যা মাথায় আসে — 10-এর power গুলো **একটা একটা করে বানিয়ে** `n`-এর সাথে মেলাই, যতক্ষণ না সমান বা বড় হয়:

```python
def is_power_of_10_brute(n):
    if n < 1:
        return False
    p = 1                  # 10^0 থেকে শুরু
    while p < n:
        p *= 10            # পরের power: 10, 100, 1000...
    return p == n          # ঠিক মিলল?
```

এটা সহজ আর সরল — 1, 10, 100... বানাতে থাকো; `n` ছাড়িয়ে গেলে থামো; ঠিক সমান হলে `True`। আরেকটা পথ string দিয়ে: "প্রথম digit 1, বাকি সব 0" কিনা দেখা।

### কোথায় বেশি কাজ হতে পারে {#8-why-brute-force-may-be-slow}

এই brute force আসলে ধীর নয় — power গুলো দশগুণ হারে বাড়ে, তাই মাত্র `log₁₀ n` বার loop ঘোরে, ঠিক peeling পদ্ধতির সমান। তাহলে peeling কেন শিখব?

- **শেখার লক্ষ্য:** এই level-এর আসল target হলো **peeling loop**-টা নানা কাজে বসাতে পারা। power বানানোর brute force শুধু এই problem-এ খাটে; peeling pattern পরের অনেক problem-এ (power of 2/3, trailing zeros) ফিরবে।
- **overflow-চিন্তা:** C++/Java-তে বারবার `p *= 10` করলে p বড় হয়ে overflow হতে পারে (যদিও Python-এ নয়); peeling-এ n শুধু **ছোট** হয়, তাই সে ঝুঁকি নেই।
- **multiplication vs division:** brute force গুণে বড় হয়, peeling ভাগে ছোট হয় — ছোট হওয়াটা সবসময় নিরাপদ।

```text
n = 1000000 (10^6) হলে:
  brute : 1 -> 10 -> ... -> 1000000   (7 বার গুণ, ঠিক)
  peel  : 1000000 -> ... -> 1          (7 বার ভাগ, ঠিক)
দুটোই O(log n); কিন্তু peeling pattern-টা বেশি কাজে লাগবে
```

### আরও ভালোভাবে ভাবা {#9-better-thinking}

peeling loop দিয়ে সরাসরি যাচাই — প্রতি digit 0 কিনা দেখি, শেষে 1 থাকল কিনা দেখি:

```python
def is_power_of_10(n):
    if n < 1:
        return False        # 0 আর negative বাদ
    while n % 10 == 0:       # last digit 0 থাকলে খোসা ছাড়াও
        n //= 10
    return n == 1           # সব 0 ছাড়ানোর পর ঠিক 1 বাকি?
```

লক্ষ করো — এখানে loop চলে যতক্ষণ last digit 0; প্রথম শূন্য-নয় digit পেলেই loop থামে, আর তখন `n == 1` কিনা সেটাই উত্তর। `1000 → 100 → 10 → 1`, শেষে 1 → True। `120 → 12`, last digit 2 তাই loop থামল, `12 == 1`? না → False।

### ভাবনার পরিবর্তন {#10-thinking-tweak}

মূল মোচড়: **10-এর power মানে এমন সংখ্যা যার শুধু একটাই শূন্য-নয় digit, আর সেটা সামনের `1` — বাকি সব trailing zero।**

তাই কৌশল দাঁড়ায় — **trailing zero গুলো খোসার মতো ছাড়িয়ে ফেলো, যা পড়ে থাকে তা ঠিক `1` হলেই power।** `% 10 == 0` দিয়ে শূন্য ছাড়াই, তারপর শেষে `== 1` মিলিয়ে দেখি।

এই "trailing zero ছাড়িয়ে কোর দেখা" tweak generalize হয়: একই কাঠামোয় (ভাগের base বদলে) power of 2 (`% 2`, শেষে 1), power of 3 (`% 3`, শেষে 1) — সবই হয়।

### ছবিতে বোঝা {#5-visual-explanation}

খাঁটি (`1000`) আর ভেজাল (`120`) — দুটো পাশাপাশি খোসা ছাড়িয়ে দেখো:

```text
খাঁটি: n = 1000
  step 1: 1000 % 10 = 0 ✓   1000 //10 -> 100
  step 2:  100 % 10 = 0 ✓    100 //10 -> 10
  step 3:   10 % 10 = 0 ✓     10 //10 -> 1
  loop থামল (n = 1)  ->  n == 1 ?  হ্যাঁ  ->  True

ভেজাল: n = 120
  step 1:  120 % 10 = 0 ✓    120 //10 -> 12
  step 2:   12 % 10 = 2 ✗  <-- শূন্য-নয় digit!  ->  সঙ্গে সঙ্গে False
```

এক বাক্যে: **সব খোসা 0 হলে আর শেষে ঠিক 1 থাকলে — তবেই 10-এর power।**

### ছোট input-এ ধাপে ধাপে {#11-step-by-step-dry-run}

`n = 1000` ধীরে চালাই (Section 9-এর "trailing zero ছাড়ানো" version):

| step | n (শুরুতে) | n % 10 == 0? | n //= 10 (পরে) |
| --- | --- | --- | --- |
| 1 | 1000 | হ্যাঁ (0) | 100 |
| 2 | 100 | হ্যাঁ (0) | 10 |
| 3 | 10 | হ্যাঁ (0) | 1 |
| 4 | 1 | না (1 % 10 = 1) | loop থামল |

loop শেষে `n = 1`, তাই `return n == 1` → **True**। ঠিক, `1000 = 10^3`।

এবার মনে মনে `n = 120` চালাও: step 1 — `120 % 10 = 0`, `n` হলো 12। step 2 — `12 % 10 = 2 ≠ 0`, loop থামল। `12 == 1`? না → **False**। আর `n = 1`: loop একবারও চলে না (`1 % 10 = 1`), সরাসরি `1 == 1` → **True** — 1-ও যে power, এটা এমনিই সামলে গেল।

## কোড ও ব্যাখ্যা {#code}

### Python {#12-python-solution}

```python
def is_power_of_10(n):
    """n ঠিক 10-এর power হলে True, নাহলে False।"""
    if n < 1:
        return False            # 0 আর negative power নয়
    while n % 10 == 0:          # trailing zero থাকলে ছাড়াও
        n //= 10
    return n == 1              # খোসা ছাড়ানোর পর ঠিক 1?


def is_power_of_10_brute(n):
    """একই উত্তর, power বানিয়ে মেলানো (তুলনার জন্য)।"""
    if n < 1:
        return False
    p = 1
    while p < n:
        p *= 10
    return p == n


# --- ছোট test গুলো (সব pass করা উচিত) ---
assert is_power_of_10(1) is True       # 10^0 — দামি edge case
assert is_power_of_10(10) is True
assert is_power_of_10(100) is True
assert is_power_of_10(1000) is True
assert is_power_of_10(120) is False    # মাঝে digit 2
assert is_power_of_10(50) is False     # 5-এ থামে
assert is_power_of_10(0) is False      # 0 power নয়
assert is_power_of_10(-10) is False    # negative নয়
assert is_power_of_10_brute(1000) is True   # দুই পদ্ধতি মেলে
assert is_power_of_10_brute(120) is False

print(is_power_of_10(1))      # True
print(is_power_of_10(1000))   # True
print(is_power_of_10(120))    # False
print("সব test pass!")
```

### কোডের প্রতিটি অংশ {#13-line-by-line-explanation}

```
    if n < 1:
        return False
```

**প্রথম রক্ষাকবচ।** 0 আর সব negative সংখ্যা সরাসরি বাদ — কোনো 10-এর power শূন্য বা ঋণাত্মক হয় না। এটা না থাকলে `n = 0`-এ loop নিয়ে গোলমাল হবে।

```
    while n % 10 == 0:
        n //= 10
```

চেনা peeling loop, কিন্তু শর্তসহ — যতক্ষণ last digit 0, ততক্ষণ খোসা (trailing zero) ছাড়াও। প্রথম শূন্য-নয় digit পেলেই থামে।

```
    return n == 1
```

খোসা ছাড়ানোর পর যা পড়ে রইল সেটাই আসল কথা। ঠিক `1` হলে → সব digit ছিল trailing zero-এর উপরে একটা 1 → 10-এর power। `1` না হলে (যেমন 12, বা 5) → power নয়।

`is_power_of_10_brute` হলো তুলনার version — `p` কে 1 থেকে শুরু করে দশগুণ বাড়াতে বাড়াতে `n`-এ পৌঁছাই; ঠিক মিললে `True`।

বাকি `assert` গুলো নিজেদের যাচাই করছে; সব ঠিক থাকলে শেষে `সব test pass!` ছাপে। (লক্ষ করো `is True` / `is False` ব্যবহার — boolean ফেরত নিশ্চিত করতে।)

### Output মিলিয়ে দেখা {#14-output-walkthrough}

চালালে ছাপবে:

```text
True
True
False
সব test pass!
```

তিনটা লাইন তিনটা `print` থেকে: `is_power_of_10(1)` → True (1-ও power!), `is_power_of_10(1000)` → True, `is_power_of_10(120)` → False। আগের সব `assert` চুপচাপ pass করেছে — দুই পদ্ধতির উত্তর মিলেছে। শেষ লাইন `সব test pass!` মানে সব ঠিক।

## খরচ ও সাধারণ ভুল {#cost}

### সময় {#15-time-complexity}

**O(log₁₀ n)** — peeling loop প্রতি ধাপে `n`-কে 10 দিয়ে ভাগ করে, তাই digit সংখ্যার সমান (≈ `log₁₀ n`) বার ঘোরে। 9-digit সংখ্যাতেও মাত্র 9 বার — খুব দ্রুত। brute version-ও একই, power গুলো দশগুণ হারে বাড়ে বলে।

### অতিরিক্ত জায়গা {#16-space-complexity}

**O(1)** — শুধু `n` (আর brute-এ `p`); কোনো বাড়তি list বা string নেই, সংখ্যার আকারের সাথে স্মৃতি বাড়ে না।

### যে ভুলগুলো এড়াতে হবে {#17-common-mistakes}

1. **1-কে বাদ দেওয়া** — `10^0 = 1`, তাই **1 অবশ্যই True**। `while n > 1` বা `n == 1` চেক ভুল বসালে 1 ফসকে যায়। সবচেয়ে কমন ভুল।
2. **0 আর negative ভুলে যাওয়া** — শুরুতে `if n < 1: return False` না থাকলে `n = 0`-এ `0 % 10 == 0` সত্যি, কিন্তু `0 // 10 = 0` — loop সাধারণত আটকায় না (Python-এ `0 % 10 == 0` চিরকাল সত্যি হলে infinite loop-ও হতে পারে); তাই আগে আটকাও।
3. **শুধু trailing zero গুনে থেমে যাওয়া** — `120`-এ একটা trailing zero আছে, কিন্তু তবু power নয়। শূন্য থাকা যথেষ্ট নয়; **শেষে ঠিক 1 থাকা** জরুরি।
4. **`% 10` আর `// 10` উল্টে ফেলা** — `% 10` digit দেখে, `// 10` digit ফেলে; উল্টে দিলে সব ভুল।
5. **float power দিয়ে চেক** — `math.log10(n)` integer কিনা দেখা float বলে বড় power-এ অনির্ভরযোগ্য (`log10(1000)` 2.9999... আসতে পারে); peeling integer-এ নিরাপদ।

## শেখা ও পরের অনুশীলন {#practice}

### এই ধারণার পরের অনুশীলন {#18-harder-problems-that-inherit-this-idea}

- **LeetCode — Power of Two** (<https://leetcode.com/problems/power-of-two/>) — হুবহু একই চিন্তা, base 10-এর বদলে 2: বারবার `% 2 == 0` ছাড়িয়ে শেষে 1 কিনা (অথবা bit-trick `n & (n-1) == 0`)।
- **LeetCode — Power of Three** (<https://leetcode.com/problems/power-of-three/>) — base 3-এ একই peeling: `% 3 == 0` ছাড়াও, শেষে 1।
- **003 — Count Digits** (এই repo) — যে peeling loop থেকে এটা এল; পার্থক্য শুধু "প্রতি ধাপে কী করি"।

### কৌশলটি মনে রাখুন {#19-pattern-learned}

**Power check via repeated division** — base দিয়ে বারবার ভাগ করতে করতে ঠিক 1-এ পৌঁছালে (আর প্রতি ভাগ নিঃশেষ হলে) সেটা সেই base-এর power। বড় শিক্ষা: **একই peeling loop-এ "প্রতি ধাপে শর্ত যাচাই" বসিয়ে দিলে গোনা থেকে যাচাই-এ চলে আসা যায়; আর base বদলেই power of 2/3/10 সব এক কাঠামোয় ধরা যায়।**

### নিজেকে যাচাই করুন {#20-final-summary}

ভবিষ্যতের আমাকে এক লাইনে: *"power of 10 = trailing zero (`% 10 == 0`) গুলো `// 10` দিয়ে ছাড়িয়ে ফেলো, শেষে ঠিক `1` থাকলে True। 1-ও power (10^0); 0 আর negative শুরুতেই বাদ। base বদলেই power of 2/3 — একই কাঠামো।"*

আগের ধাপ → [003 — Count Digits](003-count-digits.md) (যে peeling loop থেকে এল)। শিকড়ে → [001 — Even or Odd](001-even-or-odd.md)। সম্পর্কিত → [008 — Find Last Digit](008-find-last-digit.md)।

ফিরে দেখা: এই level-এর map → [../README.md](../README.md) · এই note-টা যে ছকে লেখা → [../../../templates/math-problem-note-template.md](../../../templates/math-problem-note-template.md)।

---

> **মনে রাখার নিয়ম (legal):** সব নিজের ভাষায় লেখা; problem statement copy করা হয়নি; official link শুধু attribution-এর জন্য রাখা; "asked by Google/Amazon" এমন দাবি করা হয়নি — বরং "common interview pattern" হিসেবে লেখা।
