Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,39 @@
Marco? Polo!

[A data structures and algorithms Ruby challenge from the Viking Code School](http://www.vikingcodeschool.com)

Chad Lucas

What data structure is used to implement DFS?
Stack

What data structure is typically used to implement BFS?
Queue

Which one can be done recursively? (the clue should be the data structure)
DFS

Which one would you use to print a list of all the nodes in a tree or graph, starting with depth 1, then depth 2, then depth 3 etc.?
BFS

What is the difference between a tree and a graph?
Graphs are fully unconstrained as to which vertices can connect to which ones. Trees have a strictly hierarchical structure where each node has a defined parent.

Pseudocode the following processes:

Searching a simple tree of nodes where each Node has an array of child nodes (some_node.children) using DFS.

Push the root node onto the stack
Pop a node off the stack
Return if is the search value
Else look at any unsearched children
Push "worst" nodes onto the stack first
Push "best" nodes onto the stack last
Repeat from step 2 until search value is found or no nodes left
Searching the same tree using BFS.

Starting at the root node
Return if is the search value
Else look at all the direct children of current node
Repeat from step 2 until search value is found or no nodes left

45 changes: 45 additions & 0 deletions knight_searcher.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
require_relative 'move_tree'

class KnightSearcher
attr_reader :move_tree

def initialize(move_tree)
@move_tree = move_tree
end

def bfs_for(target_coords)

start = move_tree.root
start.depth = 0
queue = [start]

until queue.empty?
current = queue.pop

# either you have found the right node,
# and you return the path you got there with
if targer_coords == [current.x, current.y]
return trace_path_to(current)

#or you add all children you habe not yet visited to the queue
else
current.children.each do |move|
next if move.depth #skip if already visited
queue.shift(move)
move.depth = current.depth + 1
end
end
end
end

def trace_path_to(move)
path = []
node = move

until node.nil?
path.unshift [node.x, node.y]
node = node.parent
end
path
end
end
78 changes: 78 additions & 0 deletions move_tree.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
Move = Struct.new(:x, :y, :depth, :parent, :children)

class MoveTree
attr_reader :start_node, :max_depth, :node_count

# tree = MoveTree.new([3,3], 1)
def initialize(start_coords, max_depth)
x, y = start_coords[0], start_coords[1]

@start_node = Move.new(x, y, nil, nil, [])
@max_depth = max_depth
@node_count = 1 # the initial one

build_tree
puts inspect
end

def inspect
"This move tree begins at [#{start_node.x},#{start_node.y}], has a maximum depth of #{max_depth}, and has #{node_count} total nodes."
end



private

#recursively builds the tree of possible moves to the given
# @max_depth.
def build_tree(current_node = self.start_node, depth = 0)

if depth < self.max_depth
append_next_moves(current_node)

# build the tree again on each child
current_node.children.each do |child|
build_tree(child, depth + 1)
end
end

end


# appends all possible next_moves to the current move
# properly updates the number of nodes
def append_next_moves(current_move)
return unless current_move.children.empty?

next_moves = possible_moves(current_move)
@node_count += next_moves.size


next_moves.each do |move|
new_move = Move.new( move[0], move[1],
nil, current_move , [] )
current_move.children << new_move
end
end


#takes a Move
#returns a 2D array of all legal moves for a knight
#from one position, in the form of coordinate pairs
def possible_moves(move)
x, y = move.x, move.y

[ [x+2, y-1], [x+2, y+1],
[x-2, y+1], [x-2, y-1],
[x+1, y+2], [x-1, y+2],
[x+1, y-2], [x-1, y-2] ].select { |move| legal?(move) }
end

#checks if a move is legal for a knight from the current location
def legal?(move)
move[0].between?(0, 7) && move[1].between?(0,7)
end
end #class


tree = MoveTree.new([3,3], 1)