from collections import defaultdict


def res_contacts(contacts):
    """
    Convert atomic contacts into unique residue contacts. The interaction type is removed as well as any third or
    fourth atoms that are part of the interaction (e.g. water-bridges). Finally, the order of the residues within an
    interaction is such that the first is lexicographically smaller than the second ('A:ARG' comes before 'A:CYS').

    Example
    -------
        res_frequencies([
            [0, 'hbbb', 'A:ASN:108:O', 'A:ARG:110:N'],
            [0, 'vdw', 'A:ARG:110:N', 'A:ASN:108:CB']
        ])
        # => [[0, 'A:ARG:110', 'A:ASN:108']]

    Parameters
    ----------
    contacts: List of list
        List of contacts, where each contact is a list of frame-num, i-type, and atom names

    Returns
    -------
    List of list
        Each entry is a list with a frame and two residue identifiers
    """
    # print(contacts)
    # Associates a frame-number with a set of contacts
    frame_dict = defaultdict(set)

    for atom_contact in contacts:
        frame = atom_contact[0]
        resi1 = ":".join(atom_contact[2].split(":")[0:3])
        resi2 = ":".join(atom_contact[3].split(":")[0:3])
        if resi2 < resi1:
            resi1, resi2 = resi2, resi1
        frame_dict[frame].add((resi1, resi2))

    ret = []
    for frame in sorted(frame_dict):
        for resi1, resi2 in frame_dict[frame]:
            ret.append([frame, resi1, resi2])

    return ret