# 002 — Sum of Digits

> 001-এ আমরা `%` দিয়ে last *bit* ছুঁয়েছিলাম। আজ একই কৌশল সামান্য বদলে — `% 10` দিয়ে last *digit* ছোঁব, আর তার সাথে যোগ হবে আমাদের প্রথম "asol" loop। এই loop-টা পুরো level 0-এর হৃৎপিণ্ড; একবার হাতে এলে অর্ধেক problem এমনিই খুলে যাবে। ধীরে যাও, dry run-টা নিজে হাতে করো।

<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: digit extraction (sum)
- Basic idea inherited from: 001 (Even or Odd)

</div>

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

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

একটা integer `n` দেওয়া আছে। তার **সব digit যোগ করে** sum বের করতে হবে।

যেমন `1234` হলে digit গুলো 1, 2, 3, 4 — যোগফল `1 + 2 + 3 + 4 = 10`।

আমরা str ছাড়া, শুধু arithmetic (`%` আর `//`) দিয়ে এটা করব — কারণ এই পদ্ধতিটাই পরের অনেক problem-এ ঘুরেফিরে লাগবে।

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

```
input   ->  output   (কীভাবে)
------------------------------
 1234   ->   10      (1+2+3+4)
    0   ->    0      (digit একটাই: 0, যোগফল 0)
    7   ->    7      (একটাই digit)
   99   ->   18      (9+9)
  305   ->    8      (3+0+5, মাঝের 0-ও ঠিক ধরা পড়ে)
-1234   ->   10      (চিহ্ন বাদ দিয়ে digit গুলোই গোনা)
```

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

ভাবো একটা **পয়সার কৌটো (piggy bank)**, মুখটা সরু — একসাথে অনেক কয়েন বের হয় না, এক-একটা করে ঝাঁকিয়ে ফেলতে হয়।

- প্রতিবার ঝাঁকুনিতে নিচ থেকে **একটা কয়েন** পড়ে → `n % 10` (last digit তুলে নেওয়া)
- সেই কয়েনের মূল্য তোমার **মোট গোনায়** যোগ করো → `total += digit`
- কৌটোয় বাকি কয়েন রয়ে গেল → `n //= 10` (একটা কমে গেল)

কৌটো খালি (`n = 0`) হলে থামো। হাতে যা মোট জমেছে — সেটাই sum of digits। এক-একটা কয়েন এক-একটা digit, আর ঝাঁকুনিই হলো আমাদের loop।

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

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

সরাসরি **001 (Even or Odd)** থেকে।

001-এ শিখেছিলাম — পুরো সংখ্যা না দেখে শুধু **শেষটা** দেখলেই চলে, আর সেই শেষটা ধরিয়ে দেয় `%` operator (`n % 2` last bit)। আজ ঠিক সেই idea, শুধু 2-এর জায়গায় 10:

```
001:  n % 2   -> last bit / even-odd
002:  n % 10  -> last digit  (একই "শেষ ছোঁয়ার" চিন্তা, বড় ভাই)
```

001-এ আমরা শুধু একবার শেষটা দেখেছিলাম। 002-এ এসে শেষটা দেখি, ফেলে দিই, আবার শেষটা দেখি — মানে একই idea-কে loop-এ বসিয়ে দিলাম। এটাই inheritance: পুরোনো চিন্তা + একটা নতুন মোচড়।

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

দুটো operator-এর জুটি — এদেরই বলি "digit-কাটার কাঁচি":

- `n % 10` → সংখ্যার **last digit** দেয়। যেমন `1234 % 10 = 4`।
- `n // 10` → last digit **ফেলে দেওয়া** সংখ্যা দেয় (খোসা ছাড়ানো)। যেমন `1234 // 10 = 123`।

তাহলে কৌশল: বারবার last digit তুলে যোগফলে জমা করো, তারপর সেই digit ফেলে দাও — যতক্ষণ না সংখ্যাটা 0 হয়ে যায়।

```
total = 0
যতক্ষণ n > 0:
    total += n % 10      # last digit তুলে যোগ করো
    n //= 10             # সেই digit ফেলে দাও
```

