تطبيقات المرجع

مكتمل

يحدد التطبيق المرجعي مجموعة من الشروط للتحقق من صحة حل لمشكلة ما. تحدد مجموعة التطبيقات المرجعية الحلول المختلفة لمجموعة المشكلات للطلاب، وتسمح للمدرسين بالتحقق من صحة كود الطالب غير المنظم لصحة الخوارزمية. في PyBryt، تأخذ هذه المراجع شكل الكائن pybryt.ReferenceImplementation، الذي يضم سلسلة من التعليقات التوضيحية التي تؤكد الشروط على بصمة الذاكرة للإرسال.

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

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

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

لإنشاء تنفيذ مرجعي برمجيًا، كما سنقوم في هذه الوحدة، يتم جمع التعليقات التوضيحية في قائمة، والتي يتم تمريرها بعد ذلك إلى المنشئ pybryt.ReferenceImplementation مع اسم المرجع. لنقم ببناء مرجع لإيجاد متسلسلة هيلستون لرقم. ترجع الدالة hailstone التسلسل كقوائم وتحتوي على تعليقات توضيحية لتتبع تقدم إنشاء القائمة. ثم يتم تخزين التعليقات التوضيحية في hailstone_annotations.

hailstone_annotations = []

def hailstone(n: int) -> List[int]:
    if n == 1:
        ret = [n]
    elif n % 2 == 0:
        ret = [n] + hailstone(n // 2)
    else:
        ret = [n] + hailstone(3 * n + 1)

    hailstone_annotations.append(pybryt.Value(ret))
    return ret

دعونا نختبر تنفيذ hailstone. تقوم الدالة run_hailstone_test_cases بتشغيل بعض حالات الاختبار على دالة hailstone_fn، والتي تقوم بإرجاع تسلسل حصى رقم، وإعادة hailstone_annotations تعيين القائمة قبل كل تشغيل حتى لا نقوم بإنشاء تعليقات توضيحية مكررة. دعونا نستخدمها لاختبار hailstone:

def run_hailstone_test_cases(hailstone_fn):
    global hailstone_annotations
    hailstone_annotations = []

    assert hailstone_fn(9) == [9, 28, 14, 7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]
    assert hailstone_fn(50) == \
        [50, 25, 76, 38, 19, 58, 29, 88, 44, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]
    assert hailstone_fn(117) == \
        [117, 352, 176, 88, 44, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]

run_hailstone_test_cases(hailstone)

الآن دعونا ننشئ تطبيق مرجع باستخدام القائمة hailstone_annotations. استدعاء المرجع hailstone.

hailstone_ref = pybryt.ReferenceImplementation("hailstone", hailstone_annotations)

باستخدام مدير السياق pybryt.check، يمكننا تشغيل حالات الاختبار الخاصة بنا مقابل هذا التطبيق المرجعي للتحقق من أن كل شيء يعمل:

>>> with pybryt.check(hailstone_ref):
...     run_hailstone_test_cases(hailstone)
REFERENCE: hailstone
SATISFIED: True

استخدام تطبيقات مرجعية متعددة

الآن بعد أن فهمنا كيفية إنشاء مراجع فردية، دعنا نلقي نظرة على الجمع بين عدة مراجع. تتمثل إحدى أفكار PyBryt الأساسية في أن تكون مرنًا ومحايدًا لتنفيذ الطلاب، مما يسمح للمدرسين بكتابة تطبيقات مرجعية متعددة للتنوع هو أن الطلاب يمكنهم حل المشكلات. لإثبات هذه المرونة، دعنا ننشئ مرجعًا آخر لمتسلسلة هيلستون. استخدم التنفيذ السابق الإعادة لإنشاء القائمة من أسفل لأعلى، مما يعطينا سلسلة من التعليقات التوضيحية التي تبدو كما يلي:

>>> [hailstone_annotations[i].initial_value for i in range(len(hailstone_annotations)) if i < 20]
[[1],
 [2, 1],
 [4, 2, 1],
 [8, 4, 2, 1],
 [16, 8, 4, 2, 1],
 [5, 16, 8, 4, 2, 1],
 [10, 5, 16, 8, 4, 2, 1],
 [20, 10, 5, 16, 8, 4, 2, 1],
 [40, 20, 10, 5, 16, 8, 4, 2, 1],
 [13, 40, 20, 10, 5, 16, 8, 4, 2, 1],
 [26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1],
 [52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1],
 [17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1],
 [34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1],
 [11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1],
 [22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1],
 [7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1],
 [14, 7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1],
 [28, 14, 7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1],
 [9, 28, 14, 7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]]

لكن افترض أن الطالب قام بدلاً من ذلك ببناء القائمة بشكل متكرر، من أعلى إلى أسفل:

def iterative_hailstone(n: int) -> List[int]:
    ret = [n]
    while n != 1:
        if n % 2 == 0:
            n = n // 2
        else:
            n = 3 * n + 1
        ret.append(n)
        hailstone_annotations.append(pybryt.Value(ret))
    return ret

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

>>> with pybryt.check(hailstone_ref):
...     run_hailstone_test_cases(iterative_hailstone)
REFERENCE: hailstone
SATISFIED: False

لحل هذه المشكلة، دعنا نحول iterative_hailstone إلى مرجعها الخاص:

>>> iterative_hailstone_ref = pybryt.ReferenceImplementation("iterative_hailstone", hailstone_annotations)
>>> iterative_hailstone_ref
<pybryt.reference.ReferenceImplementation at 0x7fe4c242aa10>

لإجراء عمليات تحقق مقابل تطبيقات مرجعية متعددة، قم بتمرير قائمة منها. دعونا نتحقق من صحة مراجعنا القديمة والجديدة باستخدام pybryt.check؛ يجب أن نرى أن كل تطبيق يرضي أحد المراجع، مما يسمح لنا بالتحقق من نوعين مختلفين من التطبيقات!

>>> with pybryt.check([hailstone_ref, iterative_hailstone_ref]):
...     run_hailstone_test_cases(hailstone)
>>> print()
>>> with pybryt.check([hailstone_ref, iterative_hailstone_ref]):
...     run_hailstone_test_cases(iterative_hailstone)
REFERENCE: hailstone
SATISFIED: True

REFERENCE: iterative_hailstone
SATISFIED: False

REFERENCE: hailstone
SATISFIED: False

REFERENCE: iterative_hailstone
SATISFIED: True

‏‫اختبر معلوماتك

1.

لإنشاء تطبيق مرجعي، ما الذي يجب تمريره إلى المنشئ؟

2.

كم عدد التطبيقات المرجعية التي يمكنك استخدامها مع PyBryt؟

3.

كيف يمكنك اختباره ضد تطبيقات مرجعية متعددة؟