المسارات
/
Julia
Julia
/
التمارين
/
المخزن المؤقت الدائري
المخزن المؤقت الدائري

المخزن المؤقت الدائري

صعب

التعليمات

المخزن المؤقت الدائري، أو المخزن المؤقت الدوري، أو مخزن الحلقة، هو بنية بيانات تستخدم مخزنًا مؤقتًا واحدًا ثابت الحجم كما لو كان موصولًا من طرفه بطرَفه.

يبدأ المخزن المؤقت الدائري فارغًا وله طول محدد مسبقًا. على سبيل المثال، هذا مخزن من 7 عناصر:

[ ][ ][ ][ ][ ][ ][ ]

افترض أن العدد 1 كُتب في منتصف المخزن (لا يهم موضع البداية الدقيق في المخزن الدائري):

[ ][ ][ ][1][ ][ ][ ]

ثم افترض أنه أُضيف عنصران آخران، 2 و3، يُضافان بعد 1:

[ ][ ][ ][1][2][3][ ]

إذا أُزيل عنصران بعد ذلك من المخزن، فستُزال أقدم القيم الموجودة داخل المخزن. العنصران المُزالان في هذه الحالة هما 1 و2، ولا يبقى في المخزن سوى 3:

[ ][ ][ ][ ][ ][3][ ]

إذا احتوى المخزن على 7 عناصر فهو ممتلئ تمامًا:

[5][6][7][8][9][3][4]

عندما يمتلئ المخزن يُرفَع خطأ يُنبّه العميل إلى أن الكتابات الإضافية محجوبة حتى تتحرر خانة.

عندما يمتلئ المخزن، يمكن للعميل أن يختار الكتابة فوق أقدم البيانات بكتابة قسرية. في هذه الحالة يُضاف عنصران آخران، A وB، فيكتبان فوق 3 و4:

[5][6][7][8][9][A][B]

استُبدل 3 و4 بـA وB، فأصبح 5 هو أقدم بيانات في المخزن. وأخيرًا، إذا أُزيل عنصران فما سيُرجع هو 5 و6، ليصبح المخزن:

[ ][ ][7][8][9][A][B]

ولأن هناك مساحة متاحة، إذا استخدم العميل الكتابة فوق مرة أخرى لتخزين C وD، فسيُستخدم المكان الذي كان يخزّن فيه 5 و6 سابقًا، لا موضع 7 و8. لا يزال 7 أقدم عنصر، وقد امتلأ المخزن مرة أخرى.

[C][D][7][8][9][A][B]

المهام

عرّف نوعًا مركّبًا ذا معاملات CircularBuffer{T} يخزّن عناصر من النوع T، واكتب مُنشئًا

CircularBuffer{T}(capacity::Integer) where {T} -> CircularBuffer{T}

ينشئ نسخة يمكنها تخزين ما يصل إلى capacity عنصرًا.

وسّع الدوال التالية من Base لتعمل على CircularBuffer:

  • Base.push!(cb::CircularBuffer, item; overwrite::Bool=false): أدرج العنصر item في نهاية cb، ثم أرجِع cb. إذا كانت cb ممتلئة بالفعل، فارفع استثناء BoundsError إذا كانت overwrite تساوي false (القيمة الافتراضية)؛ وإلا فأزل العنصر الأول لإفساح المجال أمام item إذا كانت overwrite تساوي true.
  • Base.popfirst!(cb::CircularBuffer): أزل العنصر الأول من cb وأرجِعه.
  • Base.empty!(cb::CircularBuffer): أزل كل العناصر من cb، ثم أرجِع cb وهي فارغة.

المهام الإضافية

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

وسّع CircularBuffer الخاصة بك لاجتياز اختبارات CircularBuffer من حزمة DataStructures.jl. هذه الاختبارات مُضمّنة لكنها مُعطّلة في الاختبارات المرفقة لتمرين Exercism هذا؛ ولتفعيلها، أضف إلى ملفك أو دفترك السطر enable_bonus_tests = true على المستوى الأعلى.

لاجتياز هذه الاختبارات عليك أن تُعرّف CircularBuffer كنوع فرعي من AbstractVector وأن تُعرّف دالتين:

  • capacity(cb::CircularBuffer): أرجِع سعة cb.
  • isfull(cb::CircularBuffer): أرجِع true إذا كانت cb ممتلئة.

ثم عليك أن تتأكد من أن الدوال التالية من Base تعمل بشكل صحيح مع CircularBuffer: append!، empty!، pop!، pushfirst، setindex!، collect، eltype، first، getindex، isempty، iterate، last، length، وsize.

تلميح: لست بحاجة إلى توسيع كل هذه الدوال، بل لا ينبغي لك ذلك! فعندما تُعرّف CircularBuffer كنوع فرعي من AbstractVector، فإن الدوال العامة التي عُرّفت من أجل AbstractVector ستصبح الآن تقبل CircularBuffer كمدخل. انظر قسم الواجهات في دليل Julia:

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

سيتعيّن عليك أن تتصفّح الكود المصدري لوحدة Base في Julia لترى تعريفات الدوال وتحدد أيّها ينبغي توسيعه. ولتحديد موقع الكود المتعلق باستدعاء دالة، يمكنك استخدام الماكرو @which لتحديد الطريقة المحددة التي يُوجَّه إليها استدعاء الدالة. كما يريك اسم الملف ورقم السطر الذي عُرّفت فيه تلك الطريقة (وفي دفتر Jupyter عبر IJulia، يمنحك حتى رابطًا إلى الكود المتعلق على GitHub).

إذا كنت تعمل في REPL، فقد تفضّل استخدام الماكرو @edit لفتح الملف والسطر المتعلّقين في محرّر النصوص الافتراضي لديك.


المصدر

ويكيبيديايفتح الرابط في نافذة أو علامة تبويب جديدة
تعديل عبر GitHub يفتح الرابط في نافذة أو علامة تبويب جديدة
Julia Exercism

مستعد لبدء المخزن المؤقت الدائري؟

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

تعمّق في المخزن المؤقت الدائري!

في هذا الفيديو نلقي نظرة على المخزن المؤقت الدائري: ما هو، وأين يُستخدم، وتطبيقاته المختلفة، بما في ذلك الطوابير والمصفوفات الثابتة والديناميكية وبنى البيانات غير القابلة للتغيير وتطبيق ممتع قائم على الوكلاء.