### Extract some common utilities into a library.

This commit is contained in:
parent 7826194b37
commit e9d0701b4c
4 changed files with 13 additions and 170 deletions

#### 48 graph.cr 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`

#### 39 knapsack.cr 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 ` ``` ``` `dependencies:` ` advent:` ` git: https://dev.danilafe.com/Advent-of-Code/advent` ``` ``` `crystal: 0.35.1` ``` ``` `license: MIT`