Рассчитать родословную

22

Небольшой урок генетики

Когда у вас есть доступ только к чьим-то видимым чертам или фенотипу , родословная их семейной истории часто используется для выяснения фактической генетической информации или генотипа каждого члена семьи.

Когда мы будем иметь дело с простым доминированием , простой диаграммы родословной будет достаточно, чтобы выяснить аллели или версию генов каждого человека. При простом доминировании человек с доминантным аллелем (обозначаемый заглавной буквой) всегда будет иметь черту, которую представляет эта версия, независимо от другого аллеля. Требуется два рецессивных аллеля (обозначенных строчной буквой), чтобы выразить эту версию. Другими словами, доминантный аллель всегда маскирует рецессивную версию этого гена. Вот пример родословной:

ДЕТСКАЯ ДИАГРАММА

Каждый ряд здесь - это поколение. Круги женские, мужские квадраты, горизонтальные линии - брак, вертикальные линии - дети. Довольно просто Черный означает рецессивный фенотип, белый - доминантный. Начиная сверху (предположим, что аллели Aи a), мы знаем, что у человека 2 aaгомозиготный рецессивный, потому что это единственный возможный вариант рецессивного фенотипа. Теперь, даже если человек один может быть Aaили AAдоминирующим фенотипом, потому что у него рецессивный ребенок, он должен быть Aaили гетерозиготным. Вы можете сделать это для всех других людей. В случае , если у вас нет никакой информации , которая позволяет выяснить вторую аллель, это может быть сделано следующим образом: A_.

Твое задание

  • Вы получите родословную в виде списка поколений, как [GenI, GenII, etc.]в любом нормальном формате.
  • Каждое поколение будет списком строк, каждая строка представляет человека.
  • Люди состоят из трех частей - удостоверения личности, их фенотипа и их «связей».
  • Их идентификатор - это один печатный символ ascii, который уникален во всем дереве, кроме Aили a. (Нет, на графике будет не более 95 человек).
  • Их фенотип один из Aили a, Aбудучи доминантный аллель, и aбудучи рецессивным.
  • Их соединения представляют собой последовательность идентификаторов других людей, с которыми они связаны.
  • Связь в одном поколении - это брак, в разных поколениях - ребенок и родитель.
  • Связи повторяются с обеих сторон (то есть муж говорит, что он муж жены, а жена говорит, что она муж жены).
  • Вы должны выяснить генотипы каждого как можно больше.
  • Верните тот же список, за исключением того, что вместо людей поместите их генотипы в ту же позицию.
  • Генотип должен быть выведен по порядку, Aaа не aA.
  • Небольшая свобода в формате ввода в порядке.
  • Это код-гольф, поэтому выигрывает самый короткий ответ в байтах .

Примеры

[["0A1234", "1a0234"], ["2A01", "3a01", "4A015678",
"5a4678"], ["6a45", "7A45","8A45"]] (The one above)   ->

[["Aa", "aa"], ["Aa", "aa", "Aa", "aa"], ["aa", "Aa", "Aa"]]

[["0A12", "1A02"], ["2A301", "3a2"]]    ->

[["A_", "A_"], ["A_", "aa"]]

бонус

  • -30 байт, если вы имеете дело с неполным и совместное доминирование также. При обнаружении трех фенотипов вместо двух во всей диаграмме примените к вашему алгоритму неполное / совместное доминирование.
Maltysen
источник
Разрешено ли нам изменять только Aи aи оставлять идентификаторы и соединения как есть (то есть [["0A12","1A02"],["2A301","3a2"]]становится [["0A_12","1A_02"],["2A_301","3aa2"]]вместо [["A_","A_"],["A_","aa"]])?
Кевин Круйссен

Ответы:

2

05AB1E , 39 байт

εNUε'aåi„aaë¯.øX<X>‚è˜y2£lSδåPài„Aaë„A_

Порт моего Java ответа .

Попробуйте онлайн или проверьте все контрольные примеры .

Объяснение:

