المسارات
/
Swift
Swift
/
التمارين
/
القاعدة الأولى في نادي الشعر
القاعدة الأولى في نادي الشعر

القاعدة الأولى في نادي الشعر

تمرين تعلّمي

مقدمة

الاستيراد

توفّر Swift وظائف غنية في مكتبتها القياسية، لكن يمكنك الوصول إلى مزيد من الميزات باستيراد مكتبات وأُطر عمل خارجية. قد تأتي هذه الوحدات مباشرةً من مشروع Swift (مثل Swift Argument Parser)، أو من أُطر عمل منصّات Apple (مثل Foundation وNetwork Framework)، أو من مكتبات مفتوحة المصدر من أطراف ثالثة (مثل SwiftyBeaver).

الوحدات الأساسية مثل Foundation، وهي من أكثر المكتبات استخدامًا في Swift، تأتي مضمّنة مع مجموعة أدوات Swift. أما مكتبات الأطراف الثالثة فيجب إضافتها إلى إعدادات مشروعك (مثلًا باستخدام Swift Package Manager) قبل أن تتمكن من استيرادها.

يتم استيراد الوحدات بكتابة الكلمة المفتاحية import متبوعةً باسم الوحدة. لذا يمكنك استيراد Foundation بإضافة ما يلي إلى برنامجك.

import Foundation

استيراد وحدة يجعل أنواعها وطرقها ودوالها متاحةً لكودك. على سبيل المثال، يوسّع استيراد Foundation النوع String بطرق مساعدة مفيدة مثل components(separatedBy:).

بحسب العُرف، توضع عبارات import في أعلى ملف Swift حتى تكون التبعيات ظاهرةً مباشرةً لأي شخص يقرأ الكود.

فهرسة السلاسل النصية

يمكن الوصول إلى المحارف المفردة في String باستخدام أسلوب الفهرسة المستخدم مع المصفوفات. لكن الفهارس المستخدمة مع السلاسل النصية ليست أعدادًا صحيحة ولا يمكن التعامل معها مباشرةً. بدلًا من ذلك يجب حسابها انطلاقًا من فهرس آخر معروف، مثل startIndex، الذي يشير إلى موضع أول محرف في سلسلة نصية غير فارغة، وذلك باستخدام الطرق المتاحة في مكتبتي String وNSString (فعند استيراد وحدة Foundation، تتمكن السلاسل النصية في Swift من الوصول إلى جميع خصائص NSString وطرقه).

على سبيل المثال، لنأخذ السلسلة النصية التالية:

let csv = "apple,pear,peach,orange,cherry,lime,goosberry"

لا يمكنك كتابة csv[21] للحصول على الحرف "g" في "orange"، بل يجب بدلًا من ذلك حساب قيمة من النوع String.Index وتمرير ذلك الفهرس. لاحظ أن هذه الفهارس ليست مخصصة لأن يفهمها البشر بمفردها. فهي ما يُشار إليه باسم الفهارس المعتمة، إذ لا يحتاج البشر إلى معرفة ما بداخلها.

let index = csv.index(csv.startIndex, offsetBy: 21)
csv[index]
// "g"
print(index)
// prints Index(_rawBits: 1376513)

لكن لاحظ أنه إذا لم تكن قيمة الإزاحة فهرسًا صالحًا، أي إذا كانت ستُرجع فهرسًا قبل startIndex أو بعد endIndex، فستُطلق العملية خطأً يؤدي إلى انهيار البرنامج. ولمنع هذه المشكلة، يمكنك تحديد فهرس مُقيّد. تُرجع هذه العملية فهرسًا اختياريًا، وستُرجع nil للفهارس غير الصالحة في غير ذلك.

let tooFar = csv.index(csv.startIndex, offsetBy: 200)
// error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).
let tooFarButSafe = csv.index(csv.startIndex, offsetBy: 200, limitedBy: csv.endIndex)
// nil

بالإضافة إلى ذلك، لا يمكن مشاركة الفهارس بين السلاسل النصية. فمثلًا، استخدام index للحرف "g" في "orange" المحسوب أعلاه للفهرسة داخل السلسلة fam = "This is my family: 👨‍👩‍👦‍👦, this is our dog: 🐶, this is our cat: 🐱!"، أي fam[index]، سيؤدي إلى انهيار برنامجك.

هناك أسباب كثيرة لكل هذا، لكنها جميعًا تعود في الأساس إلى أن "يونيكود معقّد".

وبشكل عام، إذا كنت تحتاج إلى وصول عشوائي إلى المحارف المفردة، فالأرجح أنك تريد استخدام بنية بيانات أخرى، مثل Array<Character>.

بعض الطرق المفيدة

توفّر Swift الطريقتين first وlast للحصول على أول محرف وآخر محرف في السلسلة النصية. تُرجع هاتان الطريقتان محرفًا اختياريًا، لذا إذا كانت السلسلة النصية فارغة فستُرجعان nil.

