-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcodingame.rb
More file actions
136 lines (104 loc) · 3.38 KB
/
codingame.rb
File metadata and controls
136 lines (104 loc) · 3.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
require "set"
require "benchmark"
require "pry"
STDOUT.sync = true # DO NOT REMOVE
def debug(message)
STDERR.puts message
end
# Implements a directionless and weightless graph structure with named nodes
class Graph
# Key data storage.
# Each key is a node (key == name),
# and the value set represents the neighbouring nodes.
# private attr_reader :structure
def initialize
@structure =
Hash.new do |hash, key|
hash[key] = {outgoing: Set.new, incoming: Set.new}
end
end
# A shorthand access to underlying has node structure
def [](node)
structure[node]
end
def nodes
structure.keys
end
# adds a bi-directional connection between two nodes
def connect_nodes_bidirectionally(node1, node2)
structure[node1][:incoming] << node2
structure[node1][:outgoing] << node2
structure[node2][:incoming] << node1
structure[node2][:outgoing] << node1
nil
end
# Severs all connections to and from this node
# @return [nil]
def remove_node(node)
structure[node][:incoming].each do |other_node|
structure[other_node][:outgoing] -= [node]
end
structure.delete(node)
nil
end
# @root/@destination [String] # "1, 4"
#
# @return [Array, nil] # will return an array of nodes from root to destination, or nil if no path exists
def dijkstra_shortest_path(root, destination)
# When we choose the arbitrary starting parent node we mark it as visited by changing its state in the 'visited' structure.
visited = Set.new([root])
parent_node_list = {root => nil}
# Then, after changing its value from FALSE to TRUE in the "visited" hash, we’d enqueue it.
queue = [root]
# Next, when dequeing the vertex, we need to examine its neighboring nodes, and iterate (loop) through its adjacent linked list.
loop do
dequeued_node = queue.shift
# debug "dequed '#{ dequeued_node }', remaining queue: '#{ queue }'"
if dequeued_node.nil?
return
# raise("Queue is empty, but destination not reached!")
end
neighboring_nodes = structure[dequeued_node][:outgoing]
# debug "neighboring_nodes for #{ dequeued_node }: '#{ neighboring_nodes }'"
neighboring_nodes.each do |node|
# If either of those neighboring nodes hasn’t been visited (doesn’t have a state of TRUE in the “visited” array),
# we mark it as visited, and enqueue it.
next if visited.include?(node)
visited << node
parent_node_list[node] = dequeued_node
# debug "parents: #{ parent_node_list }"
if node == destination
# destination reached
path = [node]
loop do
parent_node = parent_node_list[path[0]]
return path if parent_node.nil?
path.unshift(parent_node)
# debug "path after update: #{ path }"
end
else
queue << node
end
end
end
end
private
def structure
@structure
end
def initialize_copy(copy)
dupped_structure =
structure.each_with_object({}) do |(k, v), mem|
mem[k] =
v.each_with_object({}) do |(sk, sv), smem|
smem[sk] = sv.dup
end
end
copy.instance_variable_set("@structure", dupped_structure)
super
end
end
# Put the one-time game setup code tha comes before `loop do` here.
loop do
puts "WAIT"
end