EDIT: Based on @J_H's suggestion, here's a modified version of the above using a data structure with labeled fields:
from collections import Counter
from dataclasses import dataclass
@dataclass(frozen=True)
class Entry:
frequency: int
letter: str
source: str
def frequencies(s: str, source: str) -> list[Entry]:
counter = Counter(c for c in s if c.islower())
return [
Entry(frequency, letter, source)
for letter, frequency in counter.items()
if frequency > 1
]
def mix_string(letter_frequencies: list[Entry]) -> str:
return "/".join(
f"{entry.source}:{entry.frequency*entry.letter}"
for entry in letter_frequencies
)
def mix(s1: str, s2: str) -> str:
seen_letters = set()
letter_frequencies = frequencies(s1, "1") + frequencies(s2, "2")
if not letter_frequencies:
return ""
letter_frequencies.sort(key=lambda x: (-x.frequency, x.letter))
stack = [letter_frequencies[0]]
seen_letters.add(letter_frequencies[0].letter)
for entry in letter_frequencies[1:]:
top = stack[-1]
if entry.frequency == top.frequency and entry.letter == top.letter:
stack.pop()
stack.append(Entry(entry.frequency, entry.letter, "="))
elif entry.letter in seen_letters:
continue
else:
stack.append(entry)
seen_letters.add(entry.letter)
stack.sort(key=lambda x: (-x.frequency, x.source, x.letter))
return mix_string(stack)