let str = "Hello, world!"
print(str.first) // Prints Optional("H")
print(str.last)  // Prints Optional("!")

يمكنك أيضًا استخدام الطريقتين prefix وsuffix للحصول على سلسلة نصية فرعية. تأخذ هاتان الطريقتان عددًا صحيحًا كوسيط وتُرجعان سلسلة نصية فرعية تحتوي على أول n محرف أو آخر n محرف من السلسلة النصية.

let str = "Hello, world!"
print(str.prefix(5)) // Prints "Hello"
print(str.suffix(6)) // Prints "world!"

طرق السلاسل النصية

التعامل مع النصوص مهمة شائعة في البرمجة. وتوفّر Swift، إلى جانب إطار عمل Foundation، العديد من الطرق والخصائص الملائمة لفحص السلاسل النصية وتحويلها ومعالجتها.

تقسيم السلاسل النصية باستخدام components(separatedBy:)

لتقسيم سلسلة نصية إلى مصفوفة من السلاسل النصية الفرعية بناءً على فاصل، استخدم components(separatedBy:) (يتطلب استيراد Foundation):

import Foundation

let sentence = "Hello, world!"
let words = sentence.components(separatedBy: " ")
print(words) // Prints ["Hello,", "world!"]

التحقق من البادئات واللواحق باستخدام hasPrefix(_:) وhasSuffix(_:)

للتحقق مما إذا كانت سلسلة نصية تبدأ أو تنتهي بتسلسل معيّن من المحارف، استخدم hasPrefix(_:) وhasSuffix(_:):

let greeting = "Hello, world!"
print(greeting.hasPrefix("Hello"))  // Prints true
print(greeting.hasSuffix("world!")) // Prints true

تغيير حالة الأحرف

يمكنك تغيير حالة الأحرف في سلسلة نصية باستخدام هذه الطرق والخصائص القياسية:

  • lowercased(): تُرجع نسخة من السلسلة النصية بأحرف صغيرة.
  • uppercased(): تُرجع نسخة من السلسلة النصية بأحرف كبيرة.
  • capitalized: تُرجع نسخة يكون فيها أول حرف من كل كلمة كبيرًا (من Foundation).
let greeting = "hello, world!"
print(greeting.lowercased())  // Prints "hello, world!"
print(greeting.uppercased())  // Prints "HELLO, WORLD!"
print(greeting.capitalized)   // Prints "Hello, World!"

استبدال السلاسل النصية الفرعية باستخدام replacingOccurrences(of:with:)

لاستبدال كل حالات ظهور سلسلة نصية فرعية مستهدفة بسلسلة أخرى، استخدم replacingOccurrences(of:with:) (من Foundation):

let greeting = "Hello, world!"
let updated = greeting.replacingOccurrences(of: "world", with: "Swift")
print(updated) // Prints "Hello, Swift!"

ضم السلاسل النصية باستخدام joined(separator:)

تنتمي الطريقة joined(separator:) إلى مجموعات السلاسل النصية، مثل [String]. وهي تضم العناصر معًا في سلسلة نصية واحدة باستخدام فاصل:

let words = ["Hello", "world"]
let sentence = words.joined(separator: ", ")
print(sentence) // Prints "Hello, world"

التعليمات

افتتح نادٍ جديد للشعر في المدينة، وأنت تفكر في الانضمام إليه. ولأنه كانت هناك حوادث في الماضي، فإن النادي يتبع سياسة دقيقة للغاية بشأن الأبواب، وعليك أن تتقنها قبل أن تحاول الدخول.

يوجد بابان في نادي الشعر، وكلاهما محروس. لكي تتمكن من الدخول، عليك أن تعرف كلمة السر الخاصة بذلك اليوم:

1. تقسيم سلسلة نصية إلى أسطر منفردة

أول شيء عليك فعله هو تقسيم القصيدة إلى أسطر منفردة. سيُلقي الحارس قصيدة، وعليك أن تقسّمها إلى أسطر.

نفّذ الدالة splitOnNewlines التي تأخذ سلسلة نصية وتقسّمها إلى مصفوفة من السلاسل النصية، باستخدام محرف السطر الجديد كفاصل. يجب أن تُرجع الدالة مصفوفة من السلاسل النصية، حيث تمثل كل سلسلة سطرًا من القصيدة.

splitOnNewlines("Hello.\nHow are you?\n\nI'm doing fine.")
// returns ["Hello." ,"How are you?", "", "I'm doing fine"].

2. الباب الأمامي

  1. سيُلقي الحارس قصيدة.
  2. عليك أن تقسّم القصيدة إلى أسطر منفردة.
  3. عليك أن تأخذ الحرف الأول من كل سطر.
    • إذا كان السطر فارغًا، فاستخدم _ بدلًا منه.
  4. عليك أن تجمّع الأحرف، وستشكّل معًا كلمة.

على سبيل المثال، أحد كتّابهم المفضلين هو Michael Lockwood، وقد كتب القصيدة الأكروستيكية التالية، أي قصيدة يشكّل الحرف الأول من كل جملة فيها كلمة:

Stands so high
Huge hooves too
Impatiently waits for
Reins and harness
Eager to leave

عندما يُلقي الحارس القصيدة، ستقسّمها إلى أسطر منفردة وتردّ بالحروف الأولى من كل سطر، أي ["S", "H", "I", "R", "E"].

ثم يعطيك الحارس الكلمة المكوّنة من مصفوفة الأحرف التي رددت بها، لتحوّلها إلى صيغة كلمة بحروف كبيرة. وأخيرًا، كلمة السر التي ستُرجعها هي "SHIRE"، وستتمكن من الدخول.

نفّذ الدالة frontDoorPassword التي تأخذ سلسلة نصية تمثّل القصيدة. يجب أن تُرجع الدالة كلمة السر التي ستعطيها للحارس.

frontDoorPassword("Stands so high\nHuge hooves too\nImpatiently waits for\nReins and harness\nEager to leave")
// returns "SHIRE"

3. الباب الخلفي

في الجزء الخلفي من النادي ستجد أشهر الشعراء، وهو أشبه بمنطقة كبار الشخصيات. ولأن هذا الباب ليس للجميع، فإن عملية الباب الخلفي أكثر تعقيدًا بعض الشيء.

  1. سيُلقي الحارس قصيدة.
  2. عليك أن تقسّم القصيدة إلى أسطر.
  3. عليك أن تأخذ الحرف الأخير من كل سطر.
    • قد يحتوي السطر أحيانًا على مسافات زائدة في نهايته، لذا ستحتاج إلى إزالتها.
  4. عليك أن تجمّع الأحرف ثم تضيف ", please" إلى نهاية الكلمة المكوّنة من الأحرف.

على سبيل المثال، القصيدة المذكورة سابقًا هي أيضًا التيليستيكية، أي أن الحرف الأخير من كل جملة يشكّل كلمة:

Stands so high
Huge hooves too
Impatiently waits for
Reins and harness
Eager to leave

عندما يُلقي الحارس القصيدة، ستقسّمها إلى أسطر منفردة، وتزيل أي مسافات زائدة في نهايتها، وتردّ بالحروف الأولى من كل سطر، أي ["h", "o", "r", "s", "e"].

ثم يعطيك الحارس الكلمة المكوّنة من مصفوفة الأحرف التي رددت بها، لتحوّلها إلى صيغة كلمة بحروف كبيرة وتضيف إليها ", please". وأخيرًا، كلمة السر التي ستُرجعها هي "horse, please"، وستتمكن من الدخول.

نفّذ الدالة backDoorPassword التي تأخذ سلسلة نصية تمثّل القصيدة. يجب أن تُرجع الدالة كلمة السر التي ستعطيها للحارس.

backDoorPassword("Stands so high\nHuge hooves too\nImpatiently waits for\nReins and harness\nEager to leave")
// returns "horse, please"

4. الغرفة السرية

داخل الغرفة الخلفية في النادي يوجد باب آخر يؤدي إلى الغرفة السرية التي لا يدخلها إلا كبار الشعراء.

  1. سيُلقي الحارس قصيدة.
  2. عليك أن تقسّم القصيدة إلى أسطر.
  3. عليك أن تأخذ الحرف رقم ith من السطر رقم ith.
  4. عليك أن تجمّع الأحرف ثم تضيف "!" إلى نهاية الكلمة المكوّنة من الأحرف.
  5. عليك أن تحوّل الكلمة إلى حروف كبيرة.

على سبيل المثال، نسخة معدّلة من القصيدة المذكورة سابقًا تناسب هذا النمط:

Stands so high
Huge hooves too
Impatiently waits for
Rider with harness
Eager to leave

عندما يُلقي الحارس القصيدة، ستقسّمها إلى أسطر منفردة، وتزيل أي مسافات زائدة في نهايتها، وتردّ بالحروف رقم ith من كل سطر، أي ["S", "u", "p", "e", "r"].

ثم يعطيك الحارس الكلمة المكوّنة من مصفوفة الأحرف التي رددت بها، لتحوّلها إلى صيغة كلمة بحروف كبيرة وتضيف إليها "!". وأخيرًا، كلمة السر التي ستُرجعها هي SUPER!، وستتمكن من الدخول.

نفّذ الدالة secretRoomPassword التي تأخذ سلسلة نصية تمثّل القصيدة. يجب أن تُرجع الدالة كلمة السر التي ستعطيها للحارس.

secretRoomPassword("Stands so high\nHuge hooves too\nImpatiently waits for\nRider with harness\nEager to leave")
// returns "SUPER!"
تعديل عبر GitHub يفتح الرابط في نافذة أو علامة تبويب جديدة
Swift Exercism

مستعد لبدء القاعدة الأولى في نادي الشعر؟

سجّل في Exercism لتتعلّم وتتقن Swift عبر 35 مفهومًا116 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.