এই `while n > 0` কাঠামোটাকে বলে **digit extraction loop** — মুখস্থ না, বুঝে নাও।

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

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

প্রথমে যেটা মাথায় আসে — সংখ্যাটাকে **string বানিয়ে** ফেলি, তারপর প্রতিটা অক্ষর আবার int করে যোগ করি:

```python
def sum_of_digits_str(n):
    total = 0
    for ch in str(abs(n)):   # "1234" -> '1','2','3','4'
        total += int(ch)     # প্রতিটা অক্ষরকে সংখ্যা বানিয়ে যোগ
    return total
```

এটা কাজ করে, ঠিক উত্তর দেয়, পড়তেও সহজ। অনেক সময় এটাই যথেষ্ট। তাহলে সমস্যা কোথায়?

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

Time-এর দিক থেকে string version মোটেও "ধীর" নয় — দুটোই digit সংখ্যার সমান কাজ করে। কিন্তু কিছু লুকোনো খরচ আছে:

- **বাড়তি জায়গা:** `str(n)` একটা নতুন string বানায় — মানে O(digit) extra space। arithmetic loop-এ সেটা লাগে না (O(1) space)।
- **type conversion:** প্রতিটা অক্ষরে `int(ch)` ডাকা — ছোট কিন্তু অপ্রয়োজনীয় overhead।
- **ভাষা-নির্ভরতা:** Python-এ `str()` সহজ, কিন্তু C++/Java-তে string-এ যাওয়া-আসা ঝামেলার। arithmetic পদ্ধতি **যেকোনো ভাষায়** একইভাবে চলে — interview-তে এটা বড় সুবিধা।

মূল কথা: string version দিয়ে উত্তর পাওয়া যায়, কিন্তু এই level-এর **আসল লক্ষ্য** হলো arithmetic loop-টা আয়ত্ত করা — কারণ পরের problem গুলোতে (reverse, palindrome, armstrong) string দিয়ে চালানো যায় না, ওখানে এই `% 10 // 10` loop-ই লাগবে।

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

String বাদ — সরাসরি সংখ্যার উপরেই digit-কাটার কাঁচি চালাই:

```python
def sum_of_digits(n):
    n = abs(n)          # negative হলেও digit একই
    total = 0
    while n > 0:
        total += n % 10   # last digit যোগ করো
        n //= 10          # last digit ফেলো
    return total
```

কোনো নতুন string নেই, কোনো type conversion নেই — শুধু সংখ্যা আর দুটো operator। জায়গা লাগছে O(1), আর এই loop-টাই হবে তোমার সারা জীবনের সঙ্গী।

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

মাথায় এই ছবিটা গেঁথে নাও — **একটা সংখ্যা মানে digit-এর একটা সারি, আর `% 10` / `// 10` দিয়ে তুমি সেই সারির ডান প্রান্ত থেকে একটা একটা করে খুলছ।**

- `% 10` = "ডান প্রান্তের জিনিসটা দেখাও" (পড়ে নাও, সরাও না)
- `// 10` = "ডান প্রান্তেরটা সরিয়ে দাও" (এক ঘর ছোট হলো)

এই দুটো একসাথে = "ডান থেকে বাঁয়ে digit ধরে হাঁটা"। আজ আমরা হাঁটতে হাঁটতে **যোগ** করছি; কাল 003-এ একই হাঁটায় শুধু **গুনব** (count); পরে armstrong-এ digit-কে power-এ তুলব। হাঁটাটা এক, শুধু "প্রতি ধাপে কী করব" বদলায়।

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

`1234` থেকে এক-একটা digit বেরিয়ে আসছে, পাশে running total বাড়ছে — frame by frame:

```
শুরুতে: n = 1234, total = 0

frame 1:  n = 1 2 3 [4]   --%10-->  4   total = 0 + 4 = 4
                    ^^^    --//10->  n = 123

frame 2:  n = 1 2 [3]     --%10-->  3   total = 4 + 3 = 7
                  ^^^      --//10->  n = 12

frame 3:  n = 1 [2]       --%10-->  2   total = 7 + 2 = 9
                ^^^        --//10->  n = 1

frame 4:  n = [1]         --%10-->  1   total = 9 + 1 = 10
              ^^^          --//10->  n = 0   (কৌটো খালি, থামো!)

ফলাফল: total = 10
```

