Flexible List Cleaner

Question:

I have a list:

sol = ["U", "U'","U","R","R'", "R", "R", "R", "R","U","U'"]

I also created a function to clean this list:

def cleanSol(sol):
    res = '-'.join(sol)
    moveList = ['U', "U'", 'U2', 'D', "D'", 'D2', 'R', "R'", 'R2', 'L', "L'", 'L2', 'F', "F'", 'F2', 'B', "B'", 'B2', 'Y', "Y'", 'X', "X'", 'Z', "Z'", 'M', "M'", 'M2', 'E', "E'", 'E2', 'S', "S'", 'S2']
    for move in moveList:
        if move in res: # save time
            if (literal:= (f"{move}-"*4)[:-1]) and literal in res:
                res = res.replace(literal,"")
            if (literal:= f"{move}-{move}'") and literal in res:
                res = res.replace(literal,"")
            if (literal:= f"{move}'-{move}") and literal in res: 
                res = res.replace(literal,"")
            if (literal:= f"{move}-{move}") and literal in res:
                res = res.replace(literal,move+"2")
    return [r for r in res.split('-') if r] # remove emptry strings

My basic requirements are:

  • If 4 continuous instances of same move is in sol, remove them. For example, if R, R, R, R is in sol remove all the instances.
  • If move and it’s inverse is in sol, remove them. For example, if U, U' is in sol remove all the instances.
  • Same as above, just U' U inverse.
  • If only 2 moves are same, add a 2.

Samples:-

Input:

sol = ["U", "U'","U","R","R'", "R", "R", "R", "R","U'","U"]

Output:

>>> ['U']

Expected Output:

>>> ['U']

Tweek: I am using - as a simple separator and is not related with the list.

My solution works pretty well, but I think it’s too length and I’m looking for efficient solutions 🙂

Asked By: The Myth

||

Answers:

Mine is also lengthy but easy to follow, I just wanted to share as a second approach.

Here I check the list in a while True many times, every time from the beginning. If first items are removable, I remove them and start the loop again, if not I check next few items. I’ve put comment for each section.

def cleanSol(lst):
    while True:
        flag = False
        for i, item in enumerate(lst):
            inverse = item.replace("'", "") if "'" in item else item[0] + "'" + item[1:]

            # To remove "U" and "U'"
            if i < len(lst) - 1 and lst[i + 1] == inverse:
                del lst[i : i + 2]
                flag = True
                break

            # To remove "U", "U", "U", "U"
            if len(lst) >= 4 and set(lst[i : i + 4]) == {item}:
                del lst[i : i + 4]
                flag = True
                break

            # The two "U2", "U2", makes "U22" this should Also be removed.
            if "22" in item:
                del lst[i]
                flag = True
                break

            # To remove "U", "U2", "U"
            if i < len(lst) - 2 and item == lst[i + 2] and item == f"{lst[i+1]}2":
                del lst[i : i + 3]
                flag = True
                break

            # To convert "U", "U" to "U2"
            if i < len(lst) - 1 and item == lst[i + 1]:
                lst[i] = f"{item}2"
                del lst[i + 1]
                flag = True
                break

        if not flag:
            break
    return lst


for test in (
    ["U", "U'", "U", "R", "R'", "R", "R", "R", "R", "U'", "U"],
    ["U2", "U", "U", "R2", "R'", "R", "R"],
    ["U2", "U", "R", "R'", "U", "R", "R"],
):
    print(cleanSol(test))

This is now more flexible compared to the previous answer. For example it can now handle ["U2", "U", "U"] and ["U2", "U2"].

Answered By: S.B
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.