حلقههای تودرتو و الگوها
وقتی یک حلقه داخل حلقه دیگر میگذارید، از خط به صفحه میرسید. این فصل تمرین محض است: کشیدن شکل با ستاره، که ساده به نظر میرسد ولی بهترین راه برای اینکه حلقه واقعاً در ذهنتان جا بیفتد.
۱. حلقه داخل حلقه
قانون طلایی این فصل یک جمله است: حلقه داخلی برای هر یک دور حلقه بیرونی، از اول تا آخر کامل اجرا میشود.
# The inner loop runs from start to end for EVERY single turn of the outer loop.
# 3 outer turns x 4 inner turns = 12 lines.
for i in range(3):
for j in range(4):
print(f'i={i}, j={j}')
print('--- end of one outer turn ---')
اولین حلقه تودرتو: نمونه 01_first_nested_loop.py
i=0, j=0 i=0, j=1 i=0, j=2 i=0, j=3 --- end of one outer turn --- i=1, j=0 i=1, j=1 i=1, j=2 i=1, j=3 --- end of one outer turn --- i=2, j=0 i=2, j=1 i=2, j=2 i=2, j=3 --- end of one outer turn ---
شرح مثال
- حلقه بیرونی سه بار میچرخد، حلقه داخلی چهار بار. مجموع اجرای بدنه داخلی: سه ضربدر چهار، یعنی دوازده بار.
- متغیر
iکند حرکت میکند وjتند. برای هر مقدارi، تمام مقدارهایjطی میشوند. - خط آخر داخل حلقه بیرونی است ولی بیرون حلقه داخلی، پس فقط سه بار اجرا میشود. تورفتگی است که این را مشخص میکند.
به عقربههای ساعت فکر کنید. عقربه ساعتشمار حلقه بیرونی است و دقیقهشمار حلقه داخلی. برای هر یک ساعت، دقیقهشمار یک دور کامل ۶۰ تایی میزند.
۲. مستطیل ستاره
از اینجا به بعد یک الگوی ثابت داریم: حلقه بیرونی
سطرها را میشمارد و حلقه داخلی ستونها
را. کلید کار، دو تا print است.
# A rectangle of stars: the outer loop counts the rows,
# the inner loop prints the characters of one row.
ROWS = 4
COLUMNS = 8
for row in range(ROWS):
for column in range(COLUMNS):
# end='' keeps the cursor on the same line
print('*', end=' ')
# this print() ends the current line and starts a new one
print()
مستطیل: نمونه 02_rectangle.py
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
شرح مثال
print('*', end=' ')ستاره را چاپ میکند و روی همان خط میماند. بدونend، هر ستاره یک خط جدا میگرفت.print()خالی بعد از حلقه داخلی، سطر را میبندد. این خط حتماً باید بیرون حلقه داخلی و داخل حلقه بیرونی باشد.- اگر شکل شما به هم ریخت، اولین چیزی که باید چک کنید تورفتگی همین
print()خالی است.
۳. جدول ضرب
# The multiplication table of the numbers 1..n
user_input = input('Enter a number: ')
n = int(user_input)
for i in range(1, n + 1):
for j in range(1, n + 1):
print(i * j, end='\t') # \t keeps the columns aligned
print()
جدول ضرب: نمونه 03_multiplication_table.py
Enter a number: 5 1 2 3 4 5 2 4 6 8 10 3 6 9 12 15 4 8 12 16 20 5 10 15 20 25
اینجا مقدار چاپشده به هر دو متغیر حلقه بستگی دارد:
i * j. این تفاوت جدول ضرب با مستطیل ساده است. کاراکتر تب
ستونها را مرتب نگه میدارد.
۴. مثلث رشدیابنده
برای مثلث، تعداد ستارههای هر سطر باید متفاوت باشد. یعنی حلقه داخلی
نباید عدد ثابت داشته باشد، بلکه باید به i وابسته باشد.
# Row 0 gets 0 stars, row 1 gets 1 star, row 2 gets 2 stars ...
# Version 1: the inner loop simply runs 'i' times. This is the clean way.
for i in range(5):
for j in range(i):
print('*', end=' ')
print()
print('---')
# Version 2: the inner loop always runs 5 times but only prints when i > j.
# It gives the same drawing; it just does more useless turns.
for i in range(5):
for j in range(5):
if i > j:
print('*', end=' ')
print()
مثلث چپچین، دو روش: نمونه 04_left_triangle.py
* * * * * * * * * *
شرح مثال
- روش اول:
range(i)یعنی حلقه داخلی به اندازه شماره سطر میچرخد. سطر صفر هیچ ستارهای ندارد، سطر یک، یک ستاره و همینطور تا آخر. - روش دوم: حلقه داخلی همیشه پنج بار میچرخد ولی فقط وقتی
i > jباشد چیزی چاپ میکند. نتیجه یکی است ولی نصف دورها بیفایدهاند. - هر دو نسخه در فایل نمونه آمدهاند تا مقایسه کنید. در برنامه واقعی روش اول را انتخاب کنید: هم سریعتر است و هم قصد نویسنده را روشنتر بیان میکند.
۵. مثلث نزولی
# A triangle that shrinks: 5 stars, then 4, then 3 ...
SIZE = 5
for i in range(SIZE, 0, -1):
for j in range(i):
print('*', end=' ')
print()
print('---')
# The same shape written with a condition instead of a counting-down range.
for i in range(SIZE):
for j in range(SIZE):
if i <= j:
print('*', end=' ')
print()
مثلث نزولی: نمونه 05_reverse_triangle.py
* * * * * * * * * * * * * * *
روش اول از گام منفی استفاده میکند: range(5, 0, -1) یعنی ۵ و
۴ و ۳ و ۲ و ۱. روش دوم همان شکل را با شرط میسازد.
۶. مثلث راستچین
برای اینکه ستارهها به سمت راست هل داده شوند، باید پیش از آنها فاصله چاپ کنیم. فاصله هم یک کاراکتر است و جا اشغال میکند.
# To push the stars to the right we print SPACES first.
# Row i gets (SIZE - 1 - i) spaces and (i + 1) stars.
SIZE = 5
for i in range(SIZE):
for j in range(SIZE):
if j < SIZE - 1 - i:
print(' ', end=' ') # a space keeps the column width
else:
print('*', end=' ')
print()
مثلث راستچین: نمونه 06_right_aligned_triangle.py
*
* *
* * *
* * * *
* * * * *
فرمول SIZE - 1 - i تعداد فاصلههای هر سطر را میدهد. سطر
صفر چهار فاصله دارد، سطر آخر هیچ. اگر این فرمول را نمیفهمید، روی کاغذ
یک جدول پنج سطری بکشید و برای هر سطر تعداد فاصله و ستاره را بنویسید. کل
هنر مسائل الگو همین است.
۷. هرم
# A centred pyramid: row i has (SIZE - 1 - i) leading spaces
# and (2 * i + 1) stars.
SIZE = 5
for i in range(SIZE):
for space in range(SIZE - 1 - i):
print(' ', end='')
for star in range(2 * i + 1):
print('*', end='')
print()
print('---')
# The same pyramid in one line per row, using string repetition.
for i in range(SIZE):
print(' ' * (SIZE - 1 - i) + '*' * (2 * i + 1))
هرم، دو روش: نمونه 07_pyramid.py
* *** ***** ******* *********
شرح مثال
- در هر سطر دو حلقه داخلی پشت سر هم داریم: یکی برای فاصلهها و یکی برای ستارهها. این کاملاً مجاز است.
- تعداد ستارهها
2 * i + 1است، یعنی همیشه فرد: ۱ و ۳ و ۵ و ۷ و ۹. برای همین هرم قرینه در میآید. - نسخه دوم همان شکل را با تکرار رشته میسازد:
' ' * nیعنی n فاصله. یک خط به جای چهار خط، و کاملاً خواناتر. این نمونه خوبی است از اینکه دانستن ابزار درست، کد را کوتاه میکند.
۸. مثلث عددی
# Instead of a star we can print the value of the inner counter.
SIZE = 6
for i in range(1, SIZE + 1):
for j in range(1, i + 1):
print(j, end=' ')
print()
print('---')
# And here the row number is repeated instead.
for i in range(1, SIZE + 1):
for j in range(1, i + 1):
print(i, end=' ')
print()
مثلث عددی: نمونه 08_number_triangle.py
1 1 2 1 2 3 1 2 3 4 1 2 3 4 5 1 2 3 4 5 6 --- 1 2 2 3 3 3 4 4 4 4 5 5 5 5 5 6 6 6 6 6 6
تنها تفاوت دو نسخه این است که در اولی j چاپ میشود و در
دومی i. ساختار حلقهها کاملاً یکسان است. این نشان میدهد که
بعد از ساختن اسکلت حلقه، تغییر شکل خروجی کار سادهای است.
۹. صفحه شطرنج
# The character depends on both counters: when (row + column) is even we print
# one character, otherwise the other one.
SIZE = 8
for row in range(SIZE):
for column in range(SIZE):
if (row + column) % 2 == 0:
print('#', end=' ')
else:
print('.', end=' ')
print()
صفحه شطرنج: نمونه 09_chess_board.py
# . # . # . # . . # . # . # . # # . # . # . # . . # . # . # . #
ترفند اینجا ترکیب % فصل دوم با دو شمارنده است. مجموع شماره
سطر و ستون، یک در میان زوج و فرد میشود و همین الگوی شطرنجی را میسازد.
۱۰. قانون کلی حل مسائل الگو
هر مسئله الگو، هر قدر هم پیچیده به نظر برسد، با همین چهار قدم حل میشود:
- روی کاغذ بکشیدش. پیش از کد زدن، شکل نهایی را با دست رسم کنید.
- سطرها را بشمارید. این عدد، حلقه بیرونی شماست.
- برای هر سطر بپرسید چند فاصله و چند نویسه لازم است. یک جدول کوچک بسازید: شماره سطر، تعداد فاصله، تعداد ستاره.
-
رابطه آن ستونها با شماره سطر را پیدا کنید. این
رابطه، همان چیزی است که داخل
rangeحلقه داخلی مینویسید.
| سطر i | فاصله در هرم | ستاره در هرم |
|---|---|---|
| ۰ | ۴ | ۱ |
| ۱ | ۳ | ۳ |
| ۲ | ۲ | ۵ |
| ۳ | ۱ | ۷ |
| ۴ | ۰ | ۹ |
| رابطه | SIZE - 1 - i | 2 * i + 1 |
پوشه S07-nested-loops-and-patterns شامل نمونههای
01_first_nested_loop.py تا 09_chess_board.py.
خلاصه فصل
| مفهوم | توضیح |
|---|---|
| حلقه تودرتو | حلقه داخلی برای هر دور حلقه بیرونی کامل اجرا میشود |
| تعداد کل اجرا | حاصلضرب تعداد دورهای دو حلقه |
| حلقه بیرونی | سطرها |
| حلقه داخلی | ستونهای یک سطر |
end=' ' | ماندن روی همان خط |
print() خالی | بستن سطر. بیرون حلقه داخلی، داخل حلقه بیرونی |
range(i) | حلقه داخلی وابسته به شماره سطر، برای شکلهای مثلثی |
' ' * n | راه کوتاه ساختن n فاصله، بدون حلقه |
تمرینهای فصل هفت
- مربعی از ستاره به ابعاد
nدرnرسم کنید کهnرا کاربر میدهد. - مثلثی رسم کنید که اول بزرگ شود و بعد کوچک، یعنی یک لوزی.
- مربع توخالی رسم کنید: فقط لبهها ستاره باشند و داخلش خالی.
- جدول ضرب ۱ تا ۱۰ را با یک سطر عنوان در بالا چاپ کنید.
- همه زوجهای
(i, j)را چاپ کنید که در آنها1 <= i < j <= 5. - عدد
nرا بگیرید و همه جفتهای عددی کوچکتر ازnکه مجموعشانnمیشود را چاپ کنید. - مثلثی از حروف بسازید: سطر اول
A، سطر دومA B، سطر سومA B Cو همینطور ادامه.