main.py

from __future__ import print_function

def solve(watermarks, patterns):
	"""Given patterns and watermarks, find all possible mappings
	and print possible encodings."""

	# Each pattern potentially generates multiple mappings.
	# When we have two lists of mappings, we generate
	# a combined list of mappings that is compatible
	# with both input mappings lists.
	import mapping
	mappings = None
	for p in patterns:
		pattern_mappings = mapping.MappingSet()
		# Note that we try to find mappings for this
		# pattern in ALL watermarks before reconciling
		# with previous mapping.  This is because the
		# good mapping may only be found in one watermark.
		# If we start with a "bad" watermark and find
		# bad mappings, then, if we reconcile immediately,
		# we may come to the conclusion that there is no
		# solution, when, in fact, the good mapping will
		# be found if we keep looking.
		for w in watermarks:
			m = p.find_all_mappings(w)
			if m:
				pattern_mappings.extend(m)
		mappings = mapping.reconcile(mappings, pattern_mappings)

	# Loop over each mapping and try to apply it to all
	# watermarks.  If it resolve more than some threshold
	# fraction of all watermarks, print the results.
	threshold = 0.40
	for m in mappings:
		results = {}
		for w in watermarks:
			pv, wv, count = m.decode(w, '_')
			# d = decoded message,
			# count = number of unconverted values
			if count / float(len(pv)) > threshold:
				break
			results[w] = (pv, wv)
		else:
			print("Possible mapping:")
			for pv, wv in results.values():
				_print_pair(pv, wv)
			print()

def _print_pair(pv, wv):
	i = 0
	total_width = 0
	pl = []
	wl = []
	max_line_width = 72
	while i < len(pv):
		p = repr(pv[i])[1:-1]
		w = repr(wv[i])[1:-1]
		width = max(len(p), len(w))
		pl.append(p.ljust(width))
		wl.append(w.ljust(width))
		total_width += width
		if total_width > max_line_width:
			print(''.join(pl))
			print(''.join(wl))
			total_width = 0
			pl = []
			wl = []
		i += 1
	if total_width > 0:
		print(''.join(pl))
		print(''.join(wl))

if __name__ == "__main__":
	import given
	from watermark import DNAWatermark
	from pattern import StringPattern
	watermarks = [ DNAWatermark(s) for s in given.watermarks ]
	patterns = [ StringPattern(h) for h in given.hints ]

	from mapping import add_mapping
	add_mapping("CCC", "-")
	add_mapping("GAA", "'")
	solve(watermarks, patterns)