খেয়াল করো — digit গুলো বেরোচ্ছে **ডান থেকে বামে** (4, 3, 2, 1), কিন্তু যোগফলে ক্রম কোনো ব্যাপার না, তাই sum ঠিকঠাক 10।

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

`n = 1234` ধীরে চালাই। প্রতি ধাপে চারটে জিনিস লক্ষ করো — শুরুর n, তোলা digit, নতুন total, আর খোসা-ছাড়ানো n:

| step | n (শুরুতে) | d = n % 10 | total (পরে) | n //= 10 (পরে) |
| --- | --- | --- | --- | --- |
| 1 | 1234 | 4 | 0 + 4 = 4 | 123 |
| 2 | 123 | 3 | 4 + 3 = 7 | 12 |
| 3 | 12 | 2 | 7 + 2 = 9 | 1 |
| 4 | 1 | 1 | 9 + 1 = 10 | 0 |

ধাপ 4-এর শেষে `n = 0`, তাই `while n > 0` আর সত্যি নয় — loop থামল। **total = 10** — ঠিক 1+2+3+4। নিজে খাতায় এই টেবিলটা আরেকবার বানাও 305 বা 99 দিয়ে, হাত যেন চিনে যায়।

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

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

```python
def sum_of_digits(n):
    """n-এর সব digit-এর যোগফল (arithmetic পদ্ধতি)।"""
    n = abs(n)              # negative-এর জন্য চিহ্ন বাদ
    total = 0
    while n > 0:
        d = n % 10          # last digit
        total += d          # যোগফলে জমা
        n //= 10            # last digit ফেলে দাও
    return total


def sum_of_digits_str(n):
    """একই উত্তর, string পদ্ধতি (তুলনার জন্য)।"""
    return sum(int(ch) for ch in str(abs(n)))


# --- ছোট test গুলো (সব pass করা উচিত) ---
assert sum_of_digits(1234) == 10
assert sum_of_digits(0) == 0       # 0-এর digit sum 0
assert sum_of_digits(7) == 7
assert sum_of_digits(99) == 18
assert sum_of_digits(305) == 8     # মাঝের 0-ও ধরা পড়ে
assert sum_of_digits(-1234) == 10  # চিহ্ন বাদ
assert sum_of_digits_str(1234) == 10   # দুই পদ্ধতি মেলে

print(sum_of_digits(1234))   # 10
print(sum_of_digits(305))    # 8
print(sum_of_digits(99))     # 18
print("সব test pass!")
```

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

```
    n = abs(n)
```

negative হলে `abs()` দিয়ে চিহ্ন সরিয়ে দিই, যাতে `while n > 0` ঠিকমতো চলে আর digit গুলোই গোনা হয় (চিহ্ন নয়)।

```
    total = 0
```

যোগফল রাখার পাত্র, শুরুতে খালি।

```
    while n > 0:
```

যতক্ষণ সংখ্যায় digit বাকি আছে (n এখনো 0 হয়নি) — ততক্ষণ চালাও। কৌটোয় কয়েন আছে কিনা, এই চেক।

```
        d = n % 10
        total += d
```

last digit তুলে (`% 10`) যোগফলে জমা করি। (`d`-তে আলাদা করে রাখা বাধ্যতামূলক নয়, কিন্তু পড়তে সুবিধা।)

```
        n //= 10
```

**সবচেয়ে জরুরি লাইন** — last digit ফেলে দিয়ে n-কে এক ঘর ছোট করি। এটা না থাকলে n কখনো 0 হবে না → loop চিরকাল চলবে (infinite loop)।

`sum_of_digits_str` হলো generator expression — `str(abs(n))`-এর প্রতিটা অক্ষর `int()` করে `sum()` যোগ করে। ছোট আর সুন্দর, কিন্তু ভেতরে string বানায়।

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

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

