ترميز DNA

ترميز DNA

تمرين تعلّمي

مقدمة

العودية الذيلية

عند استخدام العودية للتنقل عبر الكائنات القابلة للتعداد (المصفوفات، وسلاسل البتات، والسلاسل النصية)، غالبًا ما يكون هناك اعتباران:

  • مقدار الذاكرة اللازمة لتخزين أثر استدعاءات الدوال العودية
  • كيفية بناء الحل بكفاءة

للتعامل مع هذين الاعتبارين، يمكن استخدام مُراكم.

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

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

# Count the length of a list without an accumulator
def count([]), do: 0
def count([_head | tail]), do: 1 + count(tail)

# Count the length of a list with an accumulator
def count(list), do: do_count(list, 0)

defp do_count([], count), do: count
defp do_count([_head | tail], count), do: do_count(tail, count + 1)

يتيح استخدام المُراكم تحويل الدوال العودية إلى دوال عودية ذيلية. وتكون الدالة عودية ذيلية إذا كان آخر ما تنفّذه هو استدعاء لنفسها.

التعليمات

في مختبر أبحاث DNA الخاص بك، كنت تجرّب طرقًا متعددة لضغط بيانات بحثك لتوفير مساحة التخزين. يقترح أحد زملائك في الفريق تحويل بيانات DNA إلى تمثيل ثنائي:

الحمض النووي الكود
مسافة 0000
A 0001
C 0010
G 0100
T 1000

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

1. ترميز الحمض النووي إلى قيمة ثنائية

نفّذ encode_nucleotide/1 لتقبل نقطة الكود الخاصة بالحمض النووي وتُرجع القيمة الصحيحة للكود المُرمَّز.

DNA.encode_nucleotide(?A)
# => 1
# (which is equal to 0b0001)

2. فك ترميز القيمة الثنائية إلى الحمض النووي

نفّذ decode_nucleotide/1 لتقبل القيمة الصحيحة للكود المُرمَّز وتُرجع نقطة الكود الخاصة بالحمض النووي.

DNA.decode_nucleotide(0b0001)
# => 65
# (which is equal to ?A)

3. ترميز قائمة محارف DNA

نفّذ encode/1 لتقبل قائمة محارف تمثّل أحماضًا نووية وفجوات، وتُرجع البيانات بعد ترميزها في صورة سلسلة بتات.

DNA.encode(~c"AC GT")
# => <<18, 4, 8::size(4)>>

4. فك ترميز سلسلة بتات DNA

نفّذ decode/1 لتقبل سلسلة بتات تمثّل أحماضًا نووية وفجوات، وتُرجع البيانات بعد فك ترميزها في صورة قائمة محارف.

DNA.decode(<<132, 2, 1::size(4)>>)
# => ~c"TG CA"
تعديل عبر GitHub يفتح الرابط في نافذة أو علامة تبويب جديدة
Elixir Exercism

مستعد لبدء ترميز DNA؟

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