Red Knight's Shortest Path

  • + 0 comments

    Easily readible python solution

    class Node:
        def __init__(self, x, y):
            self.state = (x, y)
            self.parent: Node = None
            self.action: str
    
    
    def find_path(node):
        path = []
        while node.parent is not None:
            path.append(node.action)
            node = node.parent
        return path[::-1]  # Reverse the path to get the correct order
    
    
    def actions(current_node, n):
        current_r, current_c = current_node.state
    
        children = []
    
        # a = [UL, UR, R, LR, LL, L]
        dr = [-2, -2, 0, 2, 2, 0]
        dc = [-1, 1, 2, 1, -1, -2]
    
        for i in range(0, 6):
    
            possible_r = current_r + dr[i]
            possible_c = current_c + dc[i]
    
            # Check it is not out of bounds.
            if possible_r < 0 or possible_c < 0:
                continue
            if possible_r > n - 1 or possible_c > n - 1:
                continue
    
            child = Node(possible_r, possible_c)
            child.parent = current_node
    
            if i == 0:
                child.action = "UL"
            elif i == 1:
                child.action = "UR"
            elif i == 2:
                child.action = "R"
            elif i == 3:
                child.action = "LR"
            elif i == 4:
                child.action = "LL"
            elif i == 5:
                child.action = "L"
    
            children.append(child)
        return children
    
    
    def printShortestPath(n, i_start, j_start, i_end, j_end):
        # start_node = Node(i_start, j_start)
        start_node = Node(i_start, j_start)
        goal_node = Node(i_end, j_end)
    
        visited = set()
        queue = [start_node]
        while queue:
            current_node = queue.pop(0)
    
            if current_node.state == goal_node.state:
                path = find_path(current_node)
                print(len(path))
                print(' '.join(path))
                return
    
            if current_node.state not in visited:
                visited.add(current_node.state)
    
            children = actions(current_node, n)
    
            for child in children:
                if child.state not in visited and child not in queue:
                    visited.add(child.state)  # Nodes are added to the visited set as soon as they are added to the queue,
                    # ensuring they are not re-added.
                    queue.append(child)
    
        print("Impossible")