Given two strings s1 and s2, we want to visualize how different the two strings are.
We will only take into account the *lowercase* letters (a to z).
First let us count the frequency of each *lowercase* letters in s1 and s2.

`s1 = "A aaaa bb c"`

`s2 = "& aaa bbb c d"`

`s1 has 4 'a', 2 'b', 1 'c'`

`s2 has 3 'a', 3 'b', 1 'c', 1 'd'`

So the maximum for 'a' in s1 and s2 is 4 from s1; the maximum for 'b' is 3 from s2.
In the following we will not consider letters when the maximum of their occurrences
is less than or equal to 1.

We can resume the differences between s1 and s2 in the following string:
`"1:aaaa/2:bbb"`
where `1` in `1:aaaa` stands for string s1 and `aaaa` because the maximum for `a` is 4.
In the same manner `2:bbb` stands for string s2 and `bbb` because the maximum for `b` is 3.

The task is to produce a string in which each *lowercase* letters of s1 or s2 appears as many times as
its maximum if this maximum is *strictly greater than 1*; these letters will be prefixed by the 
number of the string where they appear with their maximum value and `:`. 
If the maximum is in s1 as well as in s2 the prefix is `=:`.

In the result, substrings (a substring is for example 2:nnnnn or 1:hhh; it contains the prefix) will be in decreasing order of their length and when they have the same length sorted in ascending lexicographic order (letters and digits - more precisely sorted by codepoint); the different groups will be separated by '/'. See examples and "Example Tests".

Hopefully other examples can make this clearer.

```
s1 = "my&friend&Paul has heavy hats! &"
s2 = "my friend John has many many friends &"
mix(s1, s2) --> "2:nnnnn/1:aaaa/1:hhh/2:mmm/2:yyy/2:dd/2:ff/2:ii/2:rr/=:ee/=:ss"

s1 = "mmmmm m nnnnn y&friend&Paul has heavy hats! &"
s2 = "my frie n d Joh n has ma n y ma n y frie n ds n&"
mix(s1, s2) --> "1:mmmmmm/=:nnnnnn/1:aaaa/1:hhh/2:yyy/2:dd/2:ff/2:ii/2:rr/=:ee/=:ss"

s1="Are the kids at home? aaaaa fffff"
s2="Yes they are here! aaaaa fffff"
mix(s1, s2) --> "=:aaaaaa/2:eeeee/=:fffff/1:tt/2:rr/=:hh"
```
# Note for Swift, R, PowerShell
The prefix `=:` is replaced by `E:`
``` 
s1 = "mmmmm m nnnnn y&friend&Paul has heavy hats! &"
s2 = "my frie n d Joh n has ma n y ma n y frie n ds n&"
mix(s1, s2) --> "1:mmmmmm/E:nnnnnn/1:aaaa/1:hhh/2:yyy/2:dd/2:ff/2:ii/2:rr/E:ee/E:ss"
```

Source: codewars | Difficulty: MEDIUM_HARD
Tags: String algorithms

Fundamentals

Starter code: def mix(s1, s2):
	

Solutions:
def mix(s1, s2):
	hist = {}
	for ch in 'abcdefghijklmnopqrstuvwxyz':
		(val1, val2) = (s1.count(ch), s2.count(ch))
		if max(val1, val2) > 1:
			which = '1' if val1 > val2 else '2' if val2 > val1 else '='
			hist[ch] = (-max(val1, val2), which + ':' + ch * max(val1, val2))
	return '/'.join((hist[ch][1] for ch in sorted(hist, key=lambda x: hist[x])))


def mix(s1, s2):
	c1 = {l: s1.count(l) for l in s1 if l.islower() and s1.count(l) > 1}
	c2 = {l: s2.count(l) for l in s2 if l.islower() and s2.count(l) > 1}
	r = []
	for c in set(list(c1.keys()) + list(c2.keys())):
		(n1, n2) = (c1.get(c, 0), c2.get(c, 0))
		r.append(('1', c, n1) if n1 > n2 else ('2', c, n2) if n2 > n1 else ('=', c, n1))
	rs = ['{}:{}'.format(i, c * n) for (i, c, n) in r]
	return '/'.join(sorted(rs, key=lambda s: (-len(s), s)))


def mix(s1, s2):
	s = []
	lett = 'abcdefghijklmnopqrstuvwxyz'
	for ch in lett:
		(val1, val2) = (s1.count(ch), s2.count(ch))
		if max(val1, val2) >= 2:
			if val1 > val2:
				s.append('1:' + val1 * ch)
			elif val1 < val2:
				s.append('2:' + val2 * ch)
			else:
				s.append('=:' + val1 * ch)
	s.sort()
	s.sort(key=len, reverse=True)
	return '/'.join(s)


from collections import Counter

def mix(s1, s2):
	res = []
	c1 = Counter([c for c in s1 if c.islower()])
	c2 = Counter([c for c in s2 if c.islower()])
	for c in c1 | c2:
		if c1[c] > 1 and c1[c] > c2[c]:
			res += ['1:' + c * c1[c]]
		if c2[c] > 1 and c2[c] > c1[c]:
			res += ['2:' + c * c2[c]]
		if c1[c] > 1 and c1[c] == c2[c]:
			res += ['=:' + c * c1[c]]
	return '/'.join(sorted(res, key=lambda a: [-len(a), a]))


