المتابعون للمدونة

الجمعة، 20 ديسمبر 2013

طالب مندس!!


طالب مندس!!

 

من أطرف المواقف التي حدث لي، أنني كنت معتادا على الذهاب لمقابلة صديقي م. محمد الزيني في كلية حاسبات ومعلومات القاهرة، وأحيانا كنت أحضر معه بعض المحاضرات أو حصص التمارين (السكاشن).. وفي إحدى هذه المرات كان عليهم امتحان في مادة التصميم المنطقي Logic Design، ونظرا لأني كنت قد درست هذه المادة في كلية الهندسة في العام السابق، فقد قررت أن أحضر معهم الامتحان.. وبالفعل أخذت ورقة أسئلة، وبدأت أحل اعتمادا على ما أتذكره من عام مضى، ولإكمال الطرافة، كتبت اسمي على الورقة وسلمتها J

طبعا لم أحصل على نصف الدرجات وإن كدت، لكن المفاجأة أن درجتي جاءت أعلى من تلك التي حصل عليها الزيني :))، وهو الأمر الذي كاد يصيبه بالجنون :)

والأطرف من هذا أن أستاذة المادة أخذت تنادي على اسمي في المحاضرة التالية لتعرف ورقة من هذه، وكيف لا يوجد هذا الاسم في قائمة طلابها، وهل يوجد أحد يعرفه أم لا.. وطبعا كتم الزيني وأصدقاؤه الذين يعرفونني من المدينة الجامعية ضحكاتهم بصعوبة!

 

الخميس، 12 ديسمبر 2013

إلغاء عجلة الفأرة في الأداة NumericUpDown


س: عند تحريك عجلة الفأرة أثناء وجود المؤشر Focus داخل الأداة NumericUpDown يتم إنقاص أو زيادة العدد الذي تعرضه الأداة.. فكيف يمكن منع هذا؟ 

ج: المكان المناسب لتعطيل أي وظيفة تؤديها عجلة الفأرة في أي أداة، هو الحدث MouseWheel.. لكن المعامل الثاني e لهذا الحدث من النوع MouseEventArgs، وهو لا يمتلك الخاصية Handled التي يمكن جعل قيمتها True لإلغاء الحدث.. فما العمل؟

المفاجأة هي أن المعامل e في الحدث MouseWheel (في كل الأدوات) هو في الحقيقة من نوع الفئة HandledMouseEventArgs التي تمتلك الخاصية Handled، لكن لسبب ما قررت ميكروسوفت أن تخفي عنك هذه الحقيقة وتكتب نوع المعامل من الفئة الأم MouseEventArgs.. لهذا كل ما عليك فعله هو تحويل نوع المعامل e إلى نوعه الأصلي، واستخدام الخاصية Handled الخاصة به لإلغاء حدث تحريك عجلة الفأرة كالتالي:

CType(e, HandledMouseEventArgs).Handled = True
وهذا هو كل شيء!

 

ملحوظة:

إذا أردت أيضا أن تمنع المستخدم من تغيير العدد المعروض في الأداة NumericUpDown عند ضغط السهم العلوي أو السهم السفلي من لوحة المفاتيح، فكل ما عليك هو وضع القيمة False في الخاصية InterceptArrowKeys:

NumericUpDown.InterceptArrowKeys = False

 

 

الاثنين، 9 ديسمبر 2013

لحظة عشق 1



(اضغط الصورة لتكبيرها)

 

لقراءة القصيدة كاملة:


للاستماع لإلقائي للقصيدة:


لتحميل ديوان دلال الورد:


 

 

 

 

 

الأحد، 8 ديسمبر 2013

تطوير لبرنامج لمحاكاة إلقاء العملة


تطوير لبرنامج لمحاكاة إلقاء العملة المعدنية
لدراسة احتمال الحصول على 100 صورة متتالية 

في الموضوع السابق شرحت فكرة إنشاء برنامج يحاكي عملية إلقاء عملة، ويدرس عدد الصور المتوالية التي يمكن الحصول عليها.

ذلك البرنامج كان يركز على حساب أقصى عدد من الصور يمكن الوصول إليه، لهذا كان يتجاهل بعض النتائج الأقصر من أقصى عدد حصلنا عليه، كما كان يتجاهل عدد مرات تكرار نفس النتيجة.

