Skip to content

003 — Count Digits

002-এ তুমি digit extraction loop শিখেছ — সেই কষ্টের ফল এবার তুলে নেওয়ার পালা। আজকের problem-এ একই loop, প্রায় একই code, শুধু "প্রতি ধাপে কী করব" অংশটা বদলাবে। এটাই inheritance-এর মজা: নতুন problem, পুরোনো হাতিয়ার। সাথে একটা ছোট কিন্তু দামি ফাঁদ আছে (n = 0) — সেটা না দেখলে interview-তে ধরা খাবে।

Source

  • Original source: Classic beginner exercise
  • Platform: Classic exercise
  • Topic: Math-based programming fundamentals → Level 0: Absolute Basics
  • Difficulty: Easy
  • Pattern: digit extraction (count)
  • Basic idea inherited from: 002 (Sum of Digits)

1. Problem in simple words

একটা integer n দেওয়া আছে। তাতে কয়টা digit আছে — সেই সংখ্যাটা বের করতে হবে।

যেমন 1234-এ digit চারটে (1, 2, 3, 4), তাই উত্তর 47-এ একটাই, উত্তর 1

2. What is the math idea?

মূল চিন্তা 002-এর হুবহু সেই loop — % 10 দিয়ে last digit দেখা, // 10 দিয়ে ফেলে দেওয়া। শুধু এবার digit-গুলো যোগ না করে, কতবার ফেললাম সেটা গুনি:

count = 0
যতক্ষণ n > 0:
    count += 1     # একটা digit ফেলছি, তাই গোনায় এক বাড়ল
    n //= 10

এর বাইরে দুটো shortcut-ও আছে (পরে আলোচনা করব):

  • len(str(n)) — সংখ্যাকে string বানিয়ে দৈর্ঘ্য মাপা
  • math.floor(math.log10(n)) + 1 — খাঁটি গণিত, কোনো loop ছাড়াই

3. Which basic idea does this inherit from?

সরাসরি 002 (Sum of Digits) থেকে — আসলে এটা 002-এর প্রায় যমজ।

002-এর loop আর 003-এর loop পাশাপাশি রাখো:

002 (sum):    while n > 0:  total += n % 10 ;  n //= 10
003 (count):  while n > 0:  count += 1      ;  n //= 10
                            ^^^^^^^^^^^^
                       শুধু এই এক লাইন আলাদা