def filter_lowercase(character_in_s):
	lowercase_alphabet = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
	if character_in_s in lowercase_alphabet:
		return True
	else:
		return False

def sort_mix(a):
	return len(a)

def order_alphabetically_ascendent(elem):
	if elem[:1] == '=':
		return 2
	elif elem[:1] == '1':
		return 0
	elif elem[:1] == '2':
		return 1

def mix(s1, s2):
	lowercase_alphabet = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
	characters_in_s1 = []
	characters_in_s2 = []
	amount_of_each_letter_in_s1 = []
	amount_of_each_letter_in_s2 = []
	where_is_maximum = []
	maximum = []
	letters_used_with_prefix = []
	string_to_return = ''
	different_lengths = []
	array_of_letters_with_the_same_length = []
	for character in s1:
		characters_in_s1.append(character)
	for character in s2:
		characters_in_s2.append(character)
	lowercase_letters_in_s1 = list(filter(filter_lowercase, characters_in_s1))
	lowercase_letters_in_s2 = list(filter(filter_lowercase, characters_in_s2))
	for alphabet_letter in lowercase_alphabet:
		lowercase_letters_in_s = []
		i = len(amount_of_each_letter_in_s1)
		string_to_append = ''
		amount_of_each_letter_in_s1.append(lowercase_letters_in_s1.count(alphabet_letter))
		lowercase_letters_in_s.append(lowercase_letters_in_s1.count(alphabet_letter))
		amount_of_each_letter_in_s2.append(lowercase_letters_in_s2.count(alphabet_letter))
		lowercase_letters_in_s.append(lowercase_letters_in_s2.count(alphabet_letter))
		maximum.append(max(lowercase_letters_in_s))
		if lowercase_letters_in_s2.count(alphabet_letter) == lowercase_letters_in_s1.count(alphabet_letter):
			where_is_maximum.append('b')
		elif lowercase_letters_in_s1.count(alphabet_letter) > lowercase_letters_in_s2.count(alphabet_letter):
			where_is_maximum.append('1')
		elif lowercase_letters_in_s2.count(alphabet_letter) > lowercase_letters_in_s1.count(alphabet_letter):
			where_is_maximum.append('2')
		if maximum[i] > 1:
			if where_is_maximum[i] == 'b':
				string_to_append = '=:' + lowercase_alphabet[i] * maximum[i]
			elif where_is_maximum[i] != 'b':
				string_to_append += str(where_is_maximum[i]) + ':' + lowercase_alphabet[i] * maximum[i]
			letters_used_with_prefix.append(string_to_append)
	letters_used_with_prefix = sorted(letters_used_with_prefix, key=lambda conjunto: len(conjunto), reverse=True)
	for string in letters_used_with_prefix:
		if len(string) not in different_lengths:
			different_lengths.append(len(string))
	length = len(different_lengths)
	while length > 0:
		letters_with_the_same_length = []
		for letter_used_with_prefix in letters_used_with_prefix:
			if len(letter_used_with_prefix) == different_lengths[length - 1]:
				letters_with_the_same_length.append(letter_used_with_prefix)
		letters_with_the_same_length = sorted(letters_with_the_same_length, key=order_alphabetically_ascendent)
		array_of_letters_with_the_same_length.append(letters_with_the_same_length)
		length = length - 1
	array_of_letters_with_the_same_length.reverse()
	for subarray in array_of_letters_with_the_same_length:
		for item in subarray:
			string_to_return += item + '/'
	string_to_return = string_to_return[:-1]
	return string_to_return


def mix(s1, s2):
	s1 = {elem: '1:' + ''.join([x for x in s1 if x == elem]) for elem in s1 if s1.count(elem) > 1 and elem.islower()}
	s2 = {elem: '2:' + ''.join([x for x in s2 if x == elem]) for elem in s2 if s2.count(elem) > 1 and elem.islower()}
	for elem in s2:
		if elem in s1:
			if len(s2.get(elem)) > len(s1.get(elem)):
				s1.update({elem: s2.get(elem)})
			elif len(s2.get(elem)) == len(s1.get(elem)):
				s1.update({elem: '=:' + s2.get(elem)[2:]})
		else:
			s1.update({elem: s2.get(elem)})
	s2 = sorted([s1.get(elem) for elem in s1])
	print(s2)
	for i in range(len(s2)):
		for j in range(len(s2)):
			if len(s2[i]) < len(s2[j]):
				(s2[i], s2[j]) = (s2[j], s2[i])
			elif len(s2[i]) == len(s2[j]):
				if s2[i][0] == s2[j][0] and sorted([s2[i][2], s2[j][2]])[0] == s2[j][2] or (s2[i][0].isdigit() == False and s2[j][0].isdigit()) or (s2[i][0].isdigit() and s2[j][0].isdigit() and (int(s2[i][0]) > int(s2[j][0]))):
					(s2[i], s2[j]) = (s2[j], s2[i])
	return '/'.join(reversed([x for x in s2]))


from collections import Counter

def mix(s1, s2):
	(c1, c2) = [Counter({s: n for (s, n) in Counter(c).items() if n > 1 and s.islower()}) for c in (s1, s2)]
	return '/'.join((c + ':' + -n * s for (n, c, s) in sorted(((-n, '=12'[(c1[s] == n) - (c2[s] == n)], s) for (s, n) in (c1 | c2).items()))))