وقد قررت تطوير هذا البرنامج ليعطي صورة أشمل لمن يريد دراسة هذه الاحتمالات (على الأقل سيكون مفيدا كبرنامج توضيحي للطلاب الذين يدرسون علم الإحصاء).. لهذا جعلت البرنامج يأخذ في الاعتبار كل النتائج وعدد مرات تكرارها كما في الصورة:
 
 
يمكنكم تحميل كود هذا البرنامج من هنا:


الملاحظة الواضحة التي ستبرز لمن يدرس النتائج، هي أي التتابعات الأقصر للصور تحدث أسرع، وتتكرر أكثر.. فالحصول على صورة منفردة يحدث من أول بضع محاولات، ويتكرر ملايين المرات، والنسبة المئوية تظهر أن الصورة المنفردة تستأثر بحوالي نصف عدد النتائج التي نحصل عليها.. لاحظ أنني أحسب هذه النسبة المئوية بالقسمة على مجموع النتائج (مجموع القيم الموجودة في العمود "تكرار الحدوث").

ستلاحظ أيضا أن عدد مرات التكرار يقل إلى النصف كلما زدت عدد الصور المتتابعة بواحد.. فحدوث صورتين متتاليتين يستأثر بربع عدد النتائج.. وحدوث ثلاث صور متتابعة يستأثر بثمن عدد النتائج.. وهكذا يستمر القسمة على 2 كلمات زدنا عدد الصور المتتابعة بواحد.. وهذا ما يجعل مرات التكرار يقل بشكل أسي سريع، وهو ما يفسر لك لماذا يصير الحصول على عدد أكبر من الصور المتتابعة أصعب.. فالحصول على 6 صور متتابعة لم يحظ بأكثر من  1.25% من النتائج.. والحصول على 10 صور متتابعة شكّل أقل من 1 في الألف من النتائج.. أما حدوث 20 صورة متتابعة، فكان نصيبه حوالي 1 في المليون من النتائج!.. وكما تتوقع: حدوث 30 صورة متتالية نصيبه 1 في المليار من النتائج.. لاحظ أن زيادة 10 يعني القسمة على 2 عشر مرات.. 2 أس 10 يساوي 1024 ، ويمكننا اعتبار أنها تساوي 1000 للتسهيل.. هذا معناه أن كل 10 صور نضيفها للصور المتتابعة تقسم النسبة المئوية للناتج على 1000.. لهذا نتوقع أن تكون نسبة 40 صورة متتالية في النتائج هي 1 في التريليون، ونسبة 50 صورة هي 1/10 أس 15، ونسبة 60 صورة هي 1/10 أس 18، ونسبة 100 صورة  هي 1/10 أس 30، وهي النسبة التي أثبتنا مرارا وتكرارا أنها تساوي صفرا ولا يكفي عمر الكون لتوفير عدد كاف من المحاولات يجعلها تحدث.

 

ملاحظات:

- هذه النسخة المطورة من البرنامج أسرع من النسخة السابقة، حيث يمكنها تنفيذ حوالي 1.3 مليون محاولة في الثانية.. لكن لا تعتمد على هذا، فهو لن يقلل من مليارات السنين المنتظرة للحصول على 100 صورة متتابعة شيئا يذكر J

-  أقصى عدد من الخانات العشرية سمحت للبرنامج بعرضه في عمود نسبة التكرار، هو 15 خانة.. هذا معناه أن النسب المئوية الأصغر من هذا والتي تحتاج خانات عشرية أكثر، سيتم تقريبها إلى صفر.. لكن لكي ترى هذا، يجب أن تنتظر إلى أن يحدث تتابع أكثر من 50 صورة متتالية، وهو أمر يحتاج إلى ترك البرنامج يعمل لحوالي 27 سنة متواصلة لكي يكون حدوثه محتملا!

-  نظرا لأن النتائج لا تأتي بالترتيب، فمن الممكن أن يحدث تتابع 10 صور قبل أن يحدث تتابع 9 صور، فقد ظهرت الحاجة لترتيب النتائج (سابقا كنا نتجاهل النتيجة الأقصر لأننا نبحث عن النتائج التي تحوي أطول تتابع من الصور).. لهذا أضفت للبرنامج الفئة SortableBindingList لاستخدامها كمصدر ربط مع جدول العرض، بحيث يمكن ترتيب النتائج التي يعرضها.