```
10
8
18
সব test pass!
```

তিনটা সংখ্যা তিনটা `print` থেকে — 1234 → 10, 305 → 8, 99 → 18। তার আগে সব `assert` চুপচাপ pass করেছে (একটাও fail করলে সেখানেই থেমে error দিত)। শেষ লাইন `সব test pass!` মানে দুই পদ্ধতির উত্তর মিলেছে, সব ঠিক।

### JavaScript ও test cases {#21-javascript-solution-with-test-cases}

Python-এ integer division `//` আছে, JS-এ নেই — তাই খোসা-ছাড়ানোতে `Math.floor(n / 10)` লাগবে (নিচের টীকা)।

```javascript
function sumOfDigits(n) {
  n = Math.abs(n);            // negative হলেও digit একই
  let total = 0;
  while (n > 0) {
    total += n % 10;         // last digit তুলে যোগ
    n = Math.floor(n / 10);  // JS-এ // নেই → Math.floor দিয়ে integer division
  }
  return total;
}

// ছোট throwing assert — fail করলে এখানেই থেমে error দেবে
const assert = (cond, msg = "") => { if (!cond) throw new Error("FAIL " + msg); };

// ---- test cases ----
assert(sumOfDigits(1234) === 10, "1234");
assert(sumOfDigits(0) === 0, "0");
assert(sumOfDigits(99) === 18, "99");
assert(sumOfDigits(305) === 8, "305");        // মাঝের 0-ও ধরা পড়ে
assert(sumOfDigits(-1234) === 10, "-1234");   // চিহ্ন বাদ
console.log("সব JS test pass!");
```

> **JS টীকা:** JavaScript-এ floor-division operator নেই; `n = Math.floor(n / 10)` (অথবা ছোট সংখ্যায় `n = (n / 10) | 0`) ব্যবহার করো — সরাসরি `n / 10` দিলে decimal থেকে যাবে আর loop ভুল চলবে। আর `Math.abs` আগে নাও, কারণ JS-এ `-1234 % 10 === -4`।

### TypeScript ও test cases {#22-typescript-solution-with-test-cases}

```typescript
function sumOfDigits(n: number): number {
  n = Math.abs(n);
  let total = 0;
  while (n > 0) {
    total += n % 10;
    n = Math.trunc(n / 10); // Math.trunc = "ভগ্নাংশ ফেলে দাও" — intent পরিষ্কার
  }
  return total;
}

// ---- typed test table: [input, expected] ----
const cases: ReadonlyArray<readonly [number, number]> = [
  [1234, 10], [0, 0], [99, 18], [305, 8], [-1234, 10],
];
for (const [input, want] of cases) {
  const got = sumOfDigits(input);
  if (got !== want) throw new Error(`FAIL ${input}: got ${got}, want ${want}`);
}
console.log("সব TS test pass!");
```

> **TS টীকা:** test গুলো একটা `ReadonlyArray<readonly [number, number]>` table-এ রাখলে নতুন case যোগ করা সহজ আর tuple type ভুল-আকারের case compile-time-এই আটকায়। এটাই data-driven / table-driven testing — production test suite-এ খুব কমন।

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

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

**O(number of digits) = O(log₁₀ n)**। loop প্রতিবার `n`-কে 10 দিয়ে ভাগ করে, তাই যতগুলো digit ততবারই ঘোরে। 9-digit সংখ্যা হলে মাত্র 9 বার — সংখ্যা যত বড় হোক, digit সংখ্যা তার লগারিদমের সমান, তাই খুবই দ্রুত।

(কেন `log`? কারণ একটা সংখ্যার digit সংখ্যা ≈ `log₁₀(n) + 1`। 1000-এর 4 digit, 10000-এর 5 — দশগুণ বাড়লে digit বাড়ে মোটে একটা।)

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

**O(1)** — arithmetic version-এ শুধু `total`, `d`, `n` — গুটিকয় variable, সংখ্যার আকারের সাথে বাড়ে না। (string version-এ O(digit) — কারণ পুরো string-টা মেমরিতে বানায়।)

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

