ট্র্যাক
/
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()। for item in <list> কনস্ট্রাক্ট ব্যবহার করে list-এর ভিতরের এলিমেন্টগুলো ইটারেট করা যায়। এলিমেন্টের ইনডেক্স এবং এলিমেন্টের মান, দুটোই দরকার হলে for index, item in enumerate(<list>) ব্যবহার করা যায়।

Python অ্যারে নিয়ে কাজ করার জন্য অনেক কাজের অ্যারে মেথড দিয়ে থাকে। এর মধ্যে বাছাই করা কিছু list methods নিচে আলোচনা করা হয়েছে।

মনে রাখবেন, কোনো list-method দিয়ে একটি list নিয়ে কাজ করলে আপনি পাস করা অ্যারেটিই বদলে দেন। মূল list-টি মিউটেট করতে না চাইলে, স্লাইস বা <list>.copy() দিয়ে অন্তত তার একটি shallow 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 যদি 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.clear() দিয়ে একটি list থেকে সব এলিমেন্ট মুছে ফেলা যায়। এটি কোনো প্যারামিটার নেয় না।

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

>>> numbers
[]

উল্টানো ও পুনর্বিন্যাস

<list>.reverse() মেথড এলিমেন্টগুলোর ক্রম ইন-প্লেস উল্টে দেয়।

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

>>> numbers
[3, 2, 1]

<list>.sort()-এর সাহায্যে একটি অ্যারে ইন-প্লেস পুনর্বিন্যাস করা যায়। ডিফল্ট সর্ট ক্রম বাঁ দিক থেকে ঊর্ধ্বক্রমে। Python-এর ডকুমেন্টেশনে সাজানোর আরও টিপস ও কৌশল আছে।

Note

২০০২ থেকে ২০২২ সাল পর্যন্ত Python অভ্যন্তরীণভাবে অ্যারে সাজাতে 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

list-এর নির্দিষ্ট অংশে খোঁজা সীমিত করতে start ও end ইনডেক্সও দেওয়া যায়:

>>> 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. আমি কি তাদের সঙ্গে যোগ দিতে পারি?

এখন যেহেতু বন্ধুরা খুঁজে পাওয়া গেছে (উপরের #2 কাজে), দেরিতে আসা ব্যক্তি সারিতে তাদের নিজের জায়গায় তাদের সঙ্গে যোগ দিতে চান। 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), এবং ওই list-এর একটি sorted কপি রিটার্ন করে।

>>> sorted_names(queue=["Natasha", "Steve", "Eltran", "Natasha", "Rocket"])
...
['Eltran', 'Natasha', 'Natasha', 'Rocket', 'Steve']
GitHub-এর মাধ্যমে সম্পাদনা করুন লিংকটি একটি নতুন উইন্ডো বা ট্যাবে খোলে
Python Exercism

Chaitana-এর বিশাল রোলারকোস্টার শুরু করতে প্রস্তুত?

Exercism-এ সাইন আপ করুন, Python ট্র্যাকের 17টি কনসেপ্ট146টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।