দেখো — peeling loop (n //= 10 দিয়ে খোসা ছাড়ানো) হুবহু এক। 002-এ প্রতি digit-এর মান জমিয়েছিলাম; এখানে শুধু কতবার ঘুরলাম গুনছি। এটাই বুঝিয়ে দেয়, একটা loop শিখে ফেললে কত problem এমনিই হাতে চলে আসে।

4. Real-life analogy

ভাবো একটা সিঁড়ি, আর তুমি অন্ধকারে নামছ — কয়টা ধাপ আছে জানো না।

  • প্রতিবার এক ধাপ নামলে মনে মনে গোনো: "এক... দুই... তিন..." → count += 1
  • এক ধাপ নিচে নামা = n //= 10 (সংখ্যা এক digit ছোট হলো)
  • মাটিতে পা পড়ল (n = 0) → থামো; এতক্ষণ যত গুনলে, সিঁড়িতে তত ধাপ

digit গোনা আর সিঁড়ির ধাপ গোনা — একই ব্যাপার: প্রতি ধাপে এক বাড়াও, তল ছুঁলে থামো।

5. Visual explanation

1234-এ peeling চলছে, পাশে counter একটা একটা করে টিক টিক করে বাড়ছে:

শুরুতে: n = 1234, count = 0

step 1:  n = 1234   --//10-->  123    count: 0 -> 1
step 2:  n = 123    --//10-->  12     count: 1 -> 2
step 3:  n = 12     --//10-->  1      count: 2 -> 3
step 4:  n = 1      --//10-->  0      count: 3 -> 4   (n = 0, থামো!)

মোট কতবার //10 করলাম = 4  ->  digit সংখ্যা 4

এক বাক্যে মনে রাখো: যতবার // 10 করে 0-তে পৌঁছালে, ততগুলোই digit।

6. Example input and output

input   ->  output   (কেন)
---------------------------
 1234   ->    4
    7   ->    1      (একটাই digit)
    0   ->    1      <-- সাবধান! 0-এরও কিন্তু একটা digit
 1000   ->    4      (পেছনের শূন্যগুলোও digit)
   99   ->    2
  -55   ->    2      (চিহ্ন বাদ, digit দুটো)

ওই 0 -> 1 লাইনটাই এই problem-এর সবচেয়ে দামি পরীক্ষা। ভেবে দেখো — খালি loop কিন্তু এখানে ভুল করবে (নিচে section 9 আর 17-এ ব্যাখ্যা)।

7. Brute force thinking

সবচেয়ে সৎ, "হাতে গুনে" পদ্ধতি — সেই চেনা peeling loop চালিয়ে এক একটা digit ফেলো আর গোনো:

def count_digits_loop(n):
    n = abs(n)
    if n == 0:
        return 1          # 0-এর জন্য আলাদা যত্ন
    count = 0
    while n > 0:
        count += 1
        n //= 10
    return count

এটা পরিষ্কার, যেকোনো ভাষায় চলে, আর 002-এর loop জানলে এক মিনিটেই লেখা যায়। digit সংখ্যা মুষ্টিমেয়, তাই এটা মোটেও ধীর নয় — এটাই বেশিরভাগ সময়ের সেরা উত্তর।

8. Why brute force may be slow

সত্যি বলতে এই loop "ধীর" নয় — O(log n), মানে 9-digit সংখ্যাতেও মাত্র 9 ধাপ। তাহলে আরও ভাবার দরকার কেন?

দুটো কারণে এটা জানা ভালো:

  • শুধু গোনাই যখন দরকার: আমরা digit-গুলোর মান নিয়ে কিছু করছি না, শুধু কয়টা জানতে চাই। এমন "শুধু সংখ্যা চাই" ক্ষেত্রে loop না চালিয়ে এক ধাপে (formula দিয়ে) উত্তর পাওয়া আরও পরিচ্ছন্ন।
  • বারবার ডাকা হলে: কোনো বড় program-এর ভেতরের loop-এ যদি লক্ষ-লক্ষ বার digit গুনতে হয়, তখন প্রতি বার ছোট loop চালানোর চেয়ে সরাসরি len(str(n)) বা formula দ্রুত মনে হয়।

মূল শিক্ষা ধীরগতি নয় — একই জিনিস কয়েকভাবে দেখতে পারা। চলো সেই বিকল্পগুলো দেখি।

9. Better thinking

দুটো ছোট বিকল্প, যেগুলো interview-তে জানা থাকলে নম্বর কাটে না:

(ক) string-এর দৈর্ঘ্য — Python নিজেই digit গুনে দেয়:

def count_digits_str(n):
    return len(str(abs(n)))     # "1234" -> 4 ; "0" -> 1 (এমনিই ঠিক!)

ছোট, সুন্দর, আর মজার ব্যাপার — 0-এর জন্যও আলাদা যত্ন লাগে না, কারণ str(0) হলো "0", দৈর্ঘ্য 1।

(খ) log10 formula — খাঁটি গণিত, কোনো loop ছাড়াই:

import math

def count_digits_log(n):
    if n == 0:
        return 1
    return math.floor(math.log10(abs(n))) + 1

কেন কাজ করে? কারণ log10 বলে দেয় সংখ্যাটা "কত শূন্যের ঘরে"। 1234-এর log10 ≈ 3.09, তার floor 3, +1 = 41000-এর log10 = 3, floor 3, +1 = 4। অর্থাৎ digit সংখ্যা = floor(log10(n)) + 1। এটা O(1) — একদম এক ধাপ।

(সতর্কতা: log10 floating-point দিয়ে চলে, তাই 10-এর বড় power-এ মাঝে মাঝে সামান্য ভুল করতে পারে — তাই নিরাপদ পছন্দ এখনো সেই loop। নিচে common mistakes-এ এই ফাঁদটা আছে।)

10. Thinking tweak

মূল মোচড় এক বাক্যে: যতবার // 10 করে 0-তে পৌঁছাও, ততগুলো digit।

002-এ আমরা peeling-এর সময় digit-এর মান কুড়িয়েছিলাম। এখানে মান নিয়ে মাথা ঘামাই না — শুধু পদক্ষেপ গুনি। একই হাঁটা, শুধু এবার পা ফেলার সংখ্যাটাই আমাদের উত্তর। তাই 002-এর loop থেকে শুধু total += n % 10 সরিয়ে count += 1 বসিয়ে দাও — ব্যস।

11. Step-by-step dry run

n = 1234। এখানে digit-এর মান অপ্রয়োজনীয়, তাই টেবিলে শুধু n আর count দেখছি:

step n (শুরুতে) count (পরে) n //= 10 (পরে)
1 1234 0 + 1 = 1 123
2 123 1 + 1 = 2 12
3 12 2 + 1 = 3 1
4 1 3 + 1 = 4 0

ধাপ 4-এর পর n = 0, loop থামল। count = 4 — ঠিক চারটে digit।

এবার মনে মনে n = 0 চালাও: abs(0) = 0, while 0 > 0 কখনো সত্যি নয়, তাই loop একবারও চলবে না, count থেকে যাবে 0 — অথচ সঠিক উত্তর 1! এজন্যই code-এ আগে থেকে if n == 0: return 1 বসাতে হয়। এই ছোট dry run-টাই বাগটা ধরিয়ে দেয়।

12. Python solution

import math

def count_digits(n):
    """n-এ কয়টা digit (arithmetic পদ্ধতি)।"""
    n = abs(n)
    if n == 0:
        return 1            # 0-এর digit সংখ্যা 1 — আলাদা handle
    count = 0
    while n > 0:
        count += 1
        n //= 10
    return count


def count_digits_str(n):
    """একই উত্তর, string পদ্ধতি (0-ও এমনিই ঠিক)।"""
    return len(str(abs(n)))


def count_digits_log(n):
    """একই উত্তর, log10 formula (O(1), কিন্তু float-সতর্কতা)।"""
    if n == 0:
        return 1
    return math.floor(math.log10(abs(n))) + 1


# --- ছোট test গুলো (সব pass করা উচিত) ---
assert count_digits(1234) == 4
assert count_digits(0) == 1        # সবচেয়ে দামি edge case
assert count_digits(7) == 1
assert count_digits(1000) == 4
assert count_digits(99) == 2
assert count_digits(-55) == 2      # চিহ্ন বাদ
assert count_digits_str(0) == 1
assert count_digits_str(1234) == 4
assert count_digits_log(1234) == 4 # power-of-10 নয়, তাই নিরাপদ

print(count_digits(1234))   # 4
print(count_digits(0))      # 1
print(count_digits(1000))   # 4
print("সব test pass!")

13. Line-by-line explanation

    n = abs(n)

চিহ্ন সরিয়ে দিই, যাতে negative সংখ্যাতেও digit গোনা ঠিক হয় (-5555)।

    if n == 0:
        return 1

এই problem-এর প্রাণভোমরা। 0-এর জন্য loop চলবেই না, তাই আগেভাগে 1 ফেরত দিই। এই দুই লাইন বাদ দিলে count_digits(0) ভুল করে 0 দেবে।

    count = 0
    while n > 0:
        count += 1
        n //= 10

চেনা peeling loop। প্রতিবার একটা digit ফেলছি (n //= 10) আর গোনায় এক বাড়াচ্ছি (count += 1)। n = 0 হলে থামে।

def count_digits_str(n):
    return len(str(abs(n)))

str(abs(n)) সংখ্যাকে string বানায়, len() তার অক্ষর গোনে = digit সংখ্যা। 0"0" → দৈর্ঘ্য 1, তাই এখানে আলাদা if লাগে না।

def count_digits_log(n):
    ...
    return math.floor(math.log10(abs(n))) + 1

log10 দিয়ে "কত ঘরের সংখ্যা" বের করে floor নিয়ে +1। দ্রুত, কিন্তু float বলে 10-এর বড় power-এ সাবধান (তাই এখানেও if n == 0 আলাদা)।

14. Output walkthrough

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

4
1
4
সব test pass!

তিনটা সংখ্যা তিনটা print থেকে: count_digits(1234) → 4, count_digits(0) → 1 (edge case ঠিকঠাক!), count_digits(1000) → 4। আগের সব assert নিঃশব্দে pass করেছে; শেষ লাইন সব test pass! মানে তিন পদ্ধতির উত্তরই মিলেছে।

15. Time complexity

O(log₁₀ n) — loop আর log version দুটোই। loop প্রতি ধাপে n-কে 10 দিয়ে ভাগ করে, তাই digit সংখ্যার সমান ঘোরে, আর digit সংখ্যা ≈ log₁₀ n। log10 formula তো আরও সরাসরি — গণিতের চোখে O(1)। str version-ও O(digit), কারণ string বানাতে সব digit পড়তে হয়।

16. Space complexity

  • loop version: O(1) — শুধু count, n; বাড়তি কিছু না।
  • log version: O(1)
  • str version: O(log n) — কারণ পুরো string-টা মেমরিতে তৈরি হয়।

interview-তে সাধারণত loop version-ই বলবে: O(log n) time, O(1) space।

17. Common mistakes

  1. n = 0 ভুলে যাওয়া — এই problem-এর এক নম্বর ফাঁদ। খালি loop 0-এর জন্য 0 ফেরত দেয়, কিন্তু সঠিক উত্তর 1। আগে if n == 0: return 1 বসাও।
  2. n //= 10 ভুলে যাওয়া — তাহলে while n > 0 কখনো থামবে না → infinite loop।
  3. log10-এর floating-point ফাঁদmath.log10(1000) যদি কোনো সিস্টেমে 2.9999999 আসে, floor দিয়ে 2 হয়ে উত্তর ভুল (3) হয়ে যাবে। বড় power-of-10-এ ঝুঁকি থাকে; নিরাপদ থাকতে loop বা len(str(n)) ব্যবহার করো।
  4. negative ভুলে যাওয়াabs() না নিলে -55-এ loop চলবে না (while n > 0 মিথ্যা)।
  5. count যোগ আর digit যোগ গুলিয়ে ফেলা — এটা sum (002) নয়; এখানে count += 1, কখনোই count += n % 10 নয়।

18. Harder problems that inherit this idea

  • 009 — Power of 10 Check (এই repo) — বারবার // 10 করে দেখা সংখ্যাটা ঠিক 10-এর power কিনা; digit গোনার peeling loop-এরই আত্মীয়।
  • LeetCode — Add Digits (https://leetcode.com/problems/add-digits/) — digit নিয়ে কাজ; digit গোনা/যোগ করার একই extraction ভিত্তি।
  • LeetCode — Nth Digit (https://leetcode.com/problems/nth-digit/) — এখানে "কোন সংখ্যায় কয়টা digit" হিসাব করেই ঠিক করতে হয় n-তম digit কোথায় — digit counting-এর সরাসরি প্রয়োগ।

19. Pattern learned

একই extraction loop, কাজটা বদলাও। 002-এ digit যোগ করেছিলাম, 003-এ digit গুনলাম — loop এক, শুধু ভেতরের এক লাইন আলাদা। সাথে দুটো করে শেখা: (১) প্রায়ই একই কাজ loop, string, বা formula — তিন রাস্তায় করা যায়; (২) edge case (এখানে n = 0) আগে ভাবলে interview-তে ছোট ভুলে বড় দাম দিতে হয় না।

20. Final summary

ভবিষ্যতের আমাকে এক লাইনে: "count digits = 002-এর peeling loop, শুধু count += 1; n = 0 হলে আলাদা করে 1 ফেরাও। চাইলে len(str(n)) বা floor(log10 n)+1-ও চলে — কিন্তু loop সবচেয়ে নিরাপদ।"

আগের ধাপ → 002 — Sum of Digits (যেখান থেকে এই loop পেলাম)। শিকড়ে → 001 — Even or Odd। পরের আত্মীয় → 009 — Power of 10 Check

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

21. JavaScript solution (with test cases)

function countDigits(n) {
  n = Math.abs(n);
  if (n === 0) return 1;       // edge case: 0-এরও একটা digit
  let count = 0;
  while (n > 0) {
    count++;
    n = Math.floor(n / 10);
  }
  return count;
}

// O(1) বিকল্প (n > 0): Math.floor(Math.log10(Math.abs(n))) + 1
// ⚠️ খুব বড় সংখ্যায় floating-point error দিতে পারে, তাই loop নিরাপদ।

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

// ---- test cases ----
assert(countDigits(1234) === 4, "1234");
assert(countDigits(0) === 1, "0 -> 1");   // সবচেয়ে দামি case
assert(countDigits(1000) === 4, "1000");
assert(countDigits(-55) === 2, "-55");
console.log("সব JS test pass!");

JS টীকা: 0-এর জন্য আলাদা return 1 না দিলে loop একবারও চলবে না আর ভুল করে 0 ফেরত আসবে। log10 দিয়ে O(1)-তে করা যায়, কিন্তু বড় সংখ্যায় floating-point precision হারায় — তাই interview-তে loop version নিরাপদ choice।

22. TypeScript solution (with test cases)

function countDigits(n: number): number {
  n = Math.abs(n);
  if (n === 0) return 1;
  let count = 0;
  while (n > 0) {
    count++;
    n = Math.trunc(n / 10);
  }
  return count;
}

const cases: ReadonlyArray<readonly [number, number]> = [
  [1234, 4], [0, 1], [1000, 4], [-55, 2],
];
for (const [input, want] of cases) {
  if (countDigits(input) !== want) throw new Error(`FAIL ${input}`);
}
console.log("সব TS test pass!");

TS টীকা: edge case (0 -> 1) test table-এ স্পষ্ট রাখা হলো — high-end code-এ "tricky edge গুলো test-এ লেখা থাকে যাতে refactor-এ ভুল হলে সাথে সাথে ধরা পড়ে"। এটাই regression test-এর মূল ভাবনা।

23. কোথায় কাজে লাগে (real-world use)

Digit count (সংখ্যার দৈর্ঘ্য) বাস্তবে যেখানে লাগে:

  • Input validation: phone number, card, PIN, OTP-এর দৈর্ঘ্য ঠিক আছে কিনা যাচাই।
  • Fixed-width display / padding: number-কে ডানে align বা leading-zero pad করতে কত digit জানা দরকার (invoice, receipt, ID)।
  • Pagination / layout: কত digit-এর page number, সেই অনুযায়ী column width।
  • Axis scaling: chart-এ tick/label-এর জন্য মান কত "বড়" (log10 ≈ digit count) বুঝে scale।
  • Storage estimation: ID/counter কত digit হবে → কত byte/column width লাগবে database schema-তে।

মূল idea: একটা সংখ্যার digit সংখ্যা ≈ log₁₀(n) — এই log-নির্ভর "আকার" intuition scaling, complexity, capacity planning সবখানে ফিরে আসে।


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