ε                     # Map over the rows of the (implicit) input-list:
 NU                   #  Store the outer-map index in variable `X`
   ε                  #  Map over the strings `y` of the current row:
    'aåi             '#   If the current string contains an "a":
        aa           #    Push string "aa"
       ë              #   Else (it contains an "A" instead):
        ¯.ø           #    Surround the (implicit) input-list with two empty lists
                      #    (05AB1E has automatic wrap-around when indexing lists,
                      #     so this is to prevent that)
           X<X>‚      #    Push `X-1` and `X+1` and pair them together
                è     #    Index both into the list to get (potential) parent and child rows
                 ˜    #    Flatten it to a single list
        y             #    Push the current string we're mapping again
         2£           #    Only leave the first 2 characters (its id and the letter "A")
           l          #    Lowercase the "A" to "a"
            S         #    And convert it to a list of characters: [id, "A"]
             δå       #    Check in each string whether it contains the id and "A"
               P      #    Check for each whether it contained BOTH the id AND "A"
                ài    #    If a child/parent is found for which this is truthy:
                  Aa #     Push string "Aa"
                 ë    #    Else:
                  A_ #     Push string "A_"
                      # (after which the mapped result is output implicitly)
Кевин Круйссен
источник
1

Java 10, 356 349 340 байт

a->{int i=0,j,k,f,z=a.length;var r=new String[z][];for(;i<z;i++)for(r[i]=new String[j=a[i].length];j-->0;)if(a[i][j].contains("a"))r[i][j]="aa";else{var t=".a.*"+a[i][j].charAt(0)+".*";for(f=k=0;i>0&&k<a[i-1].length;)f=a[i-1][k++].matches(t)?1:f;for(k=0;i+1<z&&k<a[i+1].length;)f=a[i+1][k++].matches(t)?1:f;r[i][j]=f>0?"Aa":"A_";}return r;}

Попробуйте онлайн.

Общее объяснение:

1) Любой aвсегда будетaa

2a) Если у ребенка Aесть родители, aaи Aон станет Aa
2b) Если у ребенка Aесть родители, Aи Aон станетA_
2c) (Ребенок не Aможет иметь родителей aaи aa)

3a) Если у родителя Aесть хотя бы один ребенок a, он станет Aa
3b) Если у родителяA есть только дети A, он станетA_

Объяснение кода:

a->{                     // Method with 2D String array as both parameter and return-type
  int i=0,j,k,           //  Index-integers
      f,                 //  Flag-integer
      z=a.length;        //  Length-integer
  var r=new String[z][]; //  Result 2D String array
  for(;i<z;i++)          //  Loop over the rows:
    for(r[i]=new String[j=a[i].length];
                         //   Create the inner String-array of the result
        j-->0;)          //   Loop over the columns:
      if(a[i][j].contains("a"))
                         //    If the current node contains "a":
        r[i][j]="aa";    //     Set the result at this node to "aa"
      else{              //    Else(-if the current node contains "A" instead):
        var t=".a.*"+a[i][j].charAt(0)+".*";
                         //     Set a temp String to a regex to check relations and "a"
        for(f=k=0;       //     Set the flag to 0
            i>0&&        //     If the current node has parents:
            k<a[i-1].length;)
                         //      Loop over the row above:
          f=a[i-1][k++].matches(t)?
                         //       If a parent with "a" is found:
            1:f;         //        Set the flag to 1 (else: leave it unchanged)
        for(k=0;i+1<z&&  //     If the current node has children:
            k<a[i+1].length;) 
                         //      Loop over the row below:
          f=a[i+1][k++].matches(t)?
                         //       If child with "a" is found:
            1:f;         //        Set the flag to 1 (else: leave it unchanged)
        r[i][j]=f>0?     //     If the flag is 1:
                 "Aa"    //      Current node changes from "A" to "Aa"
                :        //     Else (flag is still 0):
                 "A_";}  //      Current node changes from "A" to "A_"
  return r;}             //  Return the result
Кевин Круйссен
источник