Exercise 1 solution B = "TCAG" AA = "FFLLSSSSYY**CC*WLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG" CODON = {a + b + c: AA[16 * i + 4 * j + k] for i, a in enumerate(B) for j, b in enumerate(B) for k, c in enumerate(B)} def translate(dna): protein = [] for i in range(0, len(dna) - 2, 3): aa = CODON[dna[i:i + 3]] if aa == "*": break protein.append(aa) return "".join(protein) def classify(old, new): if len(old) != len(new): return "frameshift" if (len(new) - len(old)) % 3 else "in-frame indel" a, b = translate(old), translate(new) if a == b: return "silent" return "nonsense" if len(b) < len(a) else "missense" def find_orfs(dna): found = [] for s in range(len(dna) - 2): if dna[s:s + 3] == "ATG": p = translate(dna[s:]) end = s + 3 * len(p) if end + 3 <= len(dna) and CODON[dna[end:end + 3]] == "*": found.append((s, p)) return found for s in ("ATGAAATTTGGGTAA", "ATGTGGTGA", "GGATGCCCTAGATGAAATAG"): print(s, find_orfs(s)) Output: ATGAAATTTGGGTAA [(0, 'MKFG')] ATGTGGTGA [(0, 'MW')] GGATGCCCTAGATGAAATAG [(2, 'MP'), (11, 'MK')] Reading it: Each ATG is checked as a possible start; translate stops at the first stop codon, so a start with no stop before the end of the sequence is rejected. Nested starts in the same frame, or overlapping ones, are reported separately.