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
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