Я строю сценарий, который рассчитывает генетику животных, которые разводятся вместе. Каждое животное имеет набор генов (например, BbEeKk), и программа должна рассчитать все генетические возможности потомства. Но я не уверен, как составить уравнения для букв, так как все решение будет иметь дело с умножением многочленов с использованием только букв. Пока что скрипт на PHP. Но если PHP не может обработать этот тип уравнения, его можно легко перевести на другое.
Вот пример того, как (на бумаге) вы можете найти потомство скрещивания между BbEEKk и bbeeKk:
// First we take the individual gene pairs and multiply them together
(B + b)(b + b) = 2Bb + 2bb
(E + E)(e + e) = 4Ee
(K + k)(K + k) = 1KK + 2Kk + 1kk
// Take those and form a polynomial
(2Bb + 2bb)(4Ee)(1KK + 2Kk + 1kk)
// Multiply first two expressions
(6BbEe + 6bbEe)(1KK + 2Kk + 1kk)
// Multiply remaining two expressions
(6BbEeKK + 12BbEeKk + 6BbEekk + 6bbEeKK + 12bbEeKk + 6bbEekk)
Извлекая эти окончательные значения, мы получаем:
12/64 (18.75%) offspring as BbEeKk
12/64 (18.75%) offspring as bbEeKk
6/64 (9.375%) offspring as BbEeKK
6/64 (9.375%) offspring as BbEekk
6/64 (9.375%) offspring as bbEeKK
6/64 (9.375%) offspring as bbEekk
Я просто не могу найти способ для PHP справиться с такого рода операциями, и я недостаточно знаком с JavaScript, чтобы знать, может ли он тоже.
Интересно 🙂
Позволяет интегрировать математику с программированием.
Прежде всего, я думаю, что вы допустили ошибку в примере, это должно быть
// First we take the individual gene pairs and multiply them together
(B + b)(b + b) = 2Bb + 2bb
(E + E)(e + e) = 4Ee
(K + k)(K + k) = 1KK + 2Kk + 1kk
// Take those and form a polynomial
(2Bb + 2bb)(4Ee)(1KK + 2Kk + 1kk)
// Multiply first two expressions
(8BbEe + 8bbEe)(1KK + 2Kk + 1kk)
// Multiply remaining two expressions
(8BbEeKK + 16BbEeKk + 8BbEekk + 8bbEeKK + 16bbEeKk + 8bbEekk)
Таким образом, сумма всей возможной весны составляет 100%
Это можно легко решить, применяя матричные вычисления,
Первым шагом было бы рассмотреть гены как числа
bb ==> 0
bB ==> Bb ==> 1
BB ==> 2
То же самое для любых букв.
После того, как у вас есть следующее уравнение:
(2Bb + 2bb)(4Ee)(1KK + 2Kk + 1kk)
Вы можете перевести его в матричную операцию:
[2 2 0] * [0 4 0] * [1 2 1]
Рассмотрите возможность использования транспонирования матрицы для сопоставления размеров. Результирующая матрица даст вам числа, сумма которых будет равна 64.
Так что, если я правильно понимаю, то сначала мы должны отделить «BbEEKk» в
«Bb», «EE», Kk «и то же самое с» bbeeKk «.
После этого у нас должны быть «Bb» и «bb».
Я немного поиграл с этим, и я думаю, что я решил первую часть с умножением их вместе, если вы разделите их, как я написал:
function test($a,$b){
if ($a[0] == $a[1]) {
if ($b[0] == $b[1]) {
return "4" . $a[0] . $b[0];
}
return "2" . $b[0] . $a[0] . "+2" . $a[0] . $a[0];
} elseif ($b[0] == $b[1]) {
if ($a[0] == $a[1]) {
return "4" . $b[0] . $a[0];
}
return "2" . $a[0] . $b[0] . "+2" . $b[0] . $b[0];
} elseif ($a[0] != $a[1]) {
return "1" . $a[0] . $a[0] . "+2" . $a . "+1" . $a[1] . $a[1];
}
}
Должно быть возможно сделать то же самое, что я сделал здесь с другими шагами.
одно решение (это решение «грубой силы» и не очень красивое):
<?php
$seqs = ["BbEEKk", "bbeeKk"];
// chunk them to parts of 2 chars
$seqs = array_map(function($el) {return str_split($el,2);}, $seqs);
echo "<pre>".print_r($seqs,true)."</pre>";
// cross the two sequence strings:
$step1 = [];
for($i=0;$i<count($seqs[0]);$i++)
$step1[] = multiplySequences([$seqs[0][$i], $seqs[1][$i]]);
echo "<pre>".print_r($step1,true)."</pre>";
// now multiply the result and sort them:
$step2 = multiplySequences($step1);
usort($step2, function($a, $b) {
return $b[0]-$a[0];
});
echo "<pre>".print_r($step2,true)."</pre>";
// takes an array of sequenzes. a sequenze is an array of sequenzeparts. a sequenzepart is an array [0=>number, 1=>the sequenz as chars]
function multiplySequences($seqs) {
foreach($seqs as &$seq)
multiplySequencesPrepare($seq);
// multiply them all:
$t = $seqs[0];
for($i=1;$i<count($seqs);$i++) {
$t = multiplySequencesHelper($t, $seqs[$i]);
$t = multiplySequencesPrepare($t);
}
return $t;
}
// prepare the data to process them. it defines the format from above: input can be a string "2Bb" or an array. if it's an array there are to possibilities: 1) [0=>number, 1=>sequence] or [[0=>number, 1=>sequence],[0=>number, 1=>sequence],...]
function multiplySequencesPrepare(&$seq) {
if(is_array($seq))
$seq = array_map(function($s) { if(is_array($s)) return $s; preg_match('/(\d*)(\w+)/', $s, $s); $s[1]=(int)$s[1]==0?1:(int)$s[1]; return array_slice($s,1);}, $seq);
else
$seq = call_user_func(function($s) {
preg_match('/(\d*)(\w+)/', $s, $s);
$s[2] = str_split($s[2]);
$s[1]=(int)$s[1]==0?1:(int)$s[1];
return array_map(function($sp) use($s) { return [$s[1], $sp]; }, $s[2]);
}, $seq);
return $seq;
}
// calculate the result of two sequences:
function multiplySequencesHelper($seq1, $seq2) {
$res = [];
$cnt = [];
foreach($seq1 as $s1)
foreach($seq2 as $s2) {
$c1 = $s1[1];
$c2 = $s2[1];
$res[] = $tcc = ($c1<$c2?$c1.$c2:$c2.$c1);
$cnt[$tcc] = $s1[0]*$s2[0];
}
$tmp = array_count_values($res);
return array_map(function($el) use($tmp,$cnt) { return ($cnt[$el]*$tmp[$el]).$el; }, array_unique($res));
}
проверенный комментарии внутри кода должны объяснить это.