"""Parse plantri -a output for 5-connected triangulations at n=21 and
check each for the intertwining-tree property (equivalently, whether its
dual is Hamiltonian)."""
import subprocess
import networkx as nx
import time

PLANTRI = '/Users/didericis/Code/math-research/plantri/plantri'


def parse_plantri_a(line):
    """Parse one line of plantri -a output into a networkx graph.
    Format: 'n adj0,adj1,...' where adj_i is a string of letters."""
    parts = line.strip().split(' ', 1)
    n = int(parts[0])
    adj_lists = parts[1].split(',')
    G = nx.Graph()
    G.add_nodes_from(range(n))
    for i, adj in enumerate(adj_lists):
        for ch in adj:
            j = ord(ch) - ord('a')
            G.add_edge(i, j)
    return G


def is_intertwining_tree(G):
    """Search all 2-partitions for one giving two induced trees."""
    nodes = list(G.nodes())
    n = len(nodes)
    for mask in range(1, 2 ** (n - 1)):
        A = [nodes[0]] + [nodes[i + 1] for i in range(n - 1) if (mask >> i) & 1]
        B = [nodes[i + 1] for i in range(n - 1) if not ((mask >> i) & 1)]
        if not B:
            continue
        if nx.is_tree(G.subgraph(A)) and nx.is_tree(G.subgraph(B)):
            return True
    return False


def main():
    out = subprocess.run([PLANTRI, '-c5', '-a', '21'],
                         capture_output=True, text=True)
    lines = [l for l in out.stdout.splitlines() if l.strip()]
    print(f'{len(lines)} triangulations to check')

    t0 = time.time()
    n_inter = 0
    non_inter = []
    for idx, line in enumerate(lines):
        G = parse_plantri_a(line)
        if G.number_of_nodes() != 21 or G.number_of_edges() != 3 * 21 - 6:
            print(f'  line {idx}: parse issue, n={G.number_of_nodes()}, '
                  f'm={G.number_of_edges()}')
            continue
        if is_intertwining_tree(G):
            n_inter += 1
        else:
            non_inter.append(idx)
        if (idx + 1) % 50 == 0:
            print(f'  ...{idx+1}/{len(lines)} done '
                  f'({time.time()-t0:.1f}s), {n_inter} intertwining so far')
    print(f'\nResult: {n_inter}/{len(lines)} are intertwining trees')
    print(f'Non-intertwining-tree (dual non-Hamiltonian): {non_inter}')
    print(f'elapsed: {time.time()-t0:.1f}s')


if __name__ == '__main__':
    main()
