Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- def find_ladders(begin_word, end_word, word_list)
- // Return an empty array if the end word isn't in the provided list
- return [] unless (unvisited = word_list.to_set).include?(end_word)
- // Build the words used to transform by using the graph implementation?
- words_by_transform = graph_word_transforms(begin_word, end_word, unvisited)
- // Reverse the path of DFS so you get word -> end word and not end word -> word
- reverse_dfs_paths(begin_word, end_word, words_by_transform)
- end
- def graph_word_transforms(begin_word, end_word, unvisited)
- // Hash where word is key and potential transformations is value as a set (I think)
- words_by_transform = Hash.new { |h, k| h[k] = Set.new }
- // transformations are each position in the word with all possible changes A-Z?
- transformations = Array(0...begin_word.size).product(Array('a'..'z'))
- unvisited.delete(end_word)
- // Begin layer is a new set, end layer is a set containing the end word
- begin_layer, end_layer = Set.new, Set[end_word]
- // prev is the end layer, curr is the begin (new set), next is a set with begin word?
- prev_layer, curr_layer, next_layer = end_layer, begin_layer, Set[begin_word]
- // next_layer used as stack for DFS? Not sure what's going on here
- until next_layer.empty? || end_layer.any? { |t| words_by_transform[t].intersect?(begin_layer) }
- // layer traversal?
- curr_layer.replace(next_layer)
- // Swap positions of layers?
- curr_layer, prev_layer = prev_layer, curr_layer
- // Remove each layer from unvisted
- unvisited.subtract(prev_layer)
- // Not sure why we clear the next layers set?
- next_layer.clear
- curr_layer.each do |word|
- transformations.each do |i, c|
- // I think this is checking if the word character position transformed at index
- // Is the same as the char from a to z so we don't transform the same twice?
- next if word[i] == c
- // No clue what this is doing?
- transform = word.dup.tap { |w| w[i] = c }
- // Push the transform to the next layer if unvisited includes the transformed
- // word?
- next_layer << transform if (is_neighbor = unvisited.include?(transform))
- // Not sure about this part
- if is_neighbor || prev_layer.include?(transform)
- orig_word, variant = curr_layer.equal?(begin_layer) ? [word, transform] : [transform, word]
- words_by_transform[variant] << orig_word
- end
- end
- end
- end
- words_by_transform
- end
- // Reverse the DFS path so we go from begin word -> end word rather than end word -> begin?
- def reverse_dfs_paths(begin_word, end_word, word_graph)
- paths, path = [], []
- stack = [[end_word, 1]]
- until stack.empty?
- word, lvl = stack.pop
- path.pop until path.size < lvl
- path << word
- if word == begin_word
- paths << path.reverse
- else
- word_graph[word].each { |w| stack << [w, lvl + 1] }
- end
- end
- paths
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement