DNA sequencing data can be stored in many different formats. In this Kata, we will be looking at SAM formatting. It is a plain text file where every line (excluding the first header lines) contains data about a "read" from whatever sample the file comes from. Rather than focusing on the whole read, we will take two pieces of information: the cigar string and the nucleotide sequence.

The cigar string is composed of numbers and flags. It represents how the read aligns to what is known as a reference genome. A reference genome is an accepted standard for mapping the DNA. 

The nucleotide sequence shows us what bases actually make up that section of DNA. They can be represented with the letters A, T, C, or G.

Example Read: ('36M', 'ACTCTTCTTGCGAAAGTTCGGTTAGTAAAGGGGATG')

The M in the above cigar string stands for "match", and the 36 stands for the length of the nucleotide sequence. Since all 36 bases are given the 'M' distinction, we know they all matched the reference.

Example Read: ('20M10S',  'ACTCTTCTTGCGAAAGTTCGGTTAGTAAAG')

In the above cigar string, only 20 have the "M" distinction, but the length of the actual string of nucleotides is 30. Therefore we know that read did not match the reference. (Don't worry about what the other letters mean. That will be covered in a later kata.)

Your job for this kata is to create a function that determines whether a cigar string fully matches the reference and accounts for all bases. If it does fully match, return True. If the numbers in the string do not match the full length of the string, return 'Invalid cigar'. If it does not fully match, return False.

*Note for C++: Return True, False, or Invalid cigar as strings*

Difficulty: EASY

Starter code:
def is_matched(read):
	

Solutions:
import re

def is_matched(read):
	total = sum([int(num) for num in re.findall('\\d+', read[0])])
	if read[0] == str(len(read[1])) + 'M':
		return True
	elif len(read[1]) != total:
		return 'Invalid cigar'
	else:
		return False


import re

def is_matched(read):
	(cigar, seq) = read
	matches = re.findall('(\\d+)([A-Z])', cigar)
	if sum((int(n) for (n, _) in matches)) != len(seq):
		return 'Invalid cigar'
	return all((sym == 'M' for (_, sym) in matches))


import re

def is_matched(read):
	if f'{len(read[1])}M' == read[0]:
		return True
	elif sum((int(n) for n in re.findall('\\d+', read[0]))) != len(read[1]):
		return 'Invalid cigar'
	return False


import re
from functools import reduce

def is_matched(read):
	parse = re.findall('[0-9]+[A-Z]', read[0])
	cigar = {}
	for i in parse:
		if cigar.get(i[-1]) == None:
			cigar[i[-1]] = 0
		cigar[i[-1]] += int(i[:-1])
	if cigar.get('M') == len(read[1]):
		return True
	elif reduce(lambda x, y: x + y, [v for v in cigar.values()], 0) == len(read[1]):
		return False
	else:
		return 'Invalid cigar'


import re

def is_matched(cig):
	ci = re.split('\\D', cig[0])[:-1]
	return 'Invalid cigar' if sum(map(int, ci)) != len(cig[1]) else cig[0] == ci[0] + 'M'


import re

def is_matched(read):
	cigar = [int(i) for i in list(filter(None, re.split('[A-Z]', read[0])))]
	if sum(cigar) == len(read[1]):
		return len(cigar) == 1 and re.split('[0-9]+', read[0])[1] == 'M'
	else:
		return 'Invalid cigar'


import re

def is_matched(read):
	num = re.compile('\\d+')
	a = list(map(int, num.findall(read[0])))
	Dna_length = sum(a[0:len(a)])
	if Dna_length != len(read[1]):
		return 'Invalid cigar'
	else:
		return a[0] == len(read[1]) and str(a[0]) + 'M' == read[0]


import re

def is_matched(read):
	res = [int(i) for i in re.findall('\\d+', read[0])]
	if sum(res) != len(read[1]):
		return 'Invalid cigar'
	if len(res) == 1 and 'M' in read[0]:
		return True
	return False


import re

def is_matched(read):
	nums = [int(v) for v in re.findall('\\d+', read[0])]
	return 'Invalid cigar' if sum(nums) != len(read[1]) else read[0] == f'{len(read[1])}M'