برنامه‌نویسی پایتون فهرست مطالب
فصل ۷

حلقه‌های تودرتو و الگوها

وقتی یک حلقه داخل حلقه دیگر می‌گذارید، از خط به صفحه می‌رسید. این فصل تمرین محض است: کشیدن شکل با ستاره، که ساده به نظر می‌رسد ولی بهترین راه برای اینکه حلقه واقعاً در ذهنتان جا بیفتد.

در این فصل می‌خوانید
  1. حلقه داخل حلقه
  2. مستطیل ستاره
  3. جدول ضرب
  4. مثلث رشدیابنده
  5. مثلث نزولی
  6. مثلث راست‌چین
  7. هرم
  8. مثلث عددی
  9. صفحه شطرنج
  10. قانون کلی حل مسائل الگو

۱. حلقه داخل حلقه

قانون طلایی این فصل یک جمله است: حلقه داخلی برای هر یک دور حلقه بیرونی، از اول تا آخر کامل اجرا می‌شود.

# 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 ---

شرح مثال

مقایسه‌ای که کار را آسان می‌کند

به عقربه‌های ساعت فکر کنید. عقربه ساعت‌شمار حلقه بیرونی است و دقیقه‌شمار حلقه داخلی. برای هر یک ساعت، دقیقه‌شمار یک دور کامل ۶۰ تایی می‌زند.

۲. مستطیل ستاره

از اینجا به بعد یک الگوی ثابت داریم: حلقه بیرونی سطرها را می‌شمارد و حلقه داخلی ستون‌ها را. کلید کار، دو تا 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

* * * * * * * * 
* * * * * * * * 
* * * * * * * * 
* * * * * * * * 

شرح مثال

۳. جدول ضرب

# 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

* 
* * 
* * * 
* * * * 

شرح مثال

۵. مثلث نزولی

# 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

    *
   ***
  *****
 *******
*********

شرح مثال

۸. مثلث عددی

# 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

# . # . # . # . 
. # . # . # . # 
# . # . # . # . 
. # . # . # . # 

ترفند اینجا ترکیب % فصل دوم با دو شمارنده است. مجموع شماره سطر و ستون، یک در میان زوج و فرد می‌شود و همین الگوی شطرنجی را می‌سازد.

۱۰. قانون کلی حل مسائل الگو

هر مسئله الگو، هر قدر هم پیچیده به نظر برسد، با همین چهار قدم حل می‌شود:

  1. روی کاغذ بکشیدش. پیش از کد زدن، شکل نهایی را با دست رسم کنید.
  2. سطرها را بشمارید. این عدد، حلقه بیرونی شماست.
  3. برای هر سطر بپرسید چند فاصله و چند نویسه لازم است. یک جدول کوچک بسازید: شماره سطر، تعداد فاصله، تعداد ستاره.
  4. رابطه آن ستون‌ها با شماره سطر را پیدا کنید. این رابطه، همان چیزی است که داخل range حلقه داخلی می‌نویسید.
سطر iفاصله در هرمستاره در هرم
۰۴۱
۱۳۳
۲۲۵
۳۱۷
۴۰۹
رابطهSIZE - 1 - i2 * i + 1
فایل‌های تمرینی این فصل

پوشه S07-nested-loops-and-patterns شامل نمونه‌های 01_first_nested_loop.py تا 09_chess_board.py.

خلاصه فصل

مفهومتوضیح
حلقه تودرتوحلقه داخلی برای هر دور حلقه بیرونی کامل اجرا می‌شود
تعداد کل اجراحاصل‌ضرب تعداد دورهای دو حلقه
حلقه بیرونیسطرها
حلقه داخلیستون‌های یک سطر
end=' 'ماندن روی همان خط
print() خالیبستن سطر. بیرون حلقه داخلی، داخل حلقه بیرونی
range(i)حلقه داخلی وابسته به شماره سطر، برای شکل‌های مثلثی
' ' * nراه کوتاه ساختن n فاصله، بدون حلقه

تمرین‌های فصل هفت

  1. مربعی از ستاره به ابعاد n در n رسم کنید که n را کاربر می‌دهد.
  2. مثلثی رسم کنید که اول بزرگ شود و بعد کوچک، یعنی یک لوزی.
  3. مربع توخالی رسم کنید: فقط لبه‌ها ستاره باشند و داخلش خالی.
  4. جدول ضرب ۱ تا ۱۰ را با یک سطر عنوان در بالا چاپ کنید.
  5. همه زوج‌های (i, j) را چاپ کنید که در آنها 1 <= i < j <= 5.
  6. عدد n را بگیرید و همه جفت‌های عددی کوچک‌تر از n که مجموعشان n می‌شود را چاپ کنید.
  7. مثلثی از حروف بسازید: سطر اول A، سطر دوم A B، سطر سوم A B C و همین‌طور ادامه.
فصل قبل: حلقه for فصل بعد: حلقه while