import copy
found = set()
def moves_to_angles(moves):
angles = ""
MOVE = {"U": 0, "R": 1, "D": 2, "L": 3}
def convert(x,y):
if x == y:
return "F"
elif (MOVE[x] - MOVE[y]) % 4 == 1:
return "C"
else:
return "A"
for i in range(1, len(moves)):
angles += convert(moves[i], moves[i-1])
angles += convert(moves[0], moves[len(moves)-1])
return angles
def equal(moves2a, moves2b):
# Cyclically equal or cyclically equal after A <-> C
for i in range(len(moves2a)):
if moves2a[i:]+moves2a[:i] == moves2b: # or (moves2a[i:]+moves2a[:i])[::-1] == moves2b:
return True
new_moves2a = ""
D = {"A": "C", "F": "F", "C": "A"}
for c in moves2a:
new_moves2a += D[c]
for i in range(len(new_moves2a)):
if new_moves2a[i:]+new_moves2a[:i] == moves2b: # or (new_moves2a[i:]+new_moves2a[:i])[::-1] == moves2b:
return True
return False
def solve(rods, point=(0,0), moves="", moves2="", visited=None):
if not rods:
if point == (0, 0):
angles2 = moves_to_angles(moves2)
if angles2.count("A") - angles2.count("C") == 4:
# Take anticlockwise
for f in found:
if equal(f, angles2):
break
else:
found.add(angles2)
print(moves, angles2)
return
if not visited:
visited = set()
new_rods = rods[:]
r = new_rods.pop(0)
for m,d in [((r,0), "R"), ((0,r), "U"), ((-r,0), "L"), ((0,-r), "D")]:
new_point = (m[0]+point[0],m[1]+point[1])
new_visited = copy.deepcopy(visited)
search = True
for i in range(min(point[0],new_point[0]), max(point[0],new_point[0])+1):
for j in range(min(point[1],new_point[1]), max(point[1],new_point[1])+1):
if (i, j) != point:
if (i, j) in new_visited:
search = False
else:
new_visited.add((i, j))
if search:
solve(new_rods, new_point, moves+d, moves2+d*r, new_visited)
solve([1,2,3,4,5,6,7])
aW1wb3J0IGNvcHkKCmZvdW5kID0gc2V0KCkKCmRlZiBtb3Zlc190b19hbmdsZXMobW92ZXMpOgogICAgYW5nbGVzID0gIiIKCiAgICBNT1ZFID0geyJVIjogMCwgIlIiOiAxLCAiRCI6IDIsICJMIjogM30KCiAgICBkZWYgY29udmVydCh4LHkpOgogICAgICAgIGlmIHggPT0geToKICAgICAgICAgICAgcmV0dXJuICJGIgoKICAgICAgICBlbGlmIChNT1ZFW3hdIC0gTU9WRVt5XSkgJSA0ID09IDE6CiAgICAgICAgICAgIHJldHVybiAiQyIKCiAgICAgICAgZWxzZToKICAgICAgICAgICAgcmV0dXJuICJBIgogICAgCiAgICBmb3IgaSBpbiByYW5nZSgxLCBsZW4obW92ZXMpKToKICAgICAgICBhbmdsZXMgKz0gY29udmVydChtb3Zlc1tpXSwgbW92ZXNbaS0xXSkKCiAgICBhbmdsZXMgKz0gY29udmVydChtb3Zlc1swXSwgbW92ZXNbbGVuKG1vdmVzKS0xXSkKCiAgICByZXR1cm4gYW5nbGVzCgpkZWYgZXF1YWwobW92ZXMyYSwgbW92ZXMyYik6CiAgICAjIEN5Y2xpY2FsbHkgZXF1YWwgb3IgY3ljbGljYWxseSBlcXVhbCBhZnRlciBBIDwtPiBDCiAgICBmb3IgaSBpbiByYW5nZShsZW4obW92ZXMyYSkpOgogICAgICAgIGlmIG1vdmVzMmFbaTpdK21vdmVzMmFbOmldID09IG1vdmVzMmI6ICMgb3IgKG1vdmVzMmFbaTpdK21vdmVzMmFbOmldKVs6Oi0xXSA9PSBtb3ZlczJiOgogICAgICAgICAgICByZXR1cm4gVHJ1ZQoKICAgIG5ld19tb3ZlczJhID0gIiIKICAgIEQgPSB7IkEiOiAiQyIsICJGIjogIkYiLCAiQyI6ICJBIn0KICAgIAogICAgZm9yIGMgaW4gbW92ZXMyYToKICAgICAgICBuZXdfbW92ZXMyYSArPSBEW2NdCgogICAgZm9yIGkgaW4gcmFuZ2UobGVuKG5ld19tb3ZlczJhKSk6CiAgICAgICAgaWYgbmV3X21vdmVzMmFbaTpdK25ld19tb3ZlczJhWzppXSA9PSBtb3ZlczJiOiAjIG9yIChuZXdfbW92ZXMyYVtpOl0rbmV3X21vdmVzMmFbOmldKVs6Oi0xXSA9PSBtb3ZlczJiOgogICAgICAgICAgICByZXR1cm4gVHJ1ZQoKICAgIHJldHVybiBGYWxzZQoKZGVmIHNvbHZlKHJvZHMsIHBvaW50PSgwLDApLCBtb3Zlcz0iIiwgbW92ZXMyPSIiLCB2aXNpdGVkPU5vbmUpOgogICAgaWYgbm90IHJvZHM6CiAgICAgICAgaWYgcG9pbnQgPT0gKDAsIDApOgogICAgICAgICAgICBhbmdsZXMyID0gbW92ZXNfdG9fYW5nbGVzKG1vdmVzMikKCiAgICAgICAgICAgIGlmIGFuZ2xlczIuY291bnQoIkEiKSAtIGFuZ2xlczIuY291bnQoIkMiKSA9PSA0OgogICAgICAgICAgICAgICAgIyBUYWtlIGFudGljbG9ja3dpc2UKICAgICAgICAgICAgICAgIGZvciBmIGluIGZvdW5kOgogICAgICAgICAgICAgICAgICAgIGlmIGVxdWFsKGYsIGFuZ2xlczIpOgogICAgICAgICAgICAgICAgICAgICAgICBicmVhawoKICAgICAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICAgICAgZm91bmQuYWRkKGFuZ2xlczIpICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgcHJpbnQobW92ZXMsIGFuZ2xlczIpCiAgICAgICAgcmV0dXJuCiAgICAgICAgCiAgICBpZiBub3QgdmlzaXRlZDoKICAgICAgICB2aXNpdGVkID0gc2V0KCkKCiAgICBuZXdfcm9kcyA9IHJvZHNbOl0KICAgIHIgPSBuZXdfcm9kcy5wb3AoMCkKCiAgICBmb3IgbSxkIGluIFsoKHIsMCksICJSIiksICgoMCxyKSwgIlUiKSwgKCgtciwwKSwgIkwiKSwgKCgwLC1yKSwgIkQiKV06CiAgICAgICAgbmV3X3BvaW50ID0gKG1bMF0rcG9pbnRbMF0sbVsxXStwb2ludFsxXSkKICAgICAgICBuZXdfdmlzaXRlZCA9IGNvcHkuZGVlcGNvcHkodmlzaXRlZCkKICAgICAgICBzZWFyY2ggPSBUcnVlCiAgICAgICAgCiAgICAgICAgZm9yIGkgaW4gcmFuZ2UobWluKHBvaW50WzBdLG5ld19wb2ludFswXSksIG1heChwb2ludFswXSxuZXdfcG9pbnRbMF0pKzEpOgogICAgICAgICAgICBmb3IgaiBpbiByYW5nZShtaW4ocG9pbnRbMV0sbmV3X3BvaW50WzFdKSwgbWF4KHBvaW50WzFdLG5ld19wb2ludFsxXSkrMSk6CiAgICAgICAgICAgICAgICBpZiAoaSwgaikgIT0gcG9pbnQ6CiAgICAgICAgICAgICAgICAgICAgaWYgKGksIGopIGluIG5ld192aXNpdGVkOgogICAgICAgICAgICAgICAgICAgICAgICBzZWFyY2ggPSBGYWxzZQogICAgICAgICAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICAgICAgICAgIG5ld192aXNpdGVkLmFkZCgoaSwgaikpCiAgICAgICAgICAgICAgICAKICAgICAgICBpZiBzZWFyY2g6CiAgICAgICAgICAgIHNvbHZlKG5ld19yb2RzLCBuZXdfcG9pbnQsIG1vdmVzK2QsIG1vdmVzMitkKnIsIG5ld192aXNpdGVkKQoKCnNvbHZlKFsxLDIsMyw0LDUsNiw3XSkK