-  لكي يمكن تحديث عدد مرات تكرار كل نتيجة، استخدمت قاموسا Dictionary، مفتاحه هو عدد مرات تتابع الصور، وقيمته هي البيانات الخاصة بالنتيجة المحفوظة كائن من نوع الفئة PictureInfo.. أي أننا صرنا نتعامل مع قاموس من النوع:

Dictionary(Of Integer, PictureInfo)

هذا القاموس لا يصلح كمصدر بيانات لجدول العرض، لهذا حصلنا منه على قائمة تصلح للربط كالتالي:

Coins.PicsInfo.Values.ToList

حيث إن الخاصية Values الخاصة بالقاموس تعيد مجموعة Collection تحتوي على كل القيم المحفوظة في القاموس (بدون المفاتيح).. لكن هذه المجموعة لا تصلح أيضا كمصدر ربط، لهذا حولناها إلى قائمة باستخدام الوسيلة ToList.

وستجد أننا أرسلنا التعبير السابق إلى حدث إنشاء الفئة SortableBindingList للحصول على قائمة قابلة للترتيب.

 

 

 

الجمعة، 6 ديسمبر 2013

الترتيب التلقائي لأعمدة DataGridView


س: عند ربط جدول العرض DataGridView بقائمة List فإن ضغط رؤوس الأعمدة لا يؤدي إلى إعادة ترتيب الجدول.. فلماذا؟.. وكيف يمكن حل هذه المشكلة؟ 

ج: عند ضغط رأس العمود لتنفيذ الترتيب التلقائي لجدول العرض تبعا لقيم هذا العمود، يطلب جدول العرض من مصدر البيانات DataSource المرتبط به أن يقوم هو بتنفيذ عملية الترتيب تبعا للخاصية التي يرتبط بها العمود المضغوط.. أي أن جدول العرض لا ينفذ أي شيء بنفسه.. لهذا يجب أن يكون مصدر البيانات قابلا للترتيب IsSortable = True.. وهذا غير متوفر في القوائم Lists والمجموعات Collections ولا حتى في قائمة الربط BindingList.

وبتتبع الأكواد التي تستخدمها ميكروسوفت في LinQ To SQL وجدت أنها تستخدم فئة خاصة اسمها SortableBindingList لتسمح بالترتيب عند عرضها في جدول العرض.. لكن الغريب أن ميكروسوفت جعلت هذه الفئة خاصة، ولا يمكن للمبرمج استخدامها.. لهذا عليك أن تكتب كود هذه الفئة بنفسك في مشاريعك.

وستجد كود هذه الفئة في هذا المشروع:


واستخدامها بسيط جدا، فهي فئة عامة Generic Type، يمكنك أن تخصصها لأي نوع تتعامل معه من البيانات، وليس عليك أكثر من أن ترسل إلى حدث إنشائها Constructor القائمة التي تريد أن تمنحها إمكانية الترتيب.. وستجدنا نستخدمها في المشروع المشار إليه على الصورة:

Dim SortedList As New SortableBindingList(

                               Of PictureInfo)(Coins.PicsInfo.Values.ToList)

DataGridView1.DataSource = SortedList

حيث:

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

- Coins.PicsInfo.Values هو مجموعة Collection تحتوي على عناصر من النوع PictureInfo.. ولتحويلها إلى قائمة استخدمنا الوسيلة الإضافية ToList، وهي الوسيلة التي ستستخدمها في الغالب لإرسال القائمة إلى حدث إنشاء الفئة SortableBindingList، لتحويل المجموعات العائدة من نتائج استعلامات LinQ إلى قوائم.

هذا كل شيء.. بعد هذا جعلنا مجموعة الربط القابلة للترتيب مصدر بيانات جدول العرض بإرسالها إلى الخاصية DataGridView.DataSource.. الآن يمكنك ترتيب الجدول تبعا لأي عمود فيه بمجرد ضغط العمود بدون كتابة أي كود إضافي.

ولا تسلني مرة أخرى لماذا لم تمنحنا ميكروسوفت هذه الإمكانية مباشرة ما دامت موجودة في إطار العمل وقررت أن تخفيها عنا، فأنا لا أعلم!

 

