زمانی که از یک برنامهنویس پایتونی بخواهید یک تابع ساده بنویسد تا ارقام یک عدد را جمع کند و برگرداند، احتمالاً ابتدا عدد را به یک رشته تبدیل میکند و سپس رشته را به لیست (فهرست) و نهایتاً تکتک اعضای لیست را که ارقام عدد به صورت رشتههای تکنویسهای هستند به عدد تبدیل میکند و سپس آنها را با هم جمع میکند. ولی الزاماً اولین روشی که برای حل مسئله به ذهنمان میرسد، بهترین روش نیست. در این مطلب دو الگوریتم برای جمع ارقام یک عدد صحیح به صورت بازگشتی و تکرارشونده به همراه کد های پایتون آن ها ارائه میدهم.
الگوریتم های تکرارشونده و بازگشتی
الگوریتم های تکرار شونده و بازگشتی تا حدودی شبیه هم هستن با این تفاوت که در حالت تکرار شونده تمام کار در یک حلقه تکرار انجام میشود اما در حالت بازگشتی تابع با شرطی خودش را صدا میزند و این کار را تا تغییر وضعیت شرط انجام میدهد. در ادامه هر دوی این روش ها را بررسی خواهیم کرد.
الگوریتم جمع ارقام
به عنوان مثال میخواهیم ارقام عدد ۱۲۳ را با هم جمع کنیم و به ۶ برسیم. اولین چیزی که ذهن میرسد این است که چطور تکتک ارقام را از عدد بیرون بکشیم. اگر باقیماندهٔ تقسیم عدد بر ۱۰ را به دست آوریم، در واقع رقم یکان که ۳ باشد را به دست آوردهایم. حال اگر عدد ۱۲۳ را به ۱۰ تقسیم کنیم و تنها قسمت صحیح آن را نگه داریم (یا در زبانهایی که از تقسیم صحیح پشتیبانی میکنند، یک تقسیم صحیح انجام دهیم)، رقمهای بعدی یعنی ۱۲ به دست میآید. حال با تکرار این فرایند تا زمانی که به عددی کوچکتر از ۱۰ برسیم، میتوانیم یکانهای جدا شده در هر دور را با هم جمع کنیم و مثلا برای ۱۲۳ به نتیجه ۶ برسیم.
روش تکرار شونده
def digit_sum(a:int):
s = 0
while a>0:
s += a%10
a //= 10
return s
توضیح کد:
برای پیادهسازی الگوریتم تکرارشونده نیازی به تعریف تابع نیست. عدد را در متغیر a
در ورودی تابع میگیریم، برای ذخیره حاصل جمع متغیر s را ایجاد می کنیم و یک حلقه تکرار تا زمانی که a بزرگ تر از صفر باشد ایجاد میکنیم. در حلقه هر بار s را با یکان (باقیمانده تقسیم a بر ۱۰) جمع میکنیم. سپس حاصل تقسیم صحیح a بر ۱۰ را در خودش ذخیره میکنیم (کد a = a//10
خلاصه میشه و مینویسیم a //= 10
) در نهایت هم زمانی که تمام جمع ها انجام شد و a مساوی (یا کوچکتر!) از ۰ شد حاصل جمع را بر میگردونیم.
روش بازگشتی
def digit_sum(a: int, b: int=0) -> int:
# print(f"{a=}, {b=}")
if a < 10:
return a + b
return digit_sum(a//10, a%10+b)
این تابع دو ورودی a
و b
میگیرد. ورودی b
نباید توسط کاربر داده شود و تنها برای استفاده توسط خود تابع است برای زمانی که خودش را صدا میزند. هر بار که تابع اجرا میشود اگر a از ۱۰ بزرگتر بود خودش را فراخوانی میکند و دو پارامتر به آن میفرستد، اولی حاصل تقسیم صحیح است که میشود همه ارقام جز یکان و پارامتر دوم حاصل جمع ارقام قبلی و یکان فعلی است (مثل همون s تو کد قبلی). همه توابع بازگشتی حتما باید یک شرط برای شکستن حلقه بازگشت داشته باشن، یعنی جایی که دیگه تابع خودش رو صدا نمیزنه. این شرط a < 10
هست که در اون زمان حاصل جمع تمام ارقام قبلی با آخرین رقم رو بدست میاره و بر میگردونه.
با قرار دادن یک جمله print
در ابتدای تابع (میتونید # رو بردارید) و اجرای تابع برای اعداد مختلف میتوانید طرز کار تابع را تماشا کنید.
سلام.اگر بخوایم b رو توی خود تابع تعریف کنیم یعنی همراه a تعریف نشه و تو ساختار تابع تعریف بشه چجوری میشه؟
سلام. اگر منظورت روش بازگشتی هست، میتونی یه تابع جدید تعریف کنی که درونش تابع فعلی تعریف و صدا زده میشه و فقط a رو قبول میکنه:
https://gist.github.com/farooqkz/01213040eae4b1cda64c4a2e44aaa02b