Hamming

Hamming

آسان

مقدمه

بدن شما از سلول‌هایی تشکیل شده است که در خود DNA دارند. این سلول‌ها به‌طور منظم فرسوده می‌شوند و باید جایگزین شوند، و این کار را با تقسیم شدن به سلول‌های دختر انجام می‌دهند. در واقع، بدن یک انسان معمولی در طول عمرش حدود ۱۰ کوادریلیون تقسیم سلولی را تجربه می‌کند!

وقتی سلول‌ها تقسیم می‌شوند، DNA آن‌ها هم همانندسازی می‌کند. گاهی در این فرایند اشتباهاتی رخ می‌دهد و تکه‌های منفرد DNA با اطلاعات نادرست رمزگذاری می‌شوند. اگر دو رشته‌ی DNA را با هم مقایسه کنیم و تفاوت‌های میان‌شان را بشماریم، می‌توانیم ببینیم چند اشتباه رخ داده است. به این کار «فاصله‌ی همینگ» می‌گویند.

فاصله‌ی همینگ در بسیاری از حوزه‌های علوم، نه فقط زیست‌شناسی، کاربرد دارد؛ پس عبارت جالبی است که با آن آشنا باشید :)

دستورالعمل‌ها

فاصله‌ی همینگ میان دو رشته‌ی DNA را محاسبه کنید.

DNA را با حروف C، A، G و T می‌خوانیم. دو رشته ممکن است به این شکل باشند:

GAGCCTACTAACGGGAT
CATCGTAATGACGGCCT
^ ^ ^  ^ ^    ^^

این دو رشته ۷ تفاوت دارند و بنابراین فاصله‌ی همینگ برابر ۷ است.

نکته‌های پیاده‌سازی

فاصله‌ی همینگ فقط برای دنباله‌هایی با طول برابر تعریف می‌شود؛ پس تلاش برای محاسبه‌ی آن میان دنباله‌هایی با طول متفاوت نباید کار کند.

از Option برای نشان دادن محاسبه‌ای استفاده می‌شود که ممکن است هیچ نتیجه‌ی مفیدی نداشته باشد (برای مثال، به دلیل یک خطا یا ورودی نامعتبر). اگر با Option آشنایی ندارید، می‌توانید این آموزش را بخوانید. Option یک موناد است که به اصطلاح یک «جنبه‌ی محاسباتی» را پوشش می‌دهد، در این مورد، امکان نبودن یک مقدار. استفاده‌ی درست از مونادها می‌تواند به کدی بسیار مختصر و در عین حال زیبا و خوانا منجر شود. استفاده‌ی نادرست به‌راحتی می‌تواند نتیجه‌ی برعکس بدهد. برای یادگیری بیشتر این ویدیو را ببینید.

دام‌های رایجی که باید از آن‌ها دوری کنید

چند قاعده‌ی سرانگشتی برای Option وجود دارد:

  1. اگر به آن نیاز ندارید، از آن استفاده نکنید. به‌جای
def add1(x: Int): Option[Int] = Some(x + 1)

بهتر است این را داشته باشید

def add1(x: Int): Int = x + 1

(تابع Option.map برای اعمال چنین توابع ساده‌ای وجود دارد، بنابراین لازم نیست آن‌ها را با Option شلوغ کنید). 2. اگر واقعاً نیازی ندارید، مقدار را «بازگشایی» نکنید. غالباً توابع توکاری برای هدف شما وجود دارد. نشانه‌های بازگشایی زودهنگام isDefined/isEmpty یا تطبیق الگو هستند. به‌جای

val x: Option[Int] = ...

if (x.isDefined) x.get + 1 else 0
// or
x match {
  case Some(n) => n + 1
  case None => 0
}

بهتر است این را داشته باشید

x map (_ + 1) getOrElse 0
  1. مونادها را می‌توان داخل یک for-comprehension به کار برد؛ FTW. این کار زمانی توصیه می‌شود که بخواهید چند نمونه‌ی Option را «ترکیب» کنید. به‌جای
val xo: Option[Int] = ...
val yo: Option[Int] = ...
val zo: Option[Int] = ...

xo.flatMap(x =>
  yo.flatMap(y =>
    zo.map(z =>
	  x + y + z)))

بهتر است این را داشته باشید

for {
  x <- xo
  y <- yo
  z <- zo
} yield x + y + z
ویرایش از طریق GitHub این لینک در پنجره یا زبانه‌ی جدیدی باز می‌شود
Scala Exercism

آماده‌اید Hamming را شروع کنید؟

در Exercism ثبت‌نام کنید تا Scala را همراه با 95 تمرین و مربی‌گری انسانی واقعی یاد بگیرید و در آن استاد شوید، همه‌ی این‌ها رایگان.