from itertools import count def params(n,fmt='pairs'): """Convert row number n in A366766-A366768 to parameters (D,d,C). fmt='pairs': C is given as a list of allowed connection types (g,h). fmt='X-': 'X' indicates an allowed type in the corresponding position in lexicographic order among all types (g,h) applicable to the current values of D and d (1 <= g <= d, 0 <= h <= min(g,D-d)). fmt='X-.': List all types (g,h) for 1 <= g <= D, 0 <= h <= g; '.' indicates that the type in the corresponding position is not applicable to the current values of D and d. Example: params(10) returns (2, 2, [(1, 0), (2, 0)]), corresponding to polyplets (A030222). """ m=0 for D in count(1): for d in range(1,D+1): L=(d+1)*(d+2)//2-1 if 2*d<=D else (D-d+1)*(3*d-D+2)//2-1 if m+2**L>=n: C0=[(g,h) for g in range(1,d+1) for h in range(min(g,D-d)+1)] i=format(n-m-1,f'0{L}b')[::-1] C=[x for x,t in zip(C0,i) if t=='1'] if fmt=='pairs': return (D,d,C) elif fmt=='X-': return ''.join('-X'[int(t)] for t in i) elif fmt=='X-.': s=['.']*((D+1)*(D+2)//2-1) j=0 for g in range(1,D+1): for h in range(g+1): if (g,h) in C0: s[j]='X' if (g,h) in C else '-' j+=1 return ''.join(s) m+=2**L def row(D,d,C): """Convert parameters (D,d,C) to row number in A366766-A366768. C should be given as a list of allowed connection types (g,h). Example: row(3,2,[(1,0),(1,1)]) returns 18, corresponding to polyominoids (A075679). """ n=sum(2**((dd+1)*(dd+2)//2-1 if 2*dd<=DD else (DD-dd+1)*(3*dd-DD+2)//2-1) for DD in range(1,D+1) for dd in range(1,DD+1 if DD!=D else d)) C0=[(g,h) for g in range(1,d+1) for h in range(min(g,D-d)+1)] for i,x in enumerate(C0): if x in C: n+=2**i return n+1