Exercise 2 solution from itertools import combinations_with_replacement def blood_group(genotype): alleles = set(genotype) if alleles == {"A", "B"}: return "AB" if "A" in alleles: return "A" if "B" in alleles: return "B" return "O" def child_groups(p1, p2): return {blood_group(a + b) for a in p1 for b in p2} genos = ["AA", "AO", "BB", "BO", "AB", "OO"] pairs = list(combinations_with_replacement(genos, 2)) o_pairs = [p for p in pairs if "O" in child_groups(*p)] print(len(pairs), len(o_pairs)) print([p for p in pairs if len(child_groups(*p)) == 4]) print([p for p in pairs if "AB" in child_groups(*p) and "O" in child_groups(*p)]) Output: 21 6 [('AO', 'BO')] [('AO', 'BO')] Reading it: there are 21 unordered pairs of parent genotypes, and only 6 of them can have a child of the first group O (each parent must carry an O allele). Just one pair, AO with BO, can have children in all four groups, so it is also the only pair that can have both an AB child and an O child.