لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 06/13/24 في كل الموقع
-
لدية شاشة مقاس ٥٥ بوصة واريد تصميم مقطع فيديو لكي اعرضه عليها ولا أعلم كم المقاسات المناسبة ماهو المقاس المناسب لها بالبكسل2 نقاط
-
2 نقاط
-
مثل RetroBat V6.2.1 نسخه تخص العب BATOCERA تكون ايزو1 نقطة
-
1 نقطة
-
أنا تاجر دواجن العمل مقسم الي قسمين : الاول : المكان والتجهيزات من معدات وغيرها . الثاني : شراء الدواجن والاعلاف. وبيع الدواجن بعد ٤٠ يوم شخص يريد تشغيل ماله معي في حين تكاليف التجهيزات وهي اصول ثابتة عليا انا و هو راس ماله في الدواجن فقط و وقت ما يكون محتاج الفلوس هاخدها كامله نسبته كام في المكسب والخسارة بفرض أن المشروع تكلفته الإجمالية ٢٣٠ ألف جنيه تجهيزات وهي المعدات ١٢٠ ألف جنيه هدفعها انا الدواجن ١١٠ ألف جنيه راس مال الشريك بفرض مكسب بعد أنها دورة الدواجن ٤٠ ألف جنيه1 نقطة
-
بعد تصميم واجهة المستخدم ( تطبيق و موقع ) هل أبدأ في تصميم وبرمجة لوحة التحكم قبل برمجة التطبيق والموقع ؟1 نقطة
-
كإجابة عامة فإني اقول لك نعم ابدأ ببرمجة لوحة التحكم في البداية، وذلك لأنك لن تستطيع تجريب وربط التطبيق و الموقع قبل ان يكون لديك لوحة تحكم. ولكن قد تختلف هذه القاعدة بحسب كل موقع و نوع الفريق الذي يعمل على المشروع وكون المشروع موثق بشكل جيد او لا.1 نقطة
-
1 نقطة
-
1 نقطة
-
ابيه صيغه ايزو على تسعدني في تخصيص RetroArch وتنزيل محكي بيلستشان 3 وشكران لكى1 نقطة
-
كل منهما له نقاط قوة وضعف، فالتعلم العميق يتفوق في التعامل مع البيانات المعقدة والغير منظمة مثل الصور، الفيديو، والنصوص، والشبكات العصبية العميقة مثل الشبكات العصبية التلافيفية (CNN) والشبكات العصبية المتكررة (RNN) تكون فعالة جدًا في تلك الحالات. بينما تعلم الآلة التقليدي أفضل في الحالات التي تكون فيها البيانات بسيطة ومنظمة، مثل الجداول والمصفوفات، ومن الأمثلة على خوارزميات تعلم الآلة التقليدية فلديك الانحدار الخطي، أشجار القرار، والـ SVM. أيضًا التعلم العميق يحتاج إلى كميات ضخمة من البيانات للتدريب بشكل فعال، فكلما زادت البيانات، كلما كانت النتائج أفضل، وهو يعتبر "صندوق أسود" إلى حد كبير، مما يجعل من الصعب تفسير كيفية اتخاذ القرارات. ويتطلب موارد حسابية كبيرة، بما في ذلك وحدات معالجة الرسوميات GPU وأحيانًا وحدات معالجة متخصصة أخرى، ويحتاج وقتًا طويلاً للتدريب وتكلفة مالية عالية بسبب متطلبات الأجهزة والبيانات. بجانب أنه أكثر دقة في بعض التطبيقات، خاصة تلك التي تتطلب التعرف على الأنماط المعقدة. على العكس في تعلم الآلة التقليدي فيعمل بشكل جيد مع كميات أصغر من البيانات، وغالبًا ما تكون النماذج أكثر شفافية وأسهل في التفسير. وأقل تطلبًا من حيث الموارد المطلوبة لمعالجة البيانات، وأسرع وأقل تكلفة، خاصة في المراحل الأولية من المشروع، وفي بعض التطبيقات، يكون الأداء مشابهًا أو حتى أفضل من التعلم العميق، خصوصًا عندما تكون البيانات محدودة.1 نقطة
-
وعليكم السلام، التعلم العميق أو التعلم الآلي كلاهما لا يعملان في الحقيقة إلا على الأعداد. فما يقوم به النموذج في الداخل هو ضرب أعداد في أعداد، وتعديل أعداد بالنسبة لقيمة أعداد أخرى، وهكذا. لذلك، فأي نوع بيانات مختلف عن الأعداد يجب أن يتم تحويله إلى أعداد. لذلك، أوّل خطوة هي دائما ما يسمى بالمعالجة القبلية (Preprocessing) التي فيها يتم تحويل البيانات الطبيعية إلى بيانات عددية. المعالجة القبلية ليست شيئا خاصا بالصورة والصوت، بل تشمل حتى النصوص أيضا لأن نماذج تعلم الآلة لا تستطيع قراءة النصوص أيضا. بل في بعض الأحيان نحتاج للقيام بالمعالجة القبلية حتى عندما تكون البيانات أعدادا. فمثلا، إن كان عندنا في بياناتنا عمود يمثل سنة الميلاد، وبجانبه عمود يمثل طول الشخص، فهذان العمودان يحتاجان أولا للتحويل إلى قيم متشابهة، وإلا فقد لن يتم التعلم بشكل صحيح. لذلك نحاول دائما أن نجعل القيم بين 0 و 1 لكل الأعمدة، وهذا ما يعرف باسم التطبيع (Normalization). توجد تقنيات مختلفة للمعالجة القبلية، وهذا يعتمد على نوع البيانات وعلى قدرات النموذج. فمثلا، إن أردنا إدخال صورة إلى نموذج تعلم آلة يستقبل بيانات عددية على شكل مصفوفة، فما يمكننا فعله هو تفكيك الصورة إلى مصفوفات حسب عرضها width (أو ارتفاعها height) ثم ربط هذه المصفوفات خلف بعضها (Concatenation) حتى تصبح مصفوفة طويلة واحدة. يعني الصورة التي أبعادها 32 * 32، تتحول إلى مصفوفة طولها 1024، حيث كل خانة من هذه المصفوفة تحوي قيمة البكسل الموافق. بالإضافة إلى ذلك، قيم البكسلات تكون من 0 إلى 255، وبما أننا نفضل دائما أن تكون القيم بين 0 و 1، فقد نقوم أيضا بعملية التطبيع لتحويلها إلى القيم المناسبة. للمزيد من المعلومات حول كيفية التعامل مع الصور في نماذج تعلم الآلة، يمكنك الإطلاع على الدليل التالي من موقع Scikit-learn، والتي هي مكتبة تعلم آلي وليست مكتبة تعلم عميق: https://scikit-learn.org/stable/auto_examples/classification/plot_digits_classification.html1 نقطة
-
سنشرح في هذا المقال نوع البيانات المسمى بالقاموس dictionary، الذي يوفر طريقة مرنة للوصول إلى البيانات وتنظيمها، ثم سنتعلم كيفية كتابة لعبة إكس-أو عبر دمج ما تعلمناه في المقالات السابقة من هذه السلسلة مع القواميس. نوع البيانات dictionary القواميس تشبه القوائم في أنها مجموعة قابلة للتعديل mutable من القيم، لكن بدلًا من وجود الفهارس الرقمية للعناصر كما في القوائم، يمكن استخدام مختلف أنواع البيانات في القواميس. نسمي المفاتيح في القواميس بالمفاتيح keys، وكل مفتاح مرتبط بقيمة، ونسمي ذلك زوجًا من المفاتيح والقيم key-value pair. نكتب القواميس في بايثون بإحاطها بقوسين مجعدين أو معقوصين {}: >>> myCat = {'size': 'fat', 'color': 'gray', 'disposition': 'loud'} السطر السابق يسند قاموسًا إلى المتغير myCat، ومفاتيح هذا القاموس هي 'size' و 'color' و 'disposition'، والقيم المرتبطة بتلك المفاتيح هي 'fat' و 'gray' و 'loud' على التوالي وبالترتيب. يمكنك الوصول إلى هذه القيم عبر مفاتيحها: >>> myCat['size'] 'fat' >>> 'My cat has ' + myCat['color'] + ' fur.' 'My cat has gray fur.' ما يزال بالإمكان استخدام الأعداد الصحيحة مفاتيحًا لقيم القواميس، لكن ليس من الضروري أن تبدأ من الصفر 0 ويمكنك استخدام أي رقم: >>> spam = {12345: 'Luggage Combination', 42: 'The Answer'} مقارنة القواميس والقوائم على خلاف القوائم، لا تكون القواميس مرتبةً، فأول عنصر في قائمة اسمها spam سيكون spam[0]، لكن لا يوجد «أول» عنصر في القاموس. سيكون ترتيب العناصر مهمًا في حال أردنا تحديد إن كانت قائمتان متساويتين، بينما لا يفرق ترتيب كتابة أزواج المفاتيح-القيم في القواميس: >>> spam = ['cats', 'dogs', 'moose'] >>> olive = ['dogs', 'moose', 'cats'] >>> spam == olive False >>> eggs = {'name': 'Zophie', 'species': 'cat', 'age': '8'} >>> steak = {'species': 'cat', 'age': '8', 'name': 'Zophie'} >>> eggs == steak True ولأن القواميس غير مرتبة، فلا يمكن تقسيمها كما في القوائم. محاولة الوصول إلى مفتاح غير موجود في قاموس ما سيؤدي إلى حدوث الخطأ KeyError، وهي تشبه رسالة الخطأ IndexError في القوائم حين محاولة الوصول إلى قيمة خارج مجال فهارس القائمة. لاحظ رسالة الخطأ الآتية التي تظهر لعدم وجود المفتاح 'color': >>> spam = {'name': 'Zophie', 'age': 7} >>> spam['color'] Traceback (most recent call last): File "<pyshell#1>", line 1, in <module> spam['color'] KeyError: 'color' وصحيحٌ أن القواميس غير مرتبة، لكن إمكانية استخدام أي قيمة تريدها للمفاتيح يسمح لنا بترتيب البيانات بطرائق رائعة! لنقل أننا نريد كتابة برنامج يخزن معلومات حول أعياد ميلاد أصدقائك، يمكنك أن تكتب الشيفرة الآتية birthdays.py التي تستخدم القواميس وتجعل أسماء أصدقائك مفاتيحًا للقيم: ➊ birthdays = {'Alice': 'Apr 1', 'Bob': 'Dec 12', 'Carol': 'Mar 4'} while True: print('Enter a name: (blank to quit)') name = input() if name == '': break ➋ if name in birthdays: ➌ print(birthdays[name] + ' is the birthday of ' + name) else: print('I do not have birthday information for ' + name) print('What is their birthday?') bday = input() ➍ birthdays[name] = bday print('Birthday database updated.') أنشأنا قاموسًا وخزناه في المتغير birthdays ➊، ثم تحققنا إن كان الاسم المدخل موجودًا في القاموس عبر الكلمة المحجوزة in ➋ كما كنا نفعل مع القوائم. إذا كان الاسم موجودًا في القاموس فيمكنك الوصول إلى القيمة المرتبطة به عبر استخدام الأقواس المربعة ➌، وإلّا فيمكنك إضافتها باستخدام صيغة الأقواس المربعة مع عامل الإسناد ➍: Enter a name: (blank to quit) Alice Apr 1 is the birthday of Alice Enter a name: (blank to quit) Eve I do not have birthday information for Eve What is their birthday? Dec 5 Birthday database updated. Enter a name: (blank to quit) Eve Dec 5 is the birthday of Eve Enter a name: (blank to quit) للأسف ستحذف كل المعلومات التي أدخلتها في هذا البرنامج حين انتهاء تنفيذه. ستتعلم كيفية حفظ الملفات على القرص في مقال لاحق من هذه السلسلة. القواميس المرتبة في بايثون 3.7 صحيح أن القواميس غير مرتبة ولا يوجد فيها عنصر «أول»، لكن القواميس في الإصدار 3.7 من بايثون وما يليه ستتذكر ترتيب أزواج القيم الموجودة فيها حين إنشاء متسلسل sequence منها. فمثلًا لاحظ أن ترتيب العناصر في القائمتين المنشأتين من القاموسين eggs و steak يطابق ترتيب إدخالها: >>> eggs = {'name': 'Zophie', 'species': 'cat', 'age': '8'} >>> list(eggs) ['name', 'species', 'age'] >>> steak = {'species': 'cat', 'age': '8', 'name': 'Zophie'} >>> list(steak) ['species', 'age', 'name'] ستبقى القواميس غير مرتبة، ولا يمكنك أن تصل إلى العناصر فيها عبر فهرس رقمي مثل eggs[0] أو steak[2]، لا يجدر بك الاعتماد على هذا السلوك لأن بايثون لا تتذكر ترتيب إدخال العناصر في الإصدارات القيمة منها، فلاحظ المثال الآتي الذي لا يطابق ترتيب عناصر القاموس الناتج النهائي الترتيبَ الذي أدخلتها به، ناتج التنفيذ الآتي على إصدار بايثون 3.5: >>> spam = {} >>> spam['first key'] = 'value' >>> spam['second key'] = 'value' >>> spam['third key'] = 'value' >>> list(spam) ['first key', 'third key', 'second key'] التوابع keys() و values() و items() هنالك ثلاثة توابع خاصة بالقواميس التي تعيد قيمًا شبيهة بالقوائم list-like من مفاتيح القواميس أو قيمها أو كلًا من المفاتيح والقيم معًا وهي التوابع keys() و values() و items() بالترتيب. القيم المعادة من هذه التوابع ليست قوائم حقيقيةً، فلا يمكننا تعديلها وليس لها التابع append()، لكن أنواع البيانات المعادة (وهي dictkeys و dictvalues و dict_items بالترتيب) يمكن أن تستخدم في حلقات التكرار for: >>> spam = {'color': 'red', 'age': 42} >>> for v in spam.values(): ... print(v) red 42 ستمر حلقة for هنا على كل قيمة في القاموس spam، يمكن لحلقة for المرور على المفاتيح فقط، وعلى المفاتيح والقيم معًا: >>> for k in spam.keys(): ... print(k) color age >>> for i in spam.items(): ... print(i) ('color', 'red') ('age', 42) حين استخدامنا للتوابع keys() و values() و items() فيمكن للحلقة for المرور على قيم المفاتيح أو قيم العناصر أو قيم أزواج المفتاح-القيمة على التوالي. لاحظ أن القيم المعادة من items() هي صفوف tuples تحتوي على المفتاح ثم قيمته. إذا أردتَ قائمةً حقيقية من ناتج أحد تلك التوابع، فيمكننا تمرير القيمة الشبيهة بالقوائم إلى الدالة list() كما يلي: >>> spam = {'color': 'red', 'age': 42} >>> spam.keys() dict_keys(['color', 'age']) >>> list(spam.keys()) ['color', 'age'] يأخذ السطر list(spam.keys()) القيمة ذات النوع dict_keys المعادة من التابع keys() ويمررها إلى الدالة list()، والتي تعيد بدورها قائمةً فيها ['color', 'age']. يمكنك استخدام الإسناد المتعدد مع حلقة for لإسناد المفتاح والقيمة إلى متغيرات منفصلة: >>> spam = {'color': 'red', 'age': 42} >>> for k, v in spam.items(): ... print('Key: ' + k + ' Value: ' + str(v)) Key: age Value: 42 Key: color Value: red التحقق من وجود مفتاح أو قيمة في قاموس نتذكر من المقال السابق أن العاملين in و not in يمكن أن يستخدما للتحقق من وجود قيمة في قائمة. ويمكننا استخدام نفس العاملين للتحقق من وجود قيمة ما في مفتاح أو قيمة في قاموس: >>> spam = {'name': 'Zophie', 'age': 7} >>> 'name' in spam.keys() True >>> 'Zophie' in spam.values() True >>> 'color' in spam.keys() False >>> 'color' not in spam.keys() True >>> 'color' in spam False لاحظ أن كتابة 'color' in spam هي مطابقة لكتابة 'color' in spam.keys(). فإذا أردت التحقق من وجود (أو عدم وجود) مفتاح ما في قاموس فاستعمل الكلمة المحجوزة in (أو not in) مع القاموس نفسه. التابع get() من الرتيب أن نتحقق من وجود مفتاح ما في القاموس قبل الوصول إلى القيمة المرتبطة به، لكن لحسن الحظ هنالك تابع باسم get() يأخذ وسيطين: الأول هو المفتاح الذي نريد الوصول إلى قيمته، والثاني هو قيمة افتراضية ستعاد إن لم يكن المفتاح موجودًا: >>> picnicItems = {'apples': 5, 'cups': 2} >>> 'I am bringing ' + str(picnicItems.get('cups', 0)) + ' cups.' 'I am bringing 2 cups.' >>> 'I am bringing ' + str(picnicItems.get('eggs', 0)) + ' eggs.' 'I am bringing 0 eggs.' ولعدم وجود المفتاح 'eggs' في القاموس picnicItems فستعاد القيمة 0 من التابع get()، وإن لم نستعمل التابع get() في المثال السابق فستظهر رسالة خطأ كما يلي: >>> picnicItems = {'apples': 5, 'cups': 2} >>> 'I am bringing ' + str(picnicItems['eggs']) + ' eggs.' Traceback (most recent call last): File "<pyshell#34>", line 1, in <module> 'I am bringing ' + str(picnicItems['eggs']) + ' eggs.' KeyError: 'eggs' التابع setdefault() الحاجة إلى ضبط قيمة في القاموس مرتبطة بمفتاح معين إن لم يكن ذاك المفتاح موجودًا مسبقًا هو أمرٌ شائع، وتكون الشيفرة بالشكل الآتي: spam = {'name': 'Pooka', 'age': 5} if 'color' not in spam: spam['color'] = 'black' يوفر التابع setdefault() طريقة أسهل لفعل ذلك بسطر برمجي وحيد، فأول وسيط يمرر إلى التابع هو المفتاح الذي سنتحقق من وجوده، والوسيط الثاني هو القيمة التي ستُضبَط إن لم يكن المفتاح موجودًا. إذا كان المفتاح موجودًا فسيعيد التابع setdefault() قيمة ذاك المفتاح: >>> spam = {'name': 'Pooka', 'age': 5} >>> spam.setdefault('color', 'black') 'black' >>> spam {'color': 'black', 'age': 5, 'name': 'Pooka'} >>> spam.setdefault('color', 'white') 'black' >>> spam {'color': 'black', 'age': 5, 'name': 'Pooka'} حينما استدعينا التابع setdefault() أول مرة، فتغيرت قيمة القاموس spam إلى {'color': 'black', 'age': 5, 'name': 'Pooka'}، وسيعيد التابع setdefault() القيمة 'black' لأنها القيمة المضبوطة للمفتاح 'color' حاليًا. لكن حين استدعاء spam.setdefault('color', 'white') فإن القيمة لن تتغير إلى 'white' لأن القاموس spam يحتوي على مفتاح باسم 'color'. التابع setdefault() هو اختصار جميل للتأكد من وجود مفتاح معين وضبط قيمته. هذا مثال عن برنامج يعدّ عدد مرات وجود كل حرف في سلسلة نصية. احفظ المثال الآتي باسم characterCount.py: message = 'It was a bright cold day in April, and the clocks were striking thirteen.' count = {} for character in message: ➊ count.setdefault(character, 0) ➋ count[character] = count[character] + 1 print(count) سيمر البرنامج على كل محرف في السلسلة النصية المخزنة في المتغير message، ويعد كم مرة يظهر فيها كل محرف. استدعاء الدالة setdefault() ➊ سيضمن وجود المفتاح في القاموس count ويضبط قيمته الافتراضية إلى 0، وبالتالي لا يرمي البرنامج الخطأ KeyError حين تنفيذ التعبير البرمجي count[character] = count[character] + 1 ➋. سيبدو الناتج كما يلي: {' ': 13, ',': 1, '.': 1, 'A': 1, 'I': 1, 'a': 4, 'c': 3, 'b': 1, 'e': 5, 'd': 3, 'g': 2, 'i': 6, 'h': 3, 'k': 2, 'l': 3, 'o': 2, 'n': 4, 'p': 1, 's': 3, 'r': 5, 't': 6, 'w': 2, 'y': 1} سترى من الناتج السابق أن الحرف c الصغير مكرر 3 مرات، بينما الفراغ مكرر 13 مرة، والحرف A الكبير يظهر مرة واحدة. سيعمل البرنامج السابق على جميع السلاسل النصية بغض النظر عن محتويات المتغير message حتى لو كان يحتوي على مليون حرف! تجميل الطباعة إذا استوردت الوحدة pprint في برامجك، فيمكنك الوصول إلى الدالتين pprint() و pformat() التي «تجمل طباعة» pretty print قيم القواميس، ستستفيد من هذه الدوال إن أردت عرض قيم القواميس عرضًا أجمل من طريقة عرض الدالة print()، لنعدل المثال السابق: import pprint message = 'It was a bright cold day in April, and the clocks were striking thirteen.' count = {} for character in message: count.setdefault(character, 0) count[character] = count[character] + 1 pprint.pprint(count) سيظهر لنا الناتج الجميل الآتي: {' ': 13, ',': 1, '.': 1, 'A': 1, 'I': 1, --snip-- 't': 6, 'w': 2, 'y': 1} سنستفيد فعليًا من الدالة pprint.pprint() عندما يحتوي القاموس على قوائم أو قواميس متشعبة داخله nested. إذا أردت الحصول على قيمة النص المجمّل بدلًا من طباعته على الشاشة مباشرةً، فاستدعِ الدالة pprint.pformat(). السطران الآتيان متكافئان تمامًا: pprint.pprint(someDictionaryValue) print(pprint.pformat(someDictionaryValue)) استخدام بنى المعطيات لنمذجة عناصر حقيقية كان بإمكاننا لعب الشطرنج مع شخص آخر عن بعد قليل ظهور الإنترنت، فكان يعد كل لاعب رقعة الشطرنج في منزله، ثم يبادلان الرسائل البريدية يصف كل منهما خطوته، ولكي يستطيعوا فعل ذلك كان لاعبو الشطرنج بحاجة إلى وصف حالة رقعة الشطرنج والحركات التي يجريها وصفًا لا لبس فيه. تمثل الفراغات في رقعة الشطرنج في التأشير الجبري Algebraic chess notation بإحداثيات تتألف من حرف ورقم كما في الشكل 5-1. الشكل 5-1: إحداثيات رقعة الشطرنج في التأشير الجبري تُعرّف قطع الشطرنج بالأحرف: K للملك king، و Q للملكة queen (يسميها البعض بالوزير)، و R للقلعة rook، و B للفيل bishop، و N للحصان knight. أما الجنود فلا رمز لهم. يكون وصف الحركات متألفًا من الحرف الذي يمثل القطعة، وإحداثيات الوجهة. وزوج من تلك الحركات يصف ما يحدث في دورٍ واحد (بفرض أن صاحب اللون الأبيض يبدأ أولًا)؛ فمثلًا التأشير 2. Nf3 Nc6 يعني أن الأبيض حرك الحصان إلى f3 والأسود حرك الحصان إلى c6 في الدور الثاني من اللعبة. هنالك المزيد من القواعد للتأشير الجبري للشطرنج، لكن الفكرة التي أحاول إيصالها هي أننا نستطيع وصف لعبة الشطرنج دون الحاجة إلى أن نكون أمام رقعة، ويمكن أن يكون خصمك في الطرف الثاني من الكوكب، وإذا كانت لديك ذاكرة ومخيلة جيدة فلا تحتاج إلى رقعة شطرنج حقيقية من الأساس: فيمكنك أن تقرأ الحركات من الرسائل البريدية وتحدِّث الرقعة الموجودة في مخيلتك! تمتلك الحواسيب ذواكر رائعة، فيمكن أن يخزن الحاسوب مليارات السلاسل النصية من الشكل '2. Nf3 Nc6'، وبهذا يمكن أن تلعب الحواسيب الشطرنج دون لوحة حقيقية؛ فما تفعله الحواسيب هو نمذجة البيانات لتمثيل رقعة الشطرنج، ويمكنك كتابة شيفرة تفعل ذلك بنفسك. هنا تلعب القوائم والقواميس دورها، فمثلًا القاموس {'1h': 'bking', '6c': 'wqueen', '2g': 'bbishop', '5h': 'bqueen', '3e': 'wking'} يمثل الرقعة في الشكل 5-2: الشكل 5-2: رقعة شطرنج منمذجة وفق قيمة قاموس لكن لمثالنا القادمة سنستعمل لعبة أسهل وأبسط من الشطرنج وهي لعبة إكس-أو. لعبة إكس-أو لعبة إكس-أو (تسمى بالإنكليزية tic-tac-toe) تشبه رمز # كبير فيه 9 خانات يمكن أن تكون قيمها X أو O أو أن تكون فارغة. لتمثيل هذه الرقعة بقاموس، فيجب أن نسند لكل خانة زوجًا من المفتاح-القيمة كما في الشكل 5-3. الشكل 5-3: خانات رقعة إكس-أو مع المفاتيح الموافقة لها يمكنك استخدام القيم النصية لتمثيل ما هو موجود في كل خانة في الرقعة: 'x' أو 'o' أو ' ' (فراغ)، وبالتالي نحتاج إلى تسع سلاسل نصية، يمكنك استخدام قاموس من القيم لهذا الأمر، فالقيمة النصية المرتبطة مع المفتاح 'top-R' تمثل القيمة في الركن العلوي الأيمن، والسلسل النصية المرتبطة مع المفتاح 'low-L' تمثل الركن السفلي الأيسر، والسلسلة النصية المرتبطة مع المفتاح 'mid-m' تمثل المنتصف، وهلم جرًا للبقية. هذا القاموس هو بنية معطيات تمثل رقعة لعبة إكس-أو، ولنخزن هذا القاموس في متغير باسم theBoard، ولنحفظ الشيفرة الآتية في ملف باسم ticTacToe.py: theBoard = {'top-L': ' ', 'top-M': ' ', 'top-R': ' ', 'mid-L': ' ', 'mid-M': ' ', 'mid-R': ' ', 'low-L': ' ', 'low-M': ' ', 'low-R': ' '} بنية المعطيات المخزنة في المتغير theBoard تمثل رقعة إكس-أو الموضحة في الشكل 5-4. الشكل 5-4: لوحة إكس-أو فارغة ولما كانت قيمة كل مفتاح في القاموس theBoard هي فراغ واحد فيمثل ذاك القاموس رقعةً فارغةً تمامًا. وإذا بدأت اللاعب X واختار الخانة في المنتصف تمامًا فسيصبح القاموس الذي يمثل الرقعة على الشكل: theBoard = {'top-L': ' ', 'top-M': ' ', 'top-R': ' ', 'mid-L': ' ', 'mid-M': 'X', 'mid-R': ' ', 'low-L': ' ', 'low-M': ' ', 'low-R': ' '} أصبحت بنية المعطيات theBoard تمثل الرقعة الموضحة في الشكل 5-5. الشكل 5-5: الحركة الأولى وتكون رقعة ربح فيها اللاعب O بوضع الشكل O في الصف العلوي كما يلي: theBoard = {'top-L': 'O', 'top-M': 'O', 'top-R': 'O', 'mid-L': 'X', 'mid-M': 'X', 'mid-R': ' ', 'low-L': ' ', 'low-M': ' ', 'low-R': 'X'} وهي ممثلة في الشكل 5-6. الشكل 5-6: ربح اللاعب O وبالتأكيد لا يستطيع أن يرى اللاعب إلا ما يطبع على الشاشة أمامه، ولا يعرف محتويات المتغيرات، فلننشئ دالةً تطبع القاموس الذي يحتوي على الرقعة على الشاشة. أضف ما يلي إلى ملف ticTacToe.py: theBoard = {'top-L': ' ', 'top-M': ' ', 'top-R': ' ', 'mid-L': ' ', 'mid-M': ' ', 'mid-R': ' ', 'low-L': ' ', 'low-M': ' ', 'low-R': ' '} def printBoard(board): print(board['top-L'] + '|' + board['top-M'] + '|' + board['top-R']) print('-+-+-') print(board['mid-L'] + '|' + board['mid-M'] + '|' + board['mid-R']) print('-+-+-') print(board['low-L'] + '|' + board['low-M'] + '|' + board['low-R']) printBoard(theBoard) حينما تشغل هذا البرنامج فستطبع رقعة إكس-أو فارغة: | | -+-+- | | -+-+- | | يمكن أن تتوالى الدالة printBoard() أي بنية معطيات تمثل رقعة إكس-أو تمررها إليها، جرب تغيير الشيفرة إلى ما يلي: theBoard = {'top-L': 'O', 'top-M': 'O', 'top-R': 'O', 'mid-L': 'X', 'mid-M': 'X', 'mid-R': ' ', 'low-L': ' ', 'low-M': ' ', 'low-R': 'X'} def printBoard(board): print(board['top-L'] + '|' + board['top-M'] + '|' + board['top-R']) print('-+-+-') print(board['mid-L'] + '|' + board['mid-M'] + '|' + board['mid-R']) print('-+-+-') print(board['low-L'] + '|' + board['low-M'] + '|' + board['low-R']) printBoard(theBoard) ستعرض الرقعة الآتية على الشاشة: O|O|O -+-+- X|X| -+-+- | |X ولأنك أنشأت بنية معطيات تمثل لوحة إكس-أو وكتبت الشيفرة في printBoard() التي تفسر بنية المعطيات وتظهر الرقعة، فأنت كتبت برنامجًا «ينمذج» models رقعة إكس-أو. كان بإمكانك تنظيم البيانات في بنية المعطيات بطريقة مختلفة، فمثلًا يمكنك استخدام المفتاح 'TOP-LEFT' بدلًا من 'top-L'، لكن طالما كانت شيفرتك تعمل مع بنية المعطيات التي لديك، فأنت كتبت عملية النمذجة بشكل صحيح. فمثلًا تتوقع الدالة printBoard() أن بنية المعطيات التي تمثل الرقعة هي قاموس فيه مفاتيح لجميع الخانات التسع، لكن إن كان في قاموسك مفتاحٌ ناقص وليكن 'mid-L' فلن يعمل برنامجك: O|O|O -+-+- Traceback (most recent call last): File "ticTacToe.py", line 10, in <module> printBoard(theBoard) File "ticTacToe.py", line 6, in printBoard print(board['mid-L'] + '|' + board['mid-M'] + '|' + board['mid-R']) KeyError: 'mid-L' لنضف الآن الشيفرة التي تسمح للاعبين بإدخال حركاتهم. لنعدل برنامجنا ليبدو كما يلي: theBoard = {'top-L': ' ', 'top-M': ' ', 'top-R': ' ', 'mid-L': ' ', 'mid-M': ' ', 'mid-R': ' ', 'low-L': ' ', 'low-M': ' ', 'low-R': ' '} def printBoard(board): print(board['top-L'] + '|' + board['top-M'] + '|' + board['top-R']) print('-+-+-') print(board['mid-L'] + '|' + board['mid-M'] + '|' + board['mid-R']) print('-+-+-') print(board['low-L'] + '|' + board['low-M'] + '|' + board['low-R']) turn = 'X' for i in range(9): ➊ printBoard(theBoard) print('Turn for ' + turn + '. Move on which space?') ➋ move = input() ➌ theBoard[move] = turn ➍ if turn == 'X': turn = 'O' else: turn = 'X' printBoard(theBoard) الشيفرة الجديدة تطبع اللوحة في بداية كل دور ➊ ثم تطلب المدخلات من اللاعب الحالي ➋ ثم تحدث الرقعة وفقًا لذلك ➌ ثم تبدل اللاعب الحالي ➍ قبل الانتقال إلى الدور القادم. | | -+-+- | | -+-+- | | Turn for X. Move on which space? mid-M | | -+-+- |X| -+-+- | | --snip-- O|O|X -+-+- X|X|O -+-+- O| |X Turn for X. Move on which space? low-M O|O|X -+-+- X|X|O -+-+- O|X|X صحيحٌ أن البرنامج ليس لعبة إكس-أو كاملة، فلن يتحقق إن ربح أحد اللاعبين مثلًا؛ لكنه كافٍ لمعرفة كيفية استخدام بنى المعطيات في برامج حقيقية. القواميس والقوائم المتشعبة نمذجة لوحة إكس-أو هو أمر سهل: تحتاج اللوحة إلى قاموس فيه 9 مفاتيح تمثل خاناتها. لكن إن أردت نموذج أمور أكثر تعقيدًا فستجد أنك تحتاج إلى القواميس والقوائم التي تحتوي على قواميس وقوائم أخرى داخلها. تناسب القوائم تخزين سلسلة مرتبة من القيم، بينما تفيد القواميس بتخزين قواميس التي ترتبط فيها المفاتيح مع القيم. هذا مثال يستعمل قاموسًا يحتوي على قواميس داخله فيها الأغراض التي أتى بها الضيوف إلى الرحلة. يمكن أن تقرأ الدالة totalBrought() بنية المعطيات وتحسب العدد الكلي للعناصر المجلوبة من كل الضيوف: allGuests = {'Alice': {'apples': 5, 'pretzels': 12}, 'Bob': {'steak sandwiches': 3, 'apples': 2}, 'Carol': {'cups': 3, 'apple pies': 1}} def totalBrought(guests, item): numBrought = 0 ➊ for k, v in guests.items(): ➋ numBrought = numBrought + v.get(item, 0) return numBrought print('Number of things being brought:') print(' - Apples ' + str(totalBrought(allGuests, 'apples'))) print(' - Cups ' + str(totalBrought(allGuests, 'cups'))) print(' - Cakes ' + str(totalBrought(allGuests, 'cakes'))) print(' - Steak Sandwiches ' + str(totalBrought(allGuests, 'steak sandwiches'))) print(' - Apple Pies ' + str(totalBrought(allGuests, 'apple pies'))) داخل الدالة totalBrought() هنالك حلقة for تدور على أزواج مفتاح-قيمة في المتغير guests ➊، وسنسند داخل الحلقة اسم كل ضيف إلى المتغير k، وسنسند القاموس الذي يحتوي على قائمة الأغراض التي سيجلبها معه إلى الرحلة إلى المتغير v. إذا كان أحد المعامل item موجودة في القاموس، فستضاف قيمته (كمية الأغراض المجلوبة) إلى المتغير numBrought ➋، لكن إذا لم يكن المفتاح موجودًا فيسعيد التابع get() القيمة 0 لإضافتها إلى numBrought. سيكون ناتج تنفيذ البرنامج كما يلي: Number of things being brought: - Apples 7 - Cups 3 - Cakes 0 - Steak Sandwiches 3 - Apple Pies 1 قد يبدو لك أن حالة الاستخدام السابقة بسيطة ولا حاجة إلى نمذجتها، لكن فكر أن الدالة totalBrought() يمكن أن تتعامل بسهولة مع قاموس يحتوي على آلاف الضيوف، وكل ضيف يجلب آلاف العناصر، وتنظيم هذه المعلومات في بنية معطيات واضحة ووجود الدالة totalBrought() سيوفر عليك وقتًا كثيرًا. يمكنك أن تنمذج العناصر في بنى المعطيات بالطريقة التي تراها مناسبة، لطالما كانت بقية الشيفرة في برنامج قادرةً على التعامل مع بنية المعطيات المنشأة. حينما تبدأ البرمجة فلا تقلق أن تنمذج البيانات بالطريقة «الصحيحة»، فكلما ازدادت خبرتك أصبحت تخطر ببالك طرائق أكثر فاعلية وكفاءة للنمذجة، لكن أهم ما في الأمر أن تعمل بنية المعطيات مع احتياجات برنامجك. الخلاصة يمكن أن تحتوي القوائم والقواميس على عدّة قيم، بما فيها قوائم وقواميس أخرى. القواميس مفيدة لأنك تستطيع ربط مفتاح معين مع قيمة، على عكس القوائم التي هي سلسلة من القيم المرتبة. يمكن الوصول إلى القيم داخل القاموس عبر استخدام الأقواس المربعة كما في القوائم، لكن بدلًا من استخدام فهرس رقمي فيمكن أن تكون المفاتيح في القواميس من مختلف القيم سواءً كانت أعدادًا صحيحةً أو أعدادًا عشريةً أو سلاسل نصية أو صفوف tuples. يمكنك تمثيل الكائنات الحقيقية بتنظيم قيم البرنامج في بنى المعطيات، ورأينا مثال ذلك عمليًا على لعبة إكس-أو. مشاريع تدريبية لكي تتدرب، اكتب برامج لتنفيذ المهام الآتية. مدقق لقواميس الشطرنج استعملنا في هذا المقال قيمةً مثل {'1h': 'bking', '6c': 'wqueen', '2g': 'bbishop', '5h': 'bqueen', '3e': 'wking'} لتمثيل رقعة الشطرنج. اكتب دالةً باسم isValidChessBoard() التي تقبل وسيطًا هو قاموس وتعيد القيمة True أو False اعتمادًا إن كان القاموس صالحًا لتمثيل رقعة الشطرنج. تحتوي الرقعة السليمة على ملك أسود واحد وملك أبيض واحد. ويمكن لأيٍ من اللاعبين امتلاك 16 قطعة كحد أقصى، و 8 جنود كحد أقصى، ويجب أن تكون جميع القطع في المجال بين 1a و 8h، أي لا يمكن أن تكون القطعة في المكان 9z. يجب أن تبدأ أسماء القطع بحرف w أو b لتمثيل اللونين الأبيض أو الأسود، متبوعًا بإحدى الكلمات pawn أو knight أو bishop أو rook أو queen أو king. قائمة الأدوات في لعبة نحن نعمل على لعبة فيها قائمة أدوات يمكن أن يمتلكها اللاعب، والتي سننمذجها باستخدام بنية معطيات تتألف من قاموس تكون فيه مفاتيحه هي سلاسل نصية تصف القيمة الموجودة في قائمة الأدوات، وقيمتها هي عدد نصي يمثل عدد الأدوات التي يمتلكها اللاعب مثلًا القاموس {'rope': 1, 'torch': 6, 'gold coin': 42, 'dagger': 1, 'arrow': 12} تعني أن اللاعب يملك حبلًا واحدًا، و 6 شعلات، و 42 قطعة ذهبية …إلخ. اكتب دالةً باسم displayInventory() التي تأخذ أي قاموس يمثل قائمة أدوات ويعرضه بالشكل: Inventory: 12 arrow 42 gold coin 1 rope 6 torch 1 dagger Total number of items: 62 تلميح: يمكنك استخدام حلقة for للمرور على جميع المفاتيح في القاموس: # inventory.py stuff = {'rope': 1, 'torch': 6, 'gold coin': 42, 'dagger': 1, 'arrow': 12} def displayInventory(inventory): print("Inventory:") item_total = 0 for k, v in inventory.items(): # أكمل الشيفرة هنا print("Total number of items: " + str(item_total)) displayInventory(stuff) دالة تحويل قائمة إلى قاموس في لعبة لنفترض أن لاعبنا في اللعبة السابقة قد حصل على غنيمة ممثلة في القائمة الآتية: playerLoot = ['gold coin', 'dagger', 'gold coin', 'gold coin', 'ruby'] اكتب دالةً باسم addToInventory(inventory, addedItems) حيث أن المعامل inventory هو قاموس يمثل قائمة أدوات اللاعب (كما في المثال السابق) والمعامل addedItems يشبه المتغير playerLoot. يجب أن تعيد الدالة addToInventory() قاموسًا يمثل قائمة الأدوات المحدثة. لاحظ أن القائمة الموجودة في addedItems قد تحتوي على عدة نسخ من نفس الأداة. يفترض أن تكون شيفرتك شبيهة بما يلي: def addToInventory(inventory, addedItems): # اكتب الدالة هنا inv = {'gold coin': 42, 'rope': 1} dragonLoot = ['gold coin', 'dagger', 'gold coin', 'gold coin', 'ruby'] inv = addToInventory(inv, dragonLoot) displayInventory(inv) يجب أن يظهر البرنامج السابق (مع الدالة displayInventory() من المثال السابق) الناتج الآتي: Inventory: 45 gold coin 1 rope 1 ruby 1 dagger Total number of items: 48 ترجمة -بتصرف- للفصل Dictionaries And Structuring DATA من كتاب Automate the Boring Stuff with Python. اقرأ أيضًا المقال السابق: القوائم Lists في لغة بايثون أنواع البيانات والعمليات الأساسية في لغة بايثون تعلم لغة بايثون النسخة العربية الكاملة لكتاب البرمجة بلغة بايثون1 نقطة
-
أولاً يجب تفهم أنك ستحتاج إلى 4 أو 5 أضعاف وقت الدورة من أجل دراستها بشكل سليم، وذلك ما بين مشاهدة ثم استيعاب ثم حفظ ثم تطبيق ثم مراجعة وتكرار وبحث. عليك بالتالي: مشاهدة 4 دروس قصيرة ثم التوقف والتطبيق على ما جاء بها من خلال إعادة ما قام به المدرب. أو درس واحد طويل وتقسيمه إلى أجزاء والتوقف ثم التطبيق بمفردك. ولا مشكلة في التطبيق مع المدرب، لكن بعد الإنتهاء عليك إعادة ما قمت به بمفردك لكي تختبر استيعابك وتركيزك يُصبح أكبر. (خصص نسخة للتطبيق مع الشرح مثلاً ونسخة أخرى للتطبيق عليها بمفردك). والمهم هو ألا تقوم بخطوة دون معرفة لماذا قمت بها، فالبرمجة ليست نسخ أكواد بل وظيفتك هي حل مشاكل برمجية لذا استيعابك للأدوات واللغة نقطة فارقة للمبرمج المتميز. وهناك مثال جيد هو "يمكنك مشاهدة فيلم لكن لن تصبح مخرج أفلام" لذا عليك بالممارسة العملية وأن تكون طالب فاعل وليس مشاهد سلبي فقط، يجب التدرب على نماذج صغيرة في البداية ثم التدرج في الصعوبة وإنشاء مشاريع كاملة، وعدم الإكتفاء بمشاريع الدورة ونماذجها فقط. وفي الدورة لا تكتفي ببناء المشروع مرة واحدة فقط، حاول إعادة بنائه بمفردك، ولا مشكلة أبدًا إذا نسيت بعض الأشياء لا تنزعج من ذلك إطلاقًا. فمرة واحدة لا تكفي أبدًا، حيث أنك في المرة الأولى تستوعب بنسبة 70% وأنت بحاجة إلى الـ 30% الأخرى والتي تحصل عليها من خلال إعادة بناء المشروع بمفردك بدون مشاهدة شرح المدرب. وبالطبع ليس عليك تذكر كل شيء قمت بدراسته ولكن يجب استيعاب كل شيء تقريبًا بنسبة 80% وبعض الأمور ستتضح لك من الواقع العملي بعد فترة وتنفيذ المشاريع. فلا أحد يتذكر كل شيء ويتم البحث عن ما نريده ويتم تذكر الأمر لأنك تعرف ما تريد البحث عنه، لكن الحفظ والاستيعاب مهمان في البداية.1 نقطة