ملحوظة:

في الفئة SortableBindingList ستجد أنني حولت جزءا من الكود إلى تعليق في حدث إنشاء الفئة الداخلية PropertyComparer.. هذا الجزء من الكود سبب معي خطأ عندما كنت أتعامل مع نوع بيانات موروث من نوع آخر، لأن هذا الكود اعتبر أن الصفات الموروثة ليست خاصة بهذا النوع!!.. وقد وجدت أنه لا ضرورة لهذا الكود فحذفته، وعملت الفئة بعد ذلك على ما يرام!

 

الأربعاء، 4 ديسمبر 2013

ابتســــــامــة


ابتســــــامــة

 

بدرٌ مُضيءٌ ضاحكٌ، في سِحرِ طِيبتِهِ بَشاشةْ
في لَمحةٍ ما غيرُها، سهمًا رَمى عُمري فَناشَهْ
يا مَنْ سَبَتْ قلبَ الفتى مِن خلفِ حاسوبٍ وشاشةْ!
لَعِبَ الجمالُ بعقلِهِ وصوابَهُ عمدًا أطاشَهْ
فإذا لِفَرطِ جنونِهِ أمسَى كتوفيقٍ عكاشةْ!!
يا مَن خُطِفتُ بحُسنِها واستوطَنتْ صَدري ارتعاشةْ
قلبي غدا كَهُرَيرةٍ، أَجْمِلْ بكفّيكِ انكماشَهْ!
عيناكِ أنوارُ المَدَى، شوقي يُلبيها فَراشةْ
إنّي بِنارِكِ مُسهدٌ وعَذَرتُ مَن جافَى فِراشَهْ
يا لابتسامتِكِ التي كالنهرِ إذ يَروي عِطاشَهْ
أتَرَكْتِ ثَغري ظامئًا وزهورُ خدّيكِ انتعاشةْ؟
يا لؤلؤا أغرَى بهِ: ماذا عن الشفتينِ حاشَهْ؟
شفتاكِ قطعةُ سكّرٍ وتذوبُ من فَرطِ الهشاشةْ
هلاّ أجبتِ مُحيَّرًا لم يُبقِ مِن لَهَفٍ حُشاشةْ:
هل حلمُهُ فيكِ اهتدَى أم أنّهُ في الوهمِ عاشَهْ؟


محمد حمدي غانم

11/8/2013

برنامج لمحاكاة إلقاء العملة المعدنية


برنامج لمحاكاة إلقاء العملة المعدنية
لدراسة احتمال الحصول على 100 صورة متتالية
 

تطرقت في كتاب "خرافة داروين" إلى هذه المسألة، كمدخل بسيط ومختصر لكيفية حساب الاحتمالات، أدلل به على استحالة أن تصنع الصدفة أي شيء مركّب، مفيدا كان أو غير مفيد.. وأثبتّ رياضيا أن الحصول على مئة صورة متتالية عند إلقاء العملة المعدنية هو أمر مستحيل، حتى لو ظل كل سكان كوكب الأرض البالغ عددهم 7 مليارات إنسان، يلقون العملة المعدنية بمعدل مرة في الثانية لمدة 300 مليار سنة!!

السبب في هذا أن هذا الاحتمال يساوي 1/2 أس 100، أي 1/1267650600228229401496703205376، وهو يساوي صفرا بلا جدال، لأن الرقم الموجود في المقام أكبر من تصوراتنا العلمية للمالانهاية، ويعجز الحاسوب عن محاكاته ولو بمجرد العد (أثبتّ هذا برمجيا أيضا في الكتاب نفسه).

لكن نظرا لأن غير المتخصصين قد يتشككون في هذه الاحتمالات ويعجزن عن تخيل فداحة هذه الأرقام التي تتكون من أكثر من 30 خانة عشرية، قررت أن أكتب برنامجا يحاكي عملية إلقاء عملة معدنية، ويسجل عدد مرات تكرار الصور على التوالي.

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

يمكنكم تحميل كود البرنامج من هنا:


والآن دعونا نعلّق على هذا البرنامج.. سيكون لدينا هنا تعليق خاص للمبرمجين، وتعليق عام على فكرة الصدفة والعشوائية التي كتبنا البرنامج من أجلها.

صفحة الشاعر