1. **`n //= 10` ভুলে যাওয়া** — সবচেয়ে কমন ভুল। ছাড়া পড়লে `n` একই থেকে যায়, `while n > 0` কখনো শেষ হয় না → **infinite loop**।
2. **`%` আর `//` উল্টে ফেলা** — `n % 10` digit দেয়, `n // 10` খোসা ফেলে। উল্টে দিলে সব ভুল। মনে রাখো: `%` = "যা বাকি", `//` = "কতবার ঢুকল"।
3. **`% 2` লিখে ফেলা** — 001-এর অভ্যাসে অনেকে `% 2` লেখে; digit চাই বলে `% 10` লাগবে।
4. **negative ভুলে যাওয়া** — `abs(n)` না নিলে `-1234`-এ `while n > 0` একবারও চলবে না, ভুল করে 0 ফেরত আসবে।
5. **`total` বাইরে initialize না করা** — `total = 0` loop-এর ভেতরে বসালে প্রতিবার রিসেট হয়ে যাবে।

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

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

এই digit extraction loop-ই নিচের সবগুলোর ভিত্তি:

- **007 — Digital Root** (এই repo) — digit sum বারবার নাও যতক্ষণ না এক digit থাকে (9875 → 29 → 11 → 2)। এটাই digit sum-এর সরাসরি বড় ভাই; এর সাথে আছে `% 9`-এর জাদু। সম্পর্কিত: **LeetCode — Add Digits** (<https://leetcode.com/problems/add-digits/>)।
- **006 — Armstrong Number** (এই repo) — একই loop, কিন্তু digit যোগ না করে `digit ** k` যোগ করো।
- **LeetCode — Happy Number** (<https://leetcode.com/problems/happy-number/>) — এখানে digit-এর *বর্গের* যোগফল বারবার নিতে হয়; ভেতরের ইঞ্জিন সেই digit extraction loop।

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

**Digit extraction loop** — `while n > 0: d = n % 10; (d-কে কাজে লাগাও); n //= 10`। এটাই level 0-এর সবচেয়ে দরকারি, সবচেয়ে বেশিবার-ফেরা pattern। আজ "কাজে লাগাও" = যোগ করা; কাল শুধু এই এক লাইন বদলে count, power-sum, reverse — সব হবে। loop-টা একবার চোখ বন্ধ করে লিখতে পারলে অর্ধেক যুদ্ধ জেতা।

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

ভবিষ্যতের আমাকে এক লাইনে: *"digit sum = while loop-এ `n % 10` তুলে যোগ করো, `n //= 10` দিয়ে ফেলে দাও, n = 0 হলে থামো। 001-এর last-digit idea-ই এখানে loop হয়ে ফিরেছে — আর এই loop-টাই পরের সব digit problem-এর মা।"*

আগের ধাপ → [001 — Even or Odd](001-even-or-odd.md)। পরের ধাপ → [003 — Count Digits](003-count-digits.md) (একই loop, এবার গুনব)। আরও দূরে → [007 — Digital Root](007-digital-root.md)।

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

### কোথায় কাজে লাগে {#23-real-world-use}

Digit extraction (`% 10` / `/ 10`) loop-টা অসংখ্য জায়গায় লুকিয়ে থাকে:

- **Checksum / validation:** **Luhn algorithm** (credit/debit card নম্বর যাচাই) মূলত digit-sum-ভিত্তিক; ISBN, IMEI-তেও digit-sum check।
- **Cast-out-nines:** হিসাব দ্রুত যাচাই করতে digit sum mod 9 (পরের problem digital-root-এর ভিত্তি)।
- **Hashing / bucketing:** সরল hash-এ digit sum দিয়ে bucket বাছা।
- **Number formatting:** currency/locale formatting-এ digit ধরে ধরে process।
- **Base conversion:** ঠিক এই `% base` / `/ base` loop দিয়েই এক base থেকে আরেক base-এ সংখ্যা রূপান্তর।

মূল pattern **digit extraction loop** — একবার হাতে এলে reverse, palindrome, base-conversion, happy-number সব এর উপরেই দাঁড়ায়।

---

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