Extract some common utilities into a library.

This commit is contained in:
Danila Fedorin 2020-12-05 15:36:08 -08:00
parent 7826194b37
commit e9d0701b4c
4 changed files with 13 additions and 170 deletions

View File

@ -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
View File

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

View File

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

13
shard.yml Normal file
View File

@ -0,0 +1,13 @@
name: advent-2020
version: 0.1.0
authors:
- your-name-here <your-email-here>
dependencies:
advent:
git: https://dev.danilafe.com/Advent-of-Code/advent
crystal: 0.35.1
license: MIT