برنامه دنباله فیبوناچی در پایتون

➌ حالا بر روی گوشه پایینی سلولا A3 کلیک کنید و آن را به سمت پایین بکشید. اصطلاحاً از روش Fill Handle استفاده کنید. نتیجه این می شود که سری فیبوناچی در اکسل تشکیل می شود.
درک عملکرد تابع بازگشتی با پایتون
در این مطلب، می خواهیم ضمن توضیح مفهوم و ساختار تابع بازگشتی، چند تابع بازگشتی مختلف برنامه دنباله فیبوناچی در پایتون و ساده در زبان پایتون را ببینیم تا درک کنیم یک راه حل بازگشتی چگونه کار می کند.
مقدمه
در حین برنامه نویسی زمانی که می خواهیم بخشی از کد که کار مشخصی انجام می دهد را بارها تکرار کنیم، معمولاً به حلقه های for و while فکر می کنیم. این حلقه ها به ما کمک می کنند تا امکان تکرار کاری روی یک لیست یا مجموعه و یا تا رسیدن به شرایط خاصی را داشته باشیم.
با این حال، ساختار دیگری برای تکرار یک کار هم وجود دارد که اندکی متفاوت از حلقه هاست. با صدا زدن یک تابع درون خودش، مثلاً برای حل بخش کوچک تری از همان مسئله، ما در واقع داریم عملی بازگشتی انجام می دهیم.
توابع بازگشتی خود را آن قدر صدا می زنند تا مسئله حل شود به نقطه پایانی برسد، به طور مثال مرتب کردن یک آرایه در الگوریتم مرتب سازی ادغامی، که در آن آرایه تا حد رسیدن به تنها یک عنصر به طور مداوم شکسته می شود.
یک مثال ساده تر و انسانی تر، عملکرد ما حین خوردن یک پیتزاست. شما شروع به تقسیم پیتزا از وسط می کنید و هر دفعه آن را از وسط به دو نیمه تقسیم می کنید. در ضمن هر بار هم بررسی می کنید که آیا اندازه فعلی به کوچکی یک لقمه شده است یا نه.
تابع بازگشتی چیست؟
همانطور که در بخش مقدمه گفته شد، تابع بازگشتی پردازه ای است که در درون تعریفش خود را می تواند صدا بزند و باعث تکرار اجرای کدهای خود شود.
به طور کلی می توان گفت که تابع بازگشتی دو بخش اصلی دارد:
- حالت پایه و پایانی، که در واقع شرطی است که مشخص می کند فراخوانی های تکراری بازگشتی کجا باید خاتمه پیدا کنند.
- بخش فراخوانی خود.
بیایید یک مثال کوچک ببینیم تا این دو بخش را در عمل ببینیم:
اینجا حالت پایه برای ما زمانی اتفاق می افتد که متغیر remaining برابر با صفر شود. به برنامه دنباله فیبوناچی در پایتون این صورت که این متغیر تعداد رشته های “hi” که باید چاپ شوند را مشخص می کند. در صورتی که حالت پایه رخ دهد، تابع فقط به فراخوانی قبل باز می گردد و چیز خاصی چاپ نمی کند.
همانطور که می بینید، بعد از دستور print ما مجدداً تابع hi_recursive را صدا می زنیم، اما این بار آرگومان آن یکی کمتر می شود.
این خیلی مهم است که شما فراخوانی تکراری و بازگشتی را با همان ورودی یا همان مسئله فعلی انجام ندهید و ورودی را تغییر دهید. وگرنه در تکراری بی نهایت گیر خواهید کرد و هیچ موقع حالت پایه یا پایانی اتفاق نخواهد افتاد.
پس بهتر است در خاطر داشته باشید که زمان طراحی تابع بازگشتی، باید تغییرات ورودی برای فراخوانی بعدی را طور در نظر بگیرید که:
- اولاً مشابه نباشد و تغییر کرده باشد،
- دوماً این تغییر به سمت نزدیک شدن به حالت پایه پیش برود تا بتوان اطمینان حاصل کرد که اجراهای بازگشتی به تکرار بی نهایت دچار نشود.
بیایید نگاهی به زنجیره اجرای بازگشتی تابع بالا با ورودی ۳ داشته باشیم.
هر بار پس از اینکه تابع رشته “hi” را چاپ می کند، خودش را با مقدار یکی کمتر از remaining فعلی، دوباره فراخوانی می کند تا اینکه بالاخره مقدار آرگومان به صفر برسد. در مقدار صفر، با دستور return تابع به فراخوانی قبلی بر می گردد. این فراخوانی ها هم به طور زنجیره ای برنامه دنباله فیبوناچی در پایتون به اولین مرحله باز می گردند.
چرا حلقه به جای بازگشتی استفاده نکنیم؟
همه این کارهای تکراری را می توان با همان حلقه ها هم انجام داد. اما راستش را که بخواهید، یک سری مسائل هستند که با راه حل تابع بازگشتی راحت تر حل می شوند.
یک استفاده معمول از بازگشتی ها، پیمایش درخت و گراف است:
زمانی که به طور بازگشتی پیمایش گره ها و یال های یک درخت را انجام می دهیم، معمولاً راحت تر می توانیم اتفاقات را درون ذهنمان تصور کنیم. اگر چه حلقه برنامه دنباله فیبوناچی در پایتون ها و بازگشتی هر دو درخت را پیمایش می کنند، اما این دو دسته روش اهداف مختلفی دارند. معمولاً کاربرد حلقه ها برای تکرار یک وظیفه است در حالی که بازگشتی بیشتر برای شکستن و ریز کرد یک کار بزرگ به بخش های کوچک تر کاربرد دارد.
ترکیب بازگشتی با درخت ها، به ما کمک می کند تا پردازش/پیمایش کل درخت را با پردازش جداگانه بخش های مختلف آن تکمیل کنیم و به پایان برسانیم.
مثال هایی از تابع بازگشتی
بهترین راه برای دستیابی به مفهوم بازگشتی و پیدا کردن احساس تسلط و راحتی بر آن، یا هر مفهوم برنامه نویسی دیگر، تمرین کردن است. با همین دید ساده شروع کنید: اطمینان حاصل کنید که حالت پایه و پایانی را در نظر گرفته اید و در هر بار فراخوانی بازگشتی داخلی، سعی کرده اید که به حالت پایه نزدیک تر شوید. به همین سادگی.
ما سعی می کنیم با تعدادی مثال همین دید ساده را به کار بگیریم و چند تابع بازگشتی بنویسیم تا سرآغازی برای تمرینات شخصی شما باشد.
مجموع اعداد داخل لیست به روش بازگشتی
می خواهیم یک تابع بازگشتی داشته باشیم که اعضای لیست را با هم جمع بزند. اعضای لیست می تواند عدد یا رشته یا هر شئ دیگری باشد که عملگر جمع برای آن تعریف شده است.
چگونگی ایجاد دنباله فیبوناچی (Fibonacci sequence) در اکسل
ایجاد انواع دنباله ها (sequences) در اکسل کار ساده ای می باشد. برای مثال در این آموزش به چگونگی ایجاد دنباله فیبوناچی (Fibonacci sequence) در اکسل می پردازیم.
➊ دو عدد اول در دنباله فیبوناچی (Fibonacci sequence) اعداد 0 و 1 می باشند.
➋ در دنباله فیبوناچی (Fibonacci sequence) اعداد بعدی دنباله را می توان با محاسبه مجموع دو عدد قبلی آن به دست آورد.
➌ حالا بر روی گوشه پایینی سلولا A3 کلیک کنید و آن را به سمت پایین بکشید. اصطلاحاً از روش Fill Handle استفاده کنید. نتیجه این می شود که سری فیبوناچی در اکسل تشکیل می شود.
توجه: برای کسب اطلاعات بیشتر در مورد Fill Handle می توانید این آموزش را بخوانید: معرفی فرمول ها در اکسل 2016
توجه: در اینجا می توانید آموزش جامع و کامل اکسل 2016 از مبتدی تا پیشرفته را بیابید: دوره رایگان آموزش جامع اکسل 2016 از مقدماتی تا پیشرفته
جلسه ۲۶: Recursion در پایتون
در این درس به جنبه های موضوع بازگشت یا Recursion در پایتون میپردازیم.
تعریف
Recursion یعنی اینکه ما یک تابع را درون خودش دوباره فرخوانی کنیم و اجرا بشود. هر فراخوانی recursive باعث میشود یک Scope درون تابع داخل تر برویم.
فراخوانی های بازگشتی، در حالتی به اسم حالت پایه متوقف میشوند. حالت پایه یک آزمون است، که برای نشان دادن اینکه دیگر هیچ بازگشتی وجود ندارد، استفاده میشود.
هر فراخوانی بازگشتی را به صورت یک جعبه فرض کنید که هر جعبه نشان دهنده یک فراخوانی تابع نیز است. هر فراخوانی بازگشتی جدید یک جعبه دیگر میسازد. وقتی که به حالت پایه برسیم یکی یکی از جعبه ها به سمت بیرون حرکت میکنیم.
در شکلهای بالا میبینید که یک تابع به تعداد مشخص برنامه دنباله فیبوناچی در پایتون مرتبا فراخوانی میشود.
یک مثال ساده
حال یک برنامهای مینویسیم که یک عدد را مرتبا یکی کم کند تا زمانی که به صفر برسد.
درک این موضوع نسبتا آسان است.برنامه دنباله فیبوناچی در پایتون
در هر فراخوانی مقدار متغیر number چاپ میگردد. سپس ما چک میکنیم که حالت پایه ما آیا اتفاق افتاده است یانه. اگر جواب نه بود، دوباره تابع را فراخوانی میکنیم اما اینبار با ورودی یکی کمتر از قبلی.
یک نکته مهم هم وجود دارد اینکه یک فراخوانی بیرونی، عملی انجام نمیدهد تا زمانی که فراخوانی درونی به اتمام برسد. به همین دلیل هم هست که توالی ما از ۵ تا ۰ و دوباره از ۰ تا ۵ اتفاق افتاده است.
چرا از Recursion استفاده کنیم؟
Recursive مفهومی است که درک آن در ابتدا میتواند مشکل باشد.اما مزایای خودش را هم دارد. برای شروع این روش میتواند زمان اجرای یکسری الگوریتمها را کاهش دهد که باعث میشود کدهای شما کارایی بالاتری داشته باشد.
recursive ها این امکان را به ما میدهند تا مسائلی نظیر، گراف ها و درخت ها را حل کنیم اینها مسائلی هستند که در برنامه دنباله فیبوناچی در پایتون برنامه دنباله فیبوناچی در پایتون آینده آن ها را یاد خواهیم گرفت. این روش در الگوریتم های جستوجو نیز بسیار با اهمیت هستند.
اما در استفاده از Recursion باید مراقب باشیم. اگر ما محل حالت پایه را مشخص نکنیم یا آرگومان ها را موقع فراخوانی آپدیت نکنیم، برنامه به یک حالت بینهایت میرود و موجب کرش کردن برنامه میشود. آرگومان هایی که به تابع بازگشتی میدهیم در هر بازگشت آپدیت میشوند تا زمانی که به حالت پایه برسیم.
یک مثال پیچیده
سری فیبوناچی یکی از محبوب ترین سری های ریاضی هستند. که هر برنامه دنباله فیبوناچی در پایتون عدد از جمع دو عدد ماقبل خودش ساخته میشود. دو عضو اول این سری همیشه ۰ و ۱ خواهند بود.
حال یک کدی را مینویسیم که ورودی ای به نام n را میگیرد و nامین عضو یک دنباله فیبوناچی را محاسبه میکند. این نکته هم مهم است که در مثال پیش رو اگر ورودی کمتر از ۱ باشد محاسبه ای انجام نمیشود. پس ورودی ما بزرگتر از ۱ خواهد بود. بنابراین اگر n=6 انتخاب شد، این تابع خروجی ۵ را به ما میدهد.
اول از همه ما حالت پایه خودمان را مشخص میکنیم. میدانیم که دو مقدار اول همیشه ۰ و ۱ هستند بنابراین اینجا جاییست که میتوان بازگشت را متوقف کرد و این جا به عنوان حالت پایه در نظر گرفته میشود.
اگر n از ۲ بزرگتر باشد، این تابع باید دو مقدار ماقبل n را محاسبه کند.
اکنون به انتهای مطالب مربوط به توابع در پایتون میرسیم. ما اکنون ابزارهایی را در اختیار داریم که میتوانیم برنامه های پیشرفتهای را بنویسیم.
در بخش بعدی به بررسی loop ها در پایتون میپردازیم. اما قبل از آن کوییز های مربوط به این بخش را انجام دهید.
منزلگه ققنوس
یکی از روشهای پرکاربرد و مشهور طراحی الگوریتم روش برنامهنویسی پویا (یا برنامهریزی پویا - Dynamic Programming) است. این روش همچون روش تقسیم و حل (Divide and Conquer) بر پایه تقسیم مساله بر زیرمسالهها کار میکند. اما تفاوتهای چشمگیری با آن دارد.
زمانی که یک مساله به دو یا چند زیرمساله تقسیم میشود، دو حالت ممکن است پیش بیاید:
1- دادههای زیرمسالهها هیچ اشتراکی با هم نداشته و کاملا مستقل از هم هستند. نمونه چنین مواردی مرتبسازی آرایهها با روش ادغام یا روش سریع است که دادهها به دو قسمت تقسیم شده و به صورت مجزا مرتب میشوند. در این حالت دادههای یکی از بخشها هیچ ارتباطی با دادههای بخش دیگر نداشته و در نتیجه حاصل از آن بخش اثری ندارند. معمولا روش تقسیم و حل برای چنین مسائلی کارآیی خوبی دارد.
2- دادههای زیرمساله وابسته به هم بوده و یا با هم اشتراک دارند. در این حالت به اصطلاح زیرمسالهها همپوشانی دارند. نمونه بارز چنین مسائلی محاسبه جمله nام دنباله اعداد فیبوناچی است.
دنباله اعداد فیبوناچی (فیبوناتچی)
دنباله اعداد فیبوناچی (Fibonacci) یکی از دنبالههای عددی مشهور ریاضیات با تعریف بازگشتی زیر است:
F( n ) = F( n - 1 ) + F( n - 2 ) n > 2 , F( 1 ) = F( 2 ) = 1
محاسبه جمله nام دنباله به محاسبه دو جمله قبلی آن نیاز دارد. پس میتوان گفت محاسبه ( F( n - 1 و ( F( n - 2 دو زیر مساله برای مساله اصلی هستند. اما در عین حال این دو زیرمساله از هم مستقل نیستند. برای محاسبه ( F( n - 1 بر اساس رابطه بالا باید داشته باشیم:
F( n - 1 ) = F( n - 2 ) + F( n - 3 )
که نشان میدهد خود ( F( n - 1 وابسته به ( F( n - 2 است.
اگر این مساله را به روش تقسیم برنامه دنباله فیبوناچی در پایتون برنامه دنباله فیبوناچی در پایتون و حل - که سادهترین روش است - حل کنیم:
int fibo( int n )
if( n > 2 )
return ( fibo( n - 1) + fibo( n - 2 ) );
return 1;
تابع fibo مقدار n را دریافت کرده و به صورت بازگشتی و بر اساس رابطه ذکر شده، جمله nام دنباله فیبوناچی را محاسبه میکند. حال درخت فراخوانیهای بازگشتی تابع را به ازای n = 7 رسم میکنیم:
هر گره درخت، فراخوانی تابع را با مقدار داخل آن نشان میدهد. برای محاسبه جمله هفتم دنباله فیبوناچی تابع fibo به صورت ( fibo( 7 فراخوانی میشود، که آن هم ( fibo( 6 و ( fibo( 5 را فراخوانی میکند و الی آخر. همانطور که مشاهده میکنید، برای محاسبه این جمله، ( fibo( 7 یک بار، ( fibo( 6 یک بار، ( fibo( 5 دو بار، ( fibo( 4 سه بار، ( fibo( 3 پنج بار، ( fibo( 2 هشت بار، ( fibo( 1 پنج بار، و روی هم رفته تابع fibo بیست و پنج بار فراخوانی میشود.
ما خود چگونه جملات دنباله فیبوناچی را محاسبه میکنیم؟ ابتدا جمله اول و دوم را جمع زده و جمله سوم را محاسبه میکنیم. سپس با استفاده از جمله به دست آمده و جمله دوم، جمله چهارم را محاسبه میکنیم و همینطور ادامه میدهیم:
1 1 2 3 5( = 3 + 2 )
1 1 2 3 5 8( = 5 + 3 )
1 1 2 3 5 8 13( = 8 + 5 )
و به این ترتیب جمله هفتم دنباله تنها با پنج محاسبه ساده به دست میآید. در حالت کلی با استفاده از این روش تنها به n - 2 عمل جمع نیاز است که نشان از الگوریتمی با مرتبه خطی دارد. در حالی که میتوان ثابت کرد در حالت اول تعداد کل فراخوانیهای بازگشتی تابع از مرتبه نمایی است. دلیل اختلاف این دو عدد در این است که در حالت دوم، هر جمله دنباله فقط و فقط یک بار محاسبه میشود. این همان روش برنامهنویسی پویا است.
در برنامهنویسی پویا مساله به صورت جزء به کل حل میشود. یعنی ابتدا زیر مسائل خرد حل شده و نتیجه آنها در مکانی دخیره میشود. سپس به سمت زیرمسائل کلیتر رفته و با استفاده از دادههای از پیش محاسبه شده، آنها نیز حل میشوند. در مورد دنباله فیبوناچی میتوان نوشت:
int fibo( int n )
int f[ MAX ], i;
for( i = 3 ; i
f[ i ] = f[ i - 1 ] + f[ i - 2 ];
return f[ n ];
در این روش ما جملات دنبالهها را پس از محاسبه در یک آرایه ذخیره میکنیم. برای این کار به جای حرکت از کل به جزء (یعنی از n به 1، که در روش تقسیم و حل استفاده میشود)، از جزء به سمت کل حرکت میکنیم. هر جمله دنباله تنها به دو جمله قبل خود نیاز دارد، که با حرکت جزء به کل قبلا محاسبه شدهاند و نیاز به محاسبه مجدد آنها نیست. البته این کد را میتوان سادهتر کرد:
int fibo( int n )
int i, f1, f2, f3;
for( i = 3 ; i
return f3;
تحلیل این تابع ساده را به خود شما وا میگذارم.
نکته مهم این است که اگر زیرمسالهها همپوشانی نداشته باشند روش برنامهنویسی پویا هیچ کمکی به ما نخواهد کرد. چرا که خاصیت اصلی این روش ذخیره دادههایی است که ممکن است به کرات به آنها مراجعه شود. حال اگر هیچ اشتراکی در کار نباشد، طبیعتا از هر داده تنها یک بار استفاده خواهد شد.
برنامهنویسی پویا برای طراحی الگوریتمهای محاسبه حالتهای بهینه مسائل نیز کاربرد زیادی دارد. به عنوان مثال در یافتن کوتاهترین مسیر بین دو نقطه، محاسبه بهینهترین حالت ضرب زنجیری ماتریسها، درخت جستجوی بهینه، مساله فروشنده دورهگرد، محاسبه ضرب چندجملهایها، مساله کولهپشتی صفر و یک، و چندین مساله دیگر، از برنامهنویسی پویا استفاده میشود. شرط اساسی امکان استفاده از این روش برای محاسبه حالت بهینه به اصل بهینگی مشهور است.
اصل بهینگی: اصل بهینگی یعنی حل مساله به صورت بهینه، حاوی حل بهینه تمامی زیرمسائل آن نیز باشد.
به عبارت دیگر، مساله باید به گونهای باشد که با یافتن حل بهینه آن، حل بهینه همه زیرمسالهها نیز به دست آمده باشد. به عنوان مثال، در یافتن کوتاهترین مسیر بین دو شهر، مسیر بین مبدا و هر گرهی که در مسیر بهینه وجود دارد، بهینهترین مسیر بین آن دو نیز هست.
مرجع تخصصی برنامه نویسان
چطور به صورت ستونی کنار هم پاراگراف درج کنم؟
ایجاد Relation یک جدول با دوستون در یک جدول دیگر در EF
واریز وجه به حساب مدرسین سایت
دستور Asserion توی سوال زیر داره چی رو چک میکنه؟
انجام یک restful http هر 5 دقیقه
استفاده از localStrorage
طراحی سبد خرید
طراحی سبد خرید
استفاده از الگوی Unit of work و Repository در برنامه نویسی ویندوز
نحوه درج پاراگراف سمت راست عکس
کتاب آموزش فارسی برنامه نویسی اندروید از مبتدی تا پیشرفته
کتاب فارسی آموزش بوت استرپ 3 (BootStrap)
آموزش ایجاد و مدیریت ربات در تلگرام با زبان سی شارپ
دانلود کتاب آموزش برنامه نویسی پیشرفته سی شارپ به زبان فارسی
سورس کد انجمن با استفاده از Asp.net 4.5 - Entity FrmaeWork - Asp.net Web Api - Asp.net Identity-Kendo ui
کتاب آموزش ASP.Net MVC 5 به زبان فارسی
آموزش MVC به زبان فارسی (نوشته شده توسط آقای وحید نصیری)
دانلود نرم افزار مدیریت داروخانه + سورس + بانک
کتاب آموزش کامل برنامه نویسی اندروید به زبان فارسی
سورس پروژه مدیریت داروخانه به زبان سی شارپ
اگر نیاز به یک مشاور در زمینه طراحی سایت ، برنامه نویسی و بازاریابی الکترونیکی دارید
با ما تماس بگیرید تا در این مسیر همراهتان باشیم :)
- خیابان شریعتی - خیابان ملک - بنبست ایرانیاد - پلاک 1
- تلفن تماس : 02188455865
کلیه حقوق مادی و معنوی برای مجموعه برنامه نویسان محفوظ می باشد . هر گونه کپی برداری از محتوای آموزشی با ذکر منبع مجاز می باشد.