المسارات
/
Julia
Julia
/
التمارين
/
روبوت المحادثة النمطي
روبوت المحادثة النمطي

روبوت المحادثة النمطي

تمرين تعلّمي

مقدمة

التعبيرات النمطية طريقة بالغة التنوع من أجل مطابقة الأنماط في السلاسل النصية، وذلك باستخدام لغة خاصة بالمجال (DSL) مصممة لهذا الغرض.

على غرار عدة لغات برمجة أخرى، لا تحاول Julia تنفيذ مكتبة Regex خاصة بها. بدلًا من ذلك، تستعمل مكتبة PCRE2 الشائعة كغلاف، فتوفّر بذلك صياغة Regex مطابقة تمامًا لصياغة Gleam (على سبيل المثال)، وشديدة الشبه بـ Javascript.

Note

يفترض هذا المقرر الخاص بـ Julia أنك تعرف بالفعل الصياغة الأساسية للتعبيرات النمطية. سنركّز فقط على الميزات الخاصة بـ Julia.

تجد أدناه بعض المصادر لتحديث معرفتك بالتعبيرات النمطية.

تُوصَف واجهة Julia مع التعبيرات النمطية في الدليل.

التعبير النمطي في Julia هو ببساطة سلسلة نصية تسبقها r قبل علامة " الافتتاحية. وكل الوظائف الأساسية جزء من المكتبة القياسية.

في الواقع، كثير من الدوال التي جرت مناقشتها بالفعل في مفهوم Strings مصممة أصلًا لعمليات بحث Regex، مثل occursin().

julia> re = r"test$"
r"test$"

julia> typeof(re)
Regex

# Does a string end with "test"?
julia> occursin(re, "this is a test")
true

julia> occursin(re, "these are tests")
false

يمكن أن تتبع أحرف التعديل علامة التنصيص الختامية، مثل i من أجل مطابقة غير حساسة لحالة الأحرف.

julia> occursin(r"test", "Testing")
false

julia> occursin(r"test"i, "Testing")
true

الالتقاط

غالبًا ما نريد معرفة ما الذي يطابق. ويتحقق ذلك بتضمين مجموعات التقاط بين قوسين هلاليين داخل التعبير النمطي، ثم استخدام الدالة match().

julia> m = match(r"(\d+g) .* (\d+ml)", "dissolve 25g sugar in 200ml water")
RegexMatch("25g sugar in 200ml", 1="25g", 2="200ml")

julia> m.captures
2-element Vector{Union{Nothing, SubString{String}}}:
 "25g"
 "200ml"

# how many matches?
julia> length(m.captures)
2

# what matched?
julia> m[1], m[2]
("25g", "200ml")

# Starting positions of the matches (character index)
julia> m.offsets
2-element Vector{Int64}:
 10
 23

بطبيعة الحال، قد تفشل المطابقات. وعندئذ تكون النتيجة القيمة الخاصة Nothing بدلًا من RegexMatch، فكن مستعدًا لاختبار ذلك.

# failed match
m = match(r"(not here)", "dissolve 25g sugar in 200ml water")

julia> typeof(m)
Nothing

julia> isnothing(m)
true

ورغم أن match تبدأ افتراضيًا من بداية السلسلة النصية، يمكننا أيضًا تحديد إزاحة n لتجاهل أول n من الأحرف.

# capture first match
julia> m = match(r"(\wat)", "cat, sat, mat")
RegexMatch("cat", 1="cat")

# ignore first 5 characters, then match
julia> m = match(r"(\wat)", "cat, sat, mat", 5)
RegexMatch("sat", 1="sat")

في Julia، لن تجد match() سوى المطابقة الأولى داخل السلسلة النصية المستهدفة: فلا يوجد معدِّل شامل كما في بعض اللغات الأخرى.

بدلًا من ذلك، لدينا eachmatch()، التي تُرجع مكرِّرًا للمطابقات. ويُقيَّم هذا بتكاسل، لذا قد تحتاج إلى تحويله إلى الصيغة التي تريدها.

julia> matches = eachmatch(r"(\wat)", "cat, sat, mat")
Base.RegexMatchIterator{String}(r"(\wat)", "cat, sat, mat", false)

# convert to vector
julia> collect(matches)
3-element Vector{RegexMatch}:
 RegexMatch("cat", 1="cat")
 RegexMatch("sat", 1="sat")
 RegexMatch("mat", 1="mat")

# convert with comprehension
julia> [m.match for m in matches]
3-element Vector{SubString{String}}:
 "cat"
 "sat"
 "mat"

# broadcast an anonymous function
julia> (m -> m.match).(matches)
3-element Vector{SubString{String}}:
 "cat"
 "sat"
 "mat"

الاستبدال

من الأسباب الشائعة لاستخدام Regex استبدال المطابقة بسلسلة نصية مختلفة.

جرت مناقشة الدالة replace() في مفهوم Strings، حيث كانت تستخدم سلاسل نصية حرفية للبحث بها. ويمكن للدالة نفسها أن تستفيد من كامل قوة مطابقة Regex.

julia> replace("some string", r"[aeiou]" => "*")
"s*m* str*ng"

julia> replace("first second", r"(\w+) (?<agroup>\w+)" => s"\g<agroup> \1")
"second first"

يوضح المثال الثاني أعلاه كيف يمكن استخدام مجموعات الالتقاط المرقّمة والمسمّاة معًا في الاستبدال، داخل سلسلة نصية s" ".

راجع الدليل لمزيد من التفاصيل: فهذا موضوع يعيد معظم المبرمجين باستمرار إلى الوثائق!

التعليمات

تم تعيينك أخصائيًا في التعبيرات النمطية في شركة تطوّر Chatbot.

الشركة لا تزال في مرحلة تطوير أولية جدًا، لذا مهمتك هي استخدام التعبيرات النمطية لتحسين قدرة Chatbot على فهم اللغة الطبيعية وتوليدها.

Note

لأغراض التعلم، يُرجى حل هذه المهام باستخدام التعبيرات النمطية.

نحن نعلم أن الحلول البديلة تكون ممكنة أحيانًا (وقد تكون حتى أكثر كفاءة!)

1. التحقق من صحة الأمر

إلى جانب كونه ذكيًا، فإن Chatbot مساعد مخلص أيضًا.

لكي يطلب المستخدم شيئًا من Chatbot، يجب أن يقول كلمة "Chatbot" في الموضع الأول من الأمر.

لا يهم إن كانت الكلمة المفتاحية بأحرف كبيرة أو صغيرة. المهم هنا هو موضع الكلمة.

نفّذ الدالة is_valid_command() التي تساعد Chatbot على التعرف على متى يعطي المستخدم أمرًا.

julia> is_valid_command("Chatbot, play a song from the 80's.")
True

julia> is_valid_command("Hey Chatbot, where is the closest pharmacy?")
False

julia> is_valid_command("CHATBOT, do you have a solution for this challenge?")
True

2. إزالة الإيموجي المشفَّر

يجد Chatbot صعوبة في فهم كيفية استخدام البشر للإيموجي للتعبير عن مشاعرهم.

عندما يستقبل Chatbot رسائل المستخدمين، يُمثَّل كل إيموجي على هيئة "emoji" متبوعة برقم الـ id الخاص به.

نفّذ الطريقة remove_emoji() التي تأخذ سلسلة نصية وتزيل كل تشفير الإيموجي في الرسالة.

تُرجَع الأسطر التي لا تحتوي على نص الإيموجي دون تعديل.

أزل نص الإيموجي فقط، ولا تحاول تعديل المسافات.

julia> remove_emoji("I love playing videogames emoji3465 it's one of my hobbies")
"I love playing videogames  it's one of my hobbies"

3. التحقق من صحة رقم الهاتف

بالنظر إلى إمكانية تنزيل مزايا Chatbot على تطبيق للهاتف المحمول، يُتوقَّع من المستخدم كتابة رقم هاتف أثناء المحادثة.

المشكلة أن Chatbot لا يستطيع قراءة وتحقّق سوى رقم بصيغة محددة.

إذا كان الرقم صالحًا (أي يطابق تسلسل الأحرف المحدد في التعبير النمطي)، يجيب Chatbot برسالة تشكر المستخدم وتؤكد الرقم. وإذا كان الرقم غير صالح، تُخبر الدالة المستخدم بأن رقم الهاتف غير صالح.

الصيغة المتوقعة هي: (+##) ###-###-###

julia> check_phone_number("(+34) 659-771-594")
"Thanks! You can now download me to your phone."

julia> check_phone_number("659-771-594")
"Oops, it seems like I can't reach out to 659-771-594"

4. الحصول على رابط الموقع

Chatbot برنامج فضولي جدًا. فرغم أنه يستطيع البحث على الإنترنت عن موضوع معيّن، إلا أنه يحب أن يسأل المستخدمين عن مواقع رائعة أو عناوين URL للعثور على معلومات ذات صلة.

مثال على محادثة:

  • Chatbot: مرحبًا username، أود أن أتعلم البرمجة بلغة JavaScript، هل تعرف موقعًا رائعًا يمكنني التعلم منه؟
  • المستخدم: تعلمت الكثير من exercism.org

نفّذ الدالة getURL() القادرة على إرجاع مصفوفة تحتوي على رابط كل موقع فقط.

julia> getURL("I learned a lot from exercism.org")
["exercism.org"]

5. الترحيب بالمستخدم

لتخزين بيانات جميع الأشخاص الذين أجرى معهم محادثة، يستطيع Chatbot الحصول على الاسم الكامل من ملف تعريف المستخدم بهذا الشكل: "smith, john".

وبهذه الطريقة نريد أن يكون Chatbot مهذبًا حقًا وأن يترك انطباعًا جيدًا.

اكتب الدالة nice_to_meet_you() التي تأخذ سلسلة نصية تحتوي على الاسم الكامل للمستخدم، وتُرجع السلسلة النصية "Nice to meet you, John Smith"

julia> str = "Smith, John"

julia> nice_to_meet_you(str)
"Nice to meet you, John Smith"
تعديل عبر GitHub يفتح الرابط في نافذة أو علامة تبويب جديدة
Julia Exercism

مستعد لبدء روبوت المحادثة النمطي؟

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