مسیرها
/
Python
Python
/
تمرین‌ها
/
ترن هوایی غول‌آسای Chaitana
ترن هوایی غول‌آسای Chaitana

ترن هوایی غول‌آسای Chaitana

تمرین یادگیری

مقدمه

list یک مجموعه‌ی تغییرپذیر از عنصرهاست که در یک دنباله قرار می‌گیرند. مانند بیشتر مجموعه‌ها (به انواع درونی tuple، dict و set نگاه کنید)، «لیست»ها می‌توانند ارجاع به هر نوع داده‌ای (یا چند نوع داده) داشته باشند، از جمله لیست‌های دیگر. لیست‌ها را می‌توان به‌صورت کامل یا بخشی، با نشانه‌گذاری برش یا با استفاده از <list>.copy() کپی کرد. مانند هر نوع دنباله دیگری، عناصر داخل lists با شماره‌ی 0-based index از سمت چپ، یا شماره‌ی -1-based index از سمت راست ارجاع داده می‌شوند.

لیست‌ها هم از عملیات دنباله‌ای عمومی و هم از عملیات دنباله‌ای تغییرپذیر پشتیبانی می‌کنند، مانند min(<list>)/max(<list>)، <list>.index()، <list>.append() و <list>.reverse(). عناصر داخل یک list را می‌توان با ساختار for item in <list> پیمایش کرد. وقتی هم به اندیس عنصر و هم به مقدار آن نیاز باشد، می‌توان از for index, item in enumerate(<list>) استفاده کرد.

پایتون همچنین متدهای لیست مفید زیادی برای کار با لیست‌ها فراهم می‌کند. در ادامه بخشی از این list methods را بررسی می‌کنیم.

توجه داشته باشید که وقتی یک list را با یک list-method دستکاری می‌کنید، شیء لیستی را تغییر می‌دهید که پاس داده شده است. اگر نمی‌خواهید list اصلی تغییر کند، باید حداقل یک shallow copy از آن، از طریق برش یا <list>.copy()، بسازید.

افزودن عنصرها

برای افزودن یک عنصر به انتها یا «سمت راست» یک لیست موجود، از <list>.append(<item>) استفاده کنید:

>>> numbers = [1, 2, 3]
>>> numbers.append(9)

>>> numbers
[1, 2, 3, 9]

به‌جای افزودن به انتها، <list>.insert() این امکان را به شما می‌دهد که عنصر را در یک اندیس مشخص در لیست اضافه کنید. این متد ۲ پارامتر می‌گیرد:

  1. <index>ای که می‌خواهید عنصر در آن درج شود.
  2. <item>ای که باید درج شود.

توجه: اگر index داده‌شده ۰ باشد، عنصر به ابتدای list («سمت چپ») اضافه می‌شود. اگر index داده‌شده بزرگ‌تر از آخرین index در list باشد، عنصر در جایگاه آخر اضافه می‌شود، یعنی معادل استفاده از <list>.append(<item>).

>>> numbers = [1, 2, 3]
>>> numbers.insert(0, -2)

>>> numbers
[-2, 1, 2, 3]

>>> numbers.insert(1, 0)

>>> numbers
[-2, 0, 1, 2, 3]

از <list>.extend(<item>) می‌توان برای ترکیب یک لیست موجود با عناصر یک شیء قابل‌پیمایش دیگر (مثلاً یک set، tuple، str یا list) استفاده کرد. شیء قابل‌پیمایش باز می‌شود و عناصر آن به ترتیب اضافه می‌شوند (استفاده از <list>.append(<item>) در این حالت، کل شیء قابل‌پیمایش را به‌صورت یک عنصر واحد اضافه می‌کند.).

>>> numbers = [1, 2, 3]
>>> other_numbers = [5, 6, 7]

>>> numbers.extend(other_numbers)

>>> numbers
[1, 2, 3, 5, 6, 7]

>>> numbers.extend([8, 9])

>>> numbers
[1, 2, 3, 5, 6, 7, 8, 9]

>>> numbers.append([8,9])

>>> numbers
[1, 2, 3, 5, 6, 7, 8, 9, [8, 9]]

حذف عنصرها

برای حذف یک عنصر از لیست از <list>.remove(<item>) استفاده کنید و عنصری را که باید حذف شود به‌عنوان آرگومان بدهید. اگر عنصر در list موجود نباشد، <list>.remove(<item>) یک ValueError ایجاد می‌کند.

>>> numbers = [1, 2, 3]
>>> numbers.remove(2)

>>> numbers
[1, 3]

# Trying to remove a value that is not in the list throws a ValueError
>>> numbers.remove(0)
ValueError: list.remove(x): x not in list

در روشی دیگر، استفاده از متد <list>.pop(<index>) هم عنصر را حذف می‌کند و هم آن را برای استفاده return می‌کند.

<list>.pop(<index>) یک پارامتر اختیاری می‌گیرد: index عنصری که باید حذف و برگردانده شود. اگر آرگومان (اختیاری) index مشخص نشود، آخرین عنصر list حذف و برگردانده می‌شود. اگر index مشخص‌شده بزرگ‌تر از آخرین index عنصرها باشد، یک IndexError ایجاد می‌شود.

>>> numbers = [1, 2, 3]

>>> numbers.pop(0)
1

>>> numbers
[2, 3]

>>> numbers.pop()
3

>>> numbers
[2]

>>> numbers.pop(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: pop index out of range

همه‌ی عناصر یک list را می‌توان با list.clear() حذف کرد. این متد هیچ پارامتری نمی‌گیرد.

>>> numbers = [1, 2, 3]
>>> numbers.clear()

>>> numbers
[]

معکوس کردن و مرتب‌سازی مجدد

متد <list>.reverse() ترتیب عناصر را درجا معکوس می‌کند.

>>> numbers = [1, 2, 3]
>>> numbers.reverse()

>>> numbers
[3, 2, 1]

با کمک <list>.sort() می‌توان ترتیب یک لیست را درجا تغییر داد. ترتیب پیش‌فرض مرتب‌سازی از سمت چپ صعودی است. مستندات پایتون نکات و تکنیک‌های بیشتری برای مرتب‌سازی ارائه می‌دهد.

Note

از سال ۲۰۰۲ تا ۲۰۲۲، پایتون به‌صورت داخلی از الگوریتمی به اسم Timsort برای مرتب‌کردن لیست‌ها استفاده می‌کرد، اما از Python 3.11 به بعد به Powersort روی آورد.

>>> names = ["Tony", "Natasha", "Thor", "Bruce"]

# The default sort order is *ascending*.
>>> names.sort()

>>> names
["Bruce", "Natasha", "Thor", "Tony"]

اگر ترتیب نزولی مورد نظر باشد، آرگومان reverse=True را پاس بدهید:

>>> names = ["Tony", "Natasha", "Thor", "Bruce"]
>>> names.sort(reverse=True)

>>> names
["Tony", "Thor", "Natasha", "Bruce"]

در مواردی که تغییر دادن لیست اصلی مطلوب نیست، می‌توان از تابع درونی sorted(<iterable>) استفاده کرد تا یک کپی مرتب برگردانده شود.

>>> names = ["Tony", "Natasha", "Thor", "Bruce"]

>>> sorted(names)
['Bruce', 'Natasha', 'Thor', 'Tony']

تعداد وقوع یک عنصر در یک لیست

تعداد وقوع یک عنصر در یک لیست را می‌توان با کمک list.count(<item>) محاسبه کرد. این متد item مورد شمارش را به‌عنوان آرگومان می‌گیرد و تعداد کل دفعاتی را برمی‌گرداند که آن عنصر در list ظاهر می‌شود.

>>> items = [1, 4, 7, 8, 2, 9, 2, 1, 1, 0, 4, 3]

>>> items.count(1)
3

یافتن اندیس عنصرها

<list>.index(<item>) شماره‌ی index نخستین وقوع عنصری را که پاس داده شده برمی‌گرداند. اگر هیچ وقوعی نباشد، یک ValueError ایجاد می‌شود. اگر به موقعیت دقیق یک عنصر نیاز نباشد، عملگر درونی in برای بررسی وجود یک مقدار مشخص در یک لیست کارآمدتر است.

اندیس‌گذاری از سمت چپ مبتنی بر صفر است، بنابراین موقعیت عنصر «اول» عدد 0 است. اندیس‌گذاری از سمت راست هم کار می‌کند و از -1 شروع می‌شود.

>>> items = [7, 4, 1, 0, 2, 5]

>>> items.index(4)
1

>>> items.index(10)
ValueError: 10 is not in list

می‌توان اندیس‌های start و end را هم ارائه داد تا جست‌وجو به بخشی مشخص از list محدود شود:

>>> names = ["Tina", "Leo", "Thomas", "Tina", "Emily", "Justin"]

>>> names.index("Tina")
0

>>> names.index("Tina", 2, 5)
3

دستورالعمل‌ها

چایتانا صاحب یک پارک تفریحی بسیار محبوب است. او فقط یک وسیله‌ی بازی درست در مرکز محوطه‌ای زیبا و منظرآرایی‌شده دارد: بزرگ‌ترین ترن هوایی جهان(TM). هرچند همین یک جاذبه وجود دارد، مردم از سراسر جهان سفر می‌کنند و ساعت‌ها در صف می‌ایستند تا فرصت سوار شدن بر هایپرکوستر چایتانا را پیدا کنند.

برای این جاذبه دو صف وجود دارد که هر کدام به‌صورت یک list نمایش داده می‌شوند:

  1. صف عادی
  2. صف سریع (که به آن مسیر سریع هم می‌گویند)، جایی که مردم برای دسترسی اولویت‌دار پول بیشتری می‌پردازند.

از شما خواسته شده کدی بنویسید تا مهمان‌های پارک را بهتر مدیریت کنید. باید هرچه سریع‌تر توابع زیر را پیاده‌سازی کنید، پیش از آنکه مهمان‌ها (و رئیس شما، چایتانا!) بداخلاق شوند. حتماً با دقت بخوانید. بعضی از وظیفه‌ها از شما می‌خواهند صف موجود را تغییر دهید یا به‌روزرسانی کنید، و بعضی دیگر می‌خواهند از آن یک کپی بسازید.

1. مرا به صف اضافه کنید

تابع add_me_to_the_queue() را تعریف کنید که ۴ پارامتر <express_queue>, <normal_queue>, <ticket_type>, <person_name> می‌گیرد و صف مناسب را که اسم آن شخص به آن اضافه شده برمی‌گرداند.

  1. <ticket_type> یک int است که در آن 1 همان express_queue و 0 همان normal_queue است.
  2. <person_name> اسم (به‌صورت یک str) شخصی است که باید به صف مربوطه اضافه شود.
>>> add_me_to_the_queue(express_queue=["Tony", "Bruce"], normal_queue=["RobotGuy", "WW"], ticket_type=1, person_name="RichieRich")
...
["Tony", "Bruce", "RichieRich"]

>>> add_me_to_the_queue(express_queue=["Tony", "Bruce"], normal_queue=["RobotGuy", "WW"], ticket_type=0, person_name="HawkEye")
....
["RobotGuy", "WW", "HawkEye"]

2. دوستانم کجا هستند؟

یک نفر دیر به پارک رسیده است، اما می‌خواهد به صفی بپیوندد که دوستانش در آن منتظر ایستاده‌اند. اما هیچ تصوری ندارد که دوستانش کجا ایستاده‌اند و آنتن تلفنی هم نیست که به آن‌ها زنگ بزند.

تابع find_my_friend() را تعریف کنید که ۲ پارامتر queue و friend_name می‌گیرد و موقعیت آن اسم را در صف برمی‌گرداند.

  1. <queue> یک list از افرادی است که در صف ایستاده‌اند.
  2. <friend_name> اسم دوستی است که باید اندیس (جایگاه در صف) او را پیدا کنید.

به یاد داشته باشید: اندیس‌گذاری از سمت چپ با 0 شروع می‌شود و از سمت راست با -1.

>>> find_my_friend(queue=["Natasha", "Steve", "T'challa", "Wanda", "Rocket"], friend_name="Steve")
...
1

3. می‌توانم لطفاً به آن‌ها بپیوندم؟

حالا که دوستانشان پیدا شده‌اند (در وظیفه‌ی ۲ بالا)، این شخص دیررسیده می‌خواهد در همان جایگاه دوستانش در صف به آن‌ها بپیوندد. تابع add_me_with_my_friends() را تعریف کنید که ۳ پارامتر queue، index و person_name می‌گیرد.

  1. <queue> یک list از افرادی است که در صف ایستاده‌اند.
  2. <index> موقعیتی است که شخص جدید باید در آن اضافه شود.
  3. <person_name> اسم شخصی است که باید در موقعیت اندیس اضافه شود.

صف به‌روزرسانی‌شده را همراه با اسم این شخص دیررسیده برگردانید.

>>> add_me_with_my_friends(queue=["Natasha", "Steve", "T'challa", "Wanda", "Rocket"], index=1, person_name="Bucky")
...
["Natasha", "Bucky", "Steve", "T'challa", "Wanda", "Rocket"]

4. آدم بدرفتار در صف

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

تابع remove_the_mean_person() را تعریف کنید که ۲ پارامتر queue و person_name می‌گیرد.

  1. <queue> یک list از افرادی است که در صف ایستاده‌اند.
  2. <person_name> اسم شخصی است که باید از صف بیرون انداخته شود.

صف به‌روزرسانی‌شده را بدون اسم آن آدم بدرفتار برگردانید.

>>> remove_the_mean_person(queue=["Natasha", "Steve", "Eltran", "Wanda", "Rocket"], person_name="Eltran")
...
["Natasha", "Steve", "Wanda", "Rocket"]

5. هم‌نام‌ها

شاید هرگز دو آدم غریبه را ندیده باشید که دقیقاً شبیه هم باشند، اما قطعاً غریبه‌هایی را دیده‌اید که اسمشان کاملاً یکسان است (هم‌نام‌ها)! امروز به نظر می‌رسد تعداد زیادی از آن‌ها در پارک حاضرند. می‌خواهید بدانید یک اسم خاص چند بار در صف تکرار شده است.

تابع how_many_namefellows() را تعریف کنید که ۲ پارامتر queue و person_name می‌گیرد.

  1. <queue> یک list از افرادی است که در صف ایستاده‌اند.
  2. <person_name> اسمی است که فکر می‌کنید ممکن است بیش از یک بار در صف آمده باشد.

تعداد تکرارهای person_name را به‌صورت یک int برگردانید.

>>> how_many_namefellows(queue=["Natasha", "Steve", "Eltran", "Natasha", "Rocket"], person_name="Natasha")
...
2

6. حذف آخرین نفر

متأسفانه امروز پارک بیش از حد شلوغ است و باید آخرین نفر صف عادی را حذف کنید (به او یک بن می‌دهید تا روز دیگری از مسیر سریع برگردد). باید تابع remove_the_last_person() را تعریف کنید که ۱ پارامتر queue می‌گیرد؛ یعنی فهرست افرادی که در صف ایستاده‌اند.

باید list را به‌روزرسانی کنید و همچنین اسم شخصی را که حذف شده return کنید تا بتوانید برایش بن بنویسید.

>>> remove_the_last_person(queue=["Natasha", "Steve", "Eltran", "Natasha", "Rocket"])
...
'Rocket'

7. مرتب‌سازی فهرست صف

برای کارهای اداری، باید همه‌ی اسم‌های یک صف مشخص را به ترتیب الفبایی مرتب کنید.

تابع sorted_names() را تعریف کنید که ۱ آرگومان، queue (همان list افرادی که در صف ایستاده‌اند)، می‌گیرد و یک کپی sortedشده از list را برمی‌گرداند.

>>> sorted_names(queue=["Natasha", "Steve", "Eltran", "Natasha", "Rocket"])
...
['Eltran', 'Natasha', 'Natasha', 'Rocket', 'Steve']
ویرایش از طریق GitHub این لینک در پنجره یا زبانه‌ی جدیدی باز می‌شود
Python Exercism

آماده‌اید ترن هوایی غول‌آسای Chaitana را شروع کنید؟

در Exercism ثبت‌نام کنید تا Python را همراه با 17 مفهوم146 تمرین و مربی‌گری انسانی واقعی یاد بگیرید و در آن استاد شوید، همه‌ی این‌ها رایگان.