Пример #1
0
def solution(M):
    """
    Snake and Ladders minimum moves solver.

    Every throw of dice generates one move possibility. Together they form a graph of all
     possible moves and associated distance, or number of preceding moves required to
     reach that cell. Using simple breadth-first search algorithm we'll be able to find
     the shortest distance to the last cell.

    Complexity: O(V+E) where `V` is number of cells and `E` is number of possible "jumps"
    :param list[int] M: List board representation
    :return int: Minimum amount of dice throws required to reach the final cell
    """
    from basic_data_structures.fifo import Queue, enqueue, dequeue, next as peek

    visited = [False] * (len(M) + 1)  # Map of visited cells
    visited[0] = True
    q = Queue(len(M))
    move = Move(0, 0)  # Generate first move
    enqueue(q, move)
    while q.length > 0:
        move = peek(q)
        if move.cell == len(M) - 1:
            break  # Reached the end, `move` is the last cell
        dequeue(q)
        for dice in range(1, 7):  # Try all the dice throws
            next_i = move.cell + dice
            if next_i < len(M):
                if visited[next_i] is False:
                    visited[next_i] = True
                    if M[next_i] == 0:
                        enqueue(q, Move(next_i, move.dist + 1))
                    else:
                        enqueue(q, Move(M[next_i], move.dist + 1))
    return move.dist
Пример #2
0
def build(D, s, t):
    """
    Words production sequence path builder using BFS algorithm.

    This BFS sub-routine connects vertices in a graph, writes parent pointers and
     distance from the source string.

    Complexity: O(n+nm) from BFS, where `n` is the number of words in the dictionary and
     `m` is the length of words used. Time devoted to construction of candidate strings
     is constant bound to the alphabet size. The number of edges in the worst case is
     `n^2`.
    :param set D: Dictionary (set) of words
    :param str s: Source string
    :param str t: Target string
    :return Vertex|None: Vertex containing target string (if found)
    """
    n = len(D)
    Q = Queue(n)
    D.remove(s)  # Remove used word from a dictionary
    enqueue(Q, Vertex(s, 0))
    while Q.length > 0:
        v = peek(Q)
        if v.candidate_string == t:
            return v  # Target is found
        cs = list(v.candidate_string)  # Converting to list, strings are immutable
        # Try all possible permutations of a candidate string
        for i in range(0, len(cs)):
            for c in ALPHABET:
                cs[i] = c
                cs_as_str = "".join(cs)
                if cs_as_str in D:
                    D.remove(cs_as_str)
                    enqueue(Q, Vertex(cs_as_str, v.distance + 1, v))
            cs[i] = v.candidate_string[i]
        dequeue(Q)
    return None