Extract some common utilities into a library.
This commit is contained in:
parent
7826194b37
commit
e9d0701b4c
48
graph.cr
48
graph.cr
|
@ -1,48 +0,0 @@
|
||||||
class Graph(A)
|
|
||||||
def initialize
|
|
||||||
@edges = {} of A => Set({A, Int32})
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_edge(f, t, c = 1)
|
|
||||||
@edges[f] ||= Set({A, Int32}).new
|
|
||||||
@edges[f] << {t, c}
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_biedge(f, t, c = 1)
|
|
||||||
add_edge(f, t, c)
|
|
||||||
add_edge(t, f, c)
|
|
||||||
end
|
|
||||||
|
|
||||||
def find_path(f, t)
|
|
||||||
visited = Set(A).new
|
|
||||||
candidates = Set { f }
|
|
||||||
distances = {f => 0}
|
|
||||||
prev = {} of A => A
|
|
||||||
|
|
||||||
while !candidates.empty?
|
|
||||||
candidate = candidates.min_by { |c| distances[c] }
|
|
||||||
break if candidate == t
|
|
||||||
visited << candidate
|
|
||||||
candidates.delete candidate
|
|
||||||
dist = distances[candidate]
|
|
||||||
|
|
||||||
@edges.fetch(candidate, Set({A, Int32}).new).each do |e|
|
|
||||||
node, cost = e
|
|
||||||
new_dist = dist + cost
|
|
||||||
candidates << node unless visited.includes? node
|
|
||||||
next if (old_dist = distances[node]?) && old_dist < new_dist
|
|
||||||
distances[node] = new_dist
|
|
||||||
prev[node] = candidate
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
backtrack = t
|
|
||||||
path = [t] of A
|
|
||||||
while backtrack != f
|
|
||||||
return nil unless prev_bt = prev[backtrack]?
|
|
||||||
path << prev_bt
|
|
||||||
backtrack = prev_bt
|
|
||||||
end
|
|
||||||
{path.reverse!, distances[t]}
|
|
||||||
end
|
|
||||||
end
|
|
83
heap.cr
83
heap.cr
|
@ -1,83 +0,0 @@
|
||||||
class Array(T)
|
|
||||||
def bubble_up(i, &cmp)
|
|
||||||
return if i >= size
|
|
||||||
while i != 0
|
|
||||||
j = (i-1)//2
|
|
||||||
break if yield self[i], self[j]
|
|
||||||
self[i], self[j] = self[j], self[i]
|
|
||||||
i = j
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def percalate_down(i, &cmp)
|
|
||||||
while i*2+1 < size
|
|
||||||
j1, j2 = i*2+1, i*2+2
|
|
||||||
v1 = self[j1]
|
|
||||||
v2 = self[j2]?
|
|
||||||
if v2 && (yield v1, v2) && (yield self[i], v2)
|
|
||||||
self[j2], self[i] = self[i], v2
|
|
||||||
i = j2
|
|
||||||
elsif yield self[i], v1
|
|
||||||
self[j1], self[i] = self[i], v1
|
|
||||||
i = j1
|
|
||||||
else
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def heapify(&cmp : T,T -> Bool)
|
|
||||||
size.times do |i|
|
|
||||||
i = size - i - 1
|
|
||||||
bubble_up(i, &cmp)
|
|
||||||
end
|
|
||||||
self
|
|
||||||
end
|
|
||||||
|
|
||||||
def heapify
|
|
||||||
heapify do |i,j|
|
|
||||||
i < j
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def heap_push(v, &cmp : T,T -> Bool)
|
|
||||||
self << v
|
|
||||||
bubble_up(size - 1, &cmp)
|
|
||||||
end
|
|
||||||
|
|
||||||
def heap_push(v)
|
|
||||||
heap_push(v) do |i,j|
|
|
||||||
i < j
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def heap_pop(&cmp : T,T -> Bool)
|
|
||||||
self[0], self[size-1] = self[size-1], self[0]
|
|
||||||
v = pop
|
|
||||||
percalate_down(0, &cmp)
|
|
||||||
v
|
|
||||||
end
|
|
||||||
|
|
||||||
def heap_pop
|
|
||||||
heap_pop do |i, j|
|
|
||||||
i < j
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def is_heap?(&cmp : T,T -> Bool)
|
|
||||||
(size-1).times do |i|
|
|
||||||
i = size - i - 1
|
|
||||||
vi = self[i]
|
|
||||||
vp = self[(i-1)//2]
|
|
||||||
return false unless (yield self[i], self[(i-1)//2]) || vi == vp
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
def is_heap?
|
|
||||||
is_heap? do |i,j|
|
|
||||||
i < j
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
39
knapsack.cr
39
knapsack.cr
|
@ -1,39 +0,0 @@
|
||||||
class Array(T)
|
|
||||||
def knapsack(budget, &cv : T -> {Int32,Int32})
|
|
||||||
cost_values = map &cv
|
|
||||||
|
|
||||||
memo = {} of {Int32, Int32} => Int32
|
|
||||||
bt = {} of {Int32, Int32} => Bool
|
|
||||||
compute = uninitialized Int32, Int32 -> Int32
|
|
||||||
compute = ->(size : Int32, budget : Int32) {
|
|
||||||
if m = memo[{size, budget}]?
|
|
||||||
return m
|
|
||||||
end
|
|
||||||
return memo[{size, budget}] = 0 if size == 0
|
|
||||||
|
|
||||||
cost, value = cost_values[size-1]
|
|
||||||
no_val = compute.call(size-1, budget)
|
|
||||||
yes_val = (budget < cost) ? 0 : compute.call(size-1, budget - cost) + value
|
|
||||||
|
|
||||||
if yes_val > no_val
|
|
||||||
bt[{size, budget}] = true
|
|
||||||
return yes_val
|
|
||||||
else
|
|
||||||
bt[{size, budget}] = false
|
|
||||||
return no_val
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
value = compute.call(size, budget)
|
|
||||||
i = size
|
|
||||||
items = [] of T
|
|
||||||
while i != 0
|
|
||||||
if bt[{i, budget}]
|
|
||||||
items << self[i-1]
|
|
||||||
budget -= cost_values[i-1][0]
|
|
||||||
end
|
|
||||||
i -= 1
|
|
||||||
end
|
|
||||||
{value, items}
|
|
||||||
end
|
|
||||||
end
|
|
Loading…
Reference in New Issue
Block a user