Javascript 使用字母的多项式方程

Javascript 使用字母的多项式方程,javascript,php,algebra,Javascript,Php,Algebra,我正在建立一个脚本,计算共同繁殖的动物的遗传学。每只动物都有一组基因(如Bbeek),程序应计算后代的所有遗传可能性。但我不知道如何在字母上建立方程,因为整个解决方案将处理仅使用字母的多项式乘法。到目前为止,脚本是用PHP编写的。但是,如果PHP不能处理这种类型的方程,它可以很容易地转移到另一个方程 下面是一个例子,说明了(在纸上)如何找到Bbeek和Bbeek杂交的后代: // First we take the individual gene pairs and multiply them

我正在建立一个脚本,计算共同繁殖的动物的遗传学。每只动物都有一组基因(如Bbeek),程序应计算后代的所有遗传可能性。但我不知道如何在字母上建立方程,因为整个解决方案将处理仅使用字母的多项式乘法。到目前为止,脚本是用PHP编写的。但是,如果PHP不能处理这种类型的方程,它可以很容易地转移到另一个方程

下面是一个例子,说明了(在纸上)如何找到Bbeek和Bbeek杂交的后代:

// 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也不太熟悉,不知道它是否可以。

因此,如果我理解正确,那么首先我们必须将“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];
}
}
应该可以像我在这里做的那样完成其他步骤。

有趣:)

让我们把数学和编程结合起来

首先,我认为你在示例中犯了一个错误,应该是

// 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的数字。

一种解决方案(这是一种“蛮力”解决方案,并不漂亮):


这是一个有趣的问题。我的女朋友会杀了我(她是一名生物学家),但你能进一步解释这些数字字符组合是如何形成的吗?我不太清楚你所说的形成是什么意思,但字符组合只是代表不同的基因。因此,每个父母都有一组3个基因(B、E和K)因为它们可以以多种不同的方式组合在一起,所以每个数字可以说代表一个重复的基因对。如果你曾经做过punnett图表,这就是试图用数学表示一个基因对。我建议你把这篇文章贴在上面,我想有比php和javascript更好的语言可以有效地解决这个问题谢谢你的建议。我有一个问题:(2Bb+2Bb)(4Ee)=(6BbEe+6BbEe)?很晚了。但是这对吗?不是(8BbEe+8BbEe)?虽然我喜欢你的答案,但这也是我问OP关于代码高尔夫的问题的原因。对于php,有太多的替换和代码重写。我认为像J这样的语言可以更好地解决这个问题,但php不适合。这将是一个巨大的混乱,直到最后。是的,我完全同意你的观点,只是展示了OP tha这是可以做到的,但我做的部分只是他做的3个步骤中简单的一部分,甚至代码看起来也很混乱。我也建议OP使用另一种语言来解决这个问题。谢谢你的这个例子。我会看看其他语言来解决这个问题。很好的理解!这就是我做得太快而无法在这里实现的原因。呵呵。我从来没有想过ught关于使用矩阵运算!是否容易分解成字符串格式显示?是的,您将得到所有可能组合的结果,结果矩阵中的数字将属于特定的基因集,具体取决于如何(序列)你是在乘法。在Matlab中尝试一下,如果你懂Matlab的话,几乎不需要几分钟。
<?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));   
    }