m = {1: 2, 7: 3, 2: 1, 4: 4, 5: 3, 6: 9}
n = {1:2, 2:3, 3:4, 4:5, 5:1, 6:1, 7:1, 8:8}
cycles = set()
for k, v in m.items():
if m.get(v) == k:
cycles.add(tuple(sorted((k, v))))
output = [[k] if k == v else (k, v) for k, v in cycles]
print(output)
cycles = set(tuple(sorted(item)) for item in m.items() if m.get(item[1]) == item[0])
output = [[k] if k == v else (k, v) for k, v in cycles]
print(output)
def find_cycles(m):
n = m.copy() # don't mutilate the original
cycles = []
while n:
visited = {}
count = 0
k, v = n.popitem()
while v is not None:
visited[k] = (count, v)
count += 1
k = v
v = n.pop(k, None)
if k in visited:
cycle_start = visited[k][0]
item = min((k, v) for k, (c, v) in visited.items() if c >= cycle_start)
cycles.append(item)
return [[k] if k == v else (k, v) for k, v in cycles]
print(find_cycles(m))
print(find_cycles(n))
def find_cycles(m):
n = m.copy() # don't mutilate the original
cycles = []
while n:
visited = {}
count = 0
k, v = n.popitem()
while v is not None:
visited[k] = count
count += 1
k = v
v = n.pop(k, None)
if k in visited:
if len(visited) == 1:
cycle = list(visited.keys())
else:
cycle_start = visited[k]
cycle = sorted((c, k) for k, c in visited.items() if c >= cycle_start)
cycle = tuple(k for c, k in cycle)
k = min(range(len(cycle)), key=lambda x: cycle[x])
cycle = cycle[k:] + cycle[:k]
cycles.append(cycle)
return cycles
print(find_cycles(m))
print(find_cycles(n))
bSA9IHsxOiAyLCA3OiAzLCAyOiAxLCA0OiA0LCA1OiAzLCA2OiA5fQpuID0gezE6MiwgMjozLCAzOjQsIDQ6NSwgNToxLCA2OjEsIDc6MSwgODo4fQoKY3ljbGVzID0gc2V0KCkKZm9yIGssIHYgaW4gbS5pdGVtcygpOgogICAgaWYgbS5nZXQodikgPT0gazoKICAgICAgICBjeWNsZXMuYWRkKHR1cGxlKHNvcnRlZCgoaywgdikpKSkKCm91dHB1dCA9IFtba10gaWYgayA9PSB2IGVsc2UgKGssIHYpIGZvciBrLCB2IGluIGN5Y2xlc10KcHJpbnQob3V0cHV0KQoKY3ljbGVzID0gc2V0KHR1cGxlKHNvcnRlZChpdGVtKSkgZm9yIGl0ZW0gaW4gbS5pdGVtcygpIGlmIG0uZ2V0KGl0ZW1bMV0pID09IGl0ZW1bMF0pCgoKb3V0cHV0ID0gW1trXSBpZiBrID09IHYgZWxzZSAoaywgdikgZm9yIGssIHYgaW4gY3ljbGVzXQpwcmludChvdXRwdXQpCgpkZWYgZmluZF9jeWNsZXMobSk6CiAgICBuID0gbS5jb3B5KCkgICMgZG9uJ3QgbXV0aWxhdGUgdGhlIG9yaWdpbmFsCiAgICBjeWNsZXMgPSBbXQogICAgd2hpbGUgbjoKICAgICAgICB2aXNpdGVkID0ge30KICAgICAgICBjb3VudCA9IDAKICAgICAgICBrLCB2ID0gbi5wb3BpdGVtKCkKICAgICAgICB3aGlsZSB2IGlzIG5vdCBOb25lOgogICAgICAgICAgICB2aXNpdGVkW2tdID0gKGNvdW50LCB2KQogICAgICAgICAgICBjb3VudCArPSAxCiAgICAgICAgICAgIGsgPSB2CiAgICAgICAgICAgIHYgPSBuLnBvcChrLCBOb25lKQoKICAgICAgICBpZiBrIGluIHZpc2l0ZWQ6CiAgICAgICAgICAgIGN5Y2xlX3N0YXJ0ID0gdmlzaXRlZFtrXVswXQogICAgICAgICAgICBpdGVtID0gbWluKChrLCB2KSBmb3IgaywgKGMsIHYpIGluIHZpc2l0ZWQuaXRlbXMoKSBpZiBjID49IGN5Y2xlX3N0YXJ0KQogICAgICAgICAgICBjeWNsZXMuYXBwZW5kKGl0ZW0pCgogICAgcmV0dXJuIFtba10gaWYgayA9PSB2IGVsc2UgKGssIHYpIGZvciBrLCB2IGluIGN5Y2xlc10KCnByaW50KGZpbmRfY3ljbGVzKG0pKQpwcmludChmaW5kX2N5Y2xlcyhuKSkKCmRlZiBmaW5kX2N5Y2xlcyhtKToKICAgIG4gPSBtLmNvcHkoKSAgIyBkb24ndCBtdXRpbGF0ZSB0aGUgb3JpZ2luYWwKICAgIGN5Y2xlcyA9IFtdCiAgICB3aGlsZSBuOgogICAgICAgIHZpc2l0ZWQgPSB7fQogICAgICAgIGNvdW50ID0gMAogICAgICAgIGssIHYgPSBuLnBvcGl0ZW0oKQogICAgICAgIHdoaWxlIHYgaXMgbm90IE5vbmU6CiAgICAgICAgICAgIHZpc2l0ZWRba10gPSBjb3VudAogICAgICAgICAgICBjb3VudCArPSAxCiAgICAgICAgICAgIGsgPSB2CiAgICAgICAgICAgIHYgPSBuLnBvcChrLCBOb25lKQoKICAgICAgICBpZiBrIGluIHZpc2l0ZWQ6CiAgICAgICAgICAgIGlmIGxlbih2aXNpdGVkKSA9PSAxOgogICAgICAgICAgICAgICAgY3ljbGUgPSBsaXN0KHZpc2l0ZWQua2V5cygpKQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgY3ljbGVfc3RhcnQgPSB2aXNpdGVkW2tdCiAgICAgICAgICAgICAgICBjeWNsZSA9IHNvcnRlZCgoYywgaykgZm9yIGssIGMgaW4gdmlzaXRlZC5pdGVtcygpIGlmIGMgPj0gY3ljbGVfc3RhcnQpCiAgICAgICAgICAgICAgICBjeWNsZSA9IHR1cGxlKGsgZm9yIGMsIGsgaW4gY3ljbGUpCiAgICAgICAgICAgICAgICBrID0gbWluKHJhbmdlKGxlbihjeWNsZSkpLCBrZXk9bGFtYmRhIHg6IGN5Y2xlW3hdKQogICAgICAgICAgICAgICAgY3ljbGUgPSBjeWNsZVtrOl0gKyBjeWNsZVs6a10KICAgICAgICAgICAgY3ljbGVzLmFwcGVuZChjeWNsZSkKCiAgICByZXR1cm4gY3ljbGVzCgpwcmludChmaW5kX2N5Y2xlcyhtKSkKcHJpbnQoZmluZF9jeWNsZXMobikp
[(1, 2), [4]]
[(1, 2), [4]]
[(1, 2), [4]]
[(1, 2), [8]]
[(1, 2), [4]]
[(1, 2, 3, 4, 5), [8]]