Skip to content

Release/v0.16.0 #16

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions lib/algorithmable.rb
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@ module Algorithmable
autoload :LevenshteinDistance, 'algorithmable/levenshtein_distance'
autoload :Cups, 'algorithmable/cups'
autoload :Cache, 'algorithmable/cache'
autoload :Trees, 'algorithmable/trees'
autoload :UnionFind, 'algorithmable/union_find'

class << self
24 changes: 12 additions & 12 deletions lib/algorithmable/data_structs/linked_list/doubly.rb
Original file line number Diff line number Diff line change
@@ -2,18 +2,6 @@ module Algorithmable
module DataStructs
module LinkedList
class Doubly < Base
class Node
attr_accessor :item, :prev, :next, :front

def initialize(item, prev_pointer = nil, next_pointer = nil)
@item = item
@prev = prev_pointer
@next = next_pointer
end
end

private_constant :Node

def push_front(item)
prev_front = @front
node = new_node item, nil, prev_front
@@ -80,6 +68,18 @@ def delete(item)
def new_node(item, prev_pointer = nil, next_pinter = nil)
Node.new item, prev_pointer, next_pinter
end

class Node
attr_accessor :item, :prev, :next, :front

def initialize(item, prev_pointer = nil, next_pointer = nil)
@item = item
@prev = prev_pointer
@next = next_pointer
end
end

private_constant :Node
end
end
end
21 changes: 11 additions & 10 deletions lib/algorithmable/data_structs/linked_list/singly.rb
Original file line number Diff line number Diff line change
@@ -2,16 +2,6 @@ module Algorithmable
module DataStructs
module LinkedList
class Singly < Base
class Node
attr_accessor :item, :next, :front

def initialize(item, next_pointer = nil)
@item = item
@next = next_pointer
end
end

private_constant :Node

def push_front(obj)
node = new_node(obj)
@@ -182,6 +172,17 @@ def remove_next(prev)
def new_node(item, next_pinter = nil)
Node.new item, next_pinter
end

class Node
attr_accessor :item, :next, :front

def initialize(item, next_pointer = nil)
@item = item
@next = next_pointer
end
end

private_constant :Node
end
end
end
6 changes: 4 additions & 2 deletions lib/algorithmable/data_structs/ordered_symbol_table.rb
Original file line number Diff line number Diff line change
@@ -2,12 +2,14 @@ module Algorithmable
module DataStructs
class OrderedSymbolTable
extend Forwardable
include Algorithmable::Trees

private_methods :new_binary_search_tree

def_delegators :@imp, :[]=, :[], :key?, :empty?, :size, :keys, :max, :min, :floor, :ceiling, :rank, :delete

def initialize(key_type, value_type)
search_strategy_factory = Object.new.extend Algorithmable::Searches
@imp = search_strategy_factory.new_binary_search_tree(key_type, value_type)
@imp = new_binary_search_tree(key_type, value_type)
end
end
end
14 changes: 12 additions & 2 deletions lib/algorithmable/graphs.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
module Algorithmable
module Graphs
autoload :Undirected, 'algorithmable/graphs/undirected'
autoload :Traversals, 'algorithmable/graphs/traversals'
require 'algorithmable/graphs/directed'
require 'algorithmable/graphs/edge'
require 'algorithmable/graphs/traversals'
require 'algorithmable/graphs/undirected'

class << self
def new_undirected_graph(vertices = [])
@@ -11,6 +13,14 @@ def new_undirected_graph(vertices = [])
end
graph
end

def new_directed_graph(vertices = [])
Directed.new.tap do |g|
vertices.each do |from, to, weight|
g.add_edge Edge.new(from, to, weight)
end
end
end
end
end
end
45 changes: 45 additions & 0 deletions lib/algorithmable/graphs/directed.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
module Algorithmable
module Graphs
class Directed
def initialize
@edges = 0
@incoming_degree = []
@adjacency_list = []
end

def add_edge(edge)
from = edge.from
to = edge.to
validate_vertex(to)
validate_vertex(from)
(@adjacency_list[from] ||= [])
.tap { |xs| xs << edge }
(@incoming_degree[to] ||= 0)
.tap { @incoming_degree[to] += 1 }
@edges += 1
end

def adjacency_list(vertex)
@adjacency_list[vertex] || []
end

def out_degree(vertex)
@adjacency_list[vertex].length
end

def in_degree(vertex)
@incoming_degree[vertex]
end

def edges
@adjacency_list.dup
end

private

def validate_vertex(value)
raise "invalid vertex value: #{value}" if 0 > value
end
end
end
end
14 changes: 14 additions & 0 deletions lib/algorithmable/graphs/edge.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module Algorithmable
module Graphs
class Edge
attr_reader :from, :to, :weight

def initialize(from, to, weight)
@from = from
@to = to
@weight = weight
freeze
end
end
end
end
7 changes: 4 additions & 3 deletions lib/algorithmable/graphs/traversals.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
module Algorithmable
module Graphs
module Traversals
autoload :Errors, 'algorithmable/graphs/traversals/errors'
autoload :DepthFirst, 'algorithmable/graphs/traversals/depth_first'
autoload :BreadthFirst, 'algorithmable/graphs/traversals/breadth_first'
require 'algorithmable/graphs/traversals/errors'
require 'algorithmable/graphs/traversals/depth_first'
require 'algorithmable/graphs/traversals/breadth_first'
require 'algorithmable/graphs/traversals/topological_sort'

def traverse_with_depth_first(graph, source)
DepthFirst.new(graph, source)
12 changes: 7 additions & 5 deletions lib/algorithmable/graphs/traversals/breadth_first.rb
Original file line number Diff line number Diff line change
@@ -5,12 +5,12 @@ module Traversals
class BreadthFirst
include Algorithmable::Graphs::Traversals::Errors

def initialize(graph, source)
def initialize(graph, source, &f)
vertices_size = graph.vertices.size
@visited = Array.new(vertices_size - 1)
@edge_to = Array.new(vertices_size - 1)
@source = source
traverse graph, source
traverse graph, source, &f
end

def visited?(vertex)
@@ -22,10 +22,10 @@ def path_to(vertex)
path = []
finish = vertex
while finish != @source
path.push finish
path.unshift finish
finish = @edge_to[finish]
end
path.push @source
path.unshift @source
path
end

@@ -35,13 +35,15 @@ def traverse(graph, vertex)
queue = ::Queue.new
@visited[vertex] = true
queue.enq vertex
yield vertex if block_given?
until queue.empty?
next_vertex = queue.deq
graph.adjacency(next_vertex).each do |neighbour_vertex|
graph.adjacency_list(next_vertex).each do |neighbour_vertex|
next if visited? neighbour_vertex
@edge_to[neighbour_vertex] = next_vertex
@visited[neighbour_vertex] = true
queue.enq neighbour_vertex
yield neighbour_vertex if block_given?
end
end
end
15 changes: 8 additions & 7 deletions lib/algorithmable/graphs/traversals/depth_first.rb
Original file line number Diff line number Diff line change
@@ -4,11 +4,11 @@ module Traversals
class DepthFirst
include Algorithmable::Graphs::Traversals::Errors

def initialize(graph, source)
def initialize(graph, source, &f)
@visited = []
@edge_to = []
@source = source
traverse graph, source
traverse graph, source, &f
end

def visited?(vertex)
@@ -20,21 +20,22 @@ def path_to(vertex)
path = []
finish = vertex
while finish != @source
path.push finish
path.unshift finish
finish = @edge_to[finish]
end
path.push @source
path.unshift @source
path
end

private

def traverse(graph, vertex)
def traverse(graph, vertex, &f)
@visited[vertex] = true
graph.adjacency(vertex).each do |neighbour_vertex|
yield vertex if block_given?
graph.adjacency_list(vertex).each do |neighbour_vertex|
unless visited? neighbour_vertex
@edge_to[neighbour_vertex] = vertex
traverse graph, neighbour_vertex
traverse graph, neighbour_vertex, &f
end
end
end
31 changes: 31 additions & 0 deletions lib/algorithmable/graphs/traversals/topological_sort.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
module Algorithmable
module Graphs
module Traversals
class TopologicalSort
include Algorithmable::Graphs::Traversals::Errors

def self.sort(graph, &f)
stack = []
visited = []
graph.edges.each_index do |i|
next if visited[i]
do_sort(graph, i, stack, visited, &f)
end
stack
end

def self.do_sort(graph, vertex, stack, visited, &f)
visited[vertex] = true
graph.adjacency_list(vertex).each do |edge|
next if visited[edge.to]
do_sort graph, edge.to, stack, visited, &f
end
yield vertex if block_given?
stack.unshift vertex
end

private_class_method :do_sort
end
end
end
end
20 changes: 10 additions & 10 deletions lib/algorithmable/graphs/undirected.rb
Original file line number Diff line number Diff line change
@@ -6,20 +6,20 @@ class Undirected
def initialize(vertices = 0)
@vertices = vertices
@edges = 0
@adj = []
@vertices.times { |i| @adj[i] = [] }
@adjacency_list = []
@vertices.times { |i| @adjacency_list[i] = [] }
end

def add_edge(left_vertex, right_vertex)
@adj[left_vertex] ||= []
@adj[right_vertex] ||= []
@adj[left_vertex].push right_vertex
@adj[right_vertex].push left_vertex
@adjacency_list[left_vertex] ||= []
@adjacency_list[right_vertex] ||= []
@adjacency_list[left_vertex].push right_vertex
@adjacency_list[right_vertex].push left_vertex
@edges = @edges.next
end

def adjacency(vertex)
@adj[vertex]
def adjacency_list(vertex)
@adjacency_list[vertex]
end

def valid_vertex?(vertex)
@@ -28,14 +28,14 @@ def valid_vertex?(vertex)

def degree(vertex)
fail "Vertex #{vertex} is not valid." unless valid_vertex?(vertex)
adjacency(vertex).size
adjacency_list(vertex).size
end

def to_s
data = ''
@vertices.times do |vertex|
data += "( #{vertex} => "
@adj[vertex].each do |neighbor|
@adjacency_list[vertex].each do |neighbor|
data += "#{neighbor} "
end
data += ') '
5 changes: 0 additions & 5 deletions lib/algorithmable/searches.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
module Algorithmable
module Searches
autoload :BinarySearch, 'algorithmable/search/binary_search'
autoload :BinarySearchTree, 'algorithmable/search/binary_search_tree'

def binary_search(element, collection)
BinarySearch.lookup(element, collection)
end

def new_binary_search_tree(key_type, value_type)
BinarySearchTree.new key_type, value_type
end
end
end
4 changes: 3 additions & 1 deletion lib/algorithmable/sort/bubble.rb
Original file line number Diff line number Diff line change
@@ -6,12 +6,14 @@ class Bubble
# Time О(N^2), stable and slow
# Space О(N)
#
# Optimized implementation of Bubble sort
#
def self.sort(collection)
length = collection.length - 1
loop do
swapped = false
0.upto(length).each do |i|
if 1 == (collection[i] <=> collection[i + 1])
if 1 == (collection[i] <=> collection[i + 1]) #nil safe comparison
swap(collection, i)
swapped = true
end
Loading