algorithmable 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 40e70c3fb85f8914dade38055945669ecaf6f950
4
- data.tar.gz: 57c983790d111dd5169bdaae1a60070766773808
3
+ metadata.gz: 2ae7569f2df39cfefa86f0a46fafd1e1b91199d3
4
+ data.tar.gz: ebb4364c7e699846eef95bd47e09c26b8dc721f2
5
5
  SHA512:
6
- metadata.gz: 7312c04abd0f47c2ee93bcfd1cbeecb6d96b81f0f7de1ca7c39ed23ab6e7826271bade36144de05c71308db96347807576706283582aa8e97b085e5b19ebc6b8
7
- data.tar.gz: 33efeca966f560372813d7397474184cf1be1839e6f4d2a76f7b79bc50fd6e3e3ae993121afc1111f678b28c552c1827ed58ccd104b5c8508900ccc7107f460b
6
+ metadata.gz: 7cae4039f94a406279f630ece5f363e05f9dd9c406152e9b19fdcf8adedf427a9ad8c21a569ba14a44f0e909c1980249e7d907b25e592c8129db10135f9797b8
7
+ data.tar.gz: e2827ed66df194ee618724277b55c986c371dd8cd638632ccff264b3a81bb3853c1aa935cf7811ade5fa20aee47c65cbf2060d5a79c215d288f469fd322e4108
@@ -24,8 +24,6 @@ module Algorithmable
24
24
  @head.each(&block) if @head
25
25
  end
26
26
 
27
- private
28
-
29
27
  class Node
30
28
  attr_accessor :succ, :item
31
29
 
@@ -0,0 +1,112 @@
1
+ module Algorithmable
2
+ module DataStructs
3
+ class Deque
4
+ include Enumerable
5
+ include Algorithmable::Errors
6
+
7
+ Node = Struct.new(:prev, :next, :item)
8
+ attr_reader :size
9
+
10
+ def initialize(collection = [])
11
+ @front = nil
12
+ @back = nil
13
+ @size = 0
14
+ collection.each { |item| push_back(item) }
15
+ end
16
+
17
+ def empty?
18
+ 0 == size
19
+ end
20
+
21
+ def clear
22
+ @front = nil
23
+ @back = nil
24
+ @size = 0
25
+ end
26
+
27
+ def peek_front
28
+ @front && @front.item
29
+ end
30
+
31
+ def peek_back
32
+ @back && @back.item
33
+ end
34
+
35
+ def push_front(obj)
36
+ node = Node.new(nil, nil, obj)
37
+ if @front
38
+ node.next = @front
39
+ @front.prev = node
40
+ @front = node
41
+ else
42
+ @front = node
43
+ @back = @front
44
+ end
45
+ @size += 1
46
+ obj
47
+ end
48
+
49
+ def push_back(obj)
50
+ node = Node.new(nil, nil, obj)
51
+ if @back
52
+ node.prev = @back
53
+ @back.next = node
54
+ @back = node
55
+ else
56
+ @front = node
57
+ @back = @front
58
+ end
59
+ @size += 1
60
+ obj
61
+ end
62
+
63
+ def pop_front
64
+ fail NoSuchElementError unless @front
65
+ node = @front
66
+ if 1 == @size
67
+ clear
68
+ return node.item
69
+ else
70
+ @front.next.prev = nil
71
+ @front = @front.next
72
+ end
73
+ @size -= 1
74
+ node.item
75
+ end
76
+
77
+ def pop_back
78
+ fail NoSuchElementError unless @back
79
+ node = @back
80
+ if @size == 1
81
+ clear
82
+ return node.item
83
+ else
84
+ @back.prev.next = nil
85
+ @back = @back.prev
86
+ end
87
+ @size -= 1
88
+ node.item
89
+ end
90
+
91
+ # represent fifo iterator
92
+ def each
93
+ return unless @front
94
+ node = @front
95
+ while node
96
+ yield node.item
97
+ node = node.next
98
+ end
99
+ end
100
+
101
+ # represent lifo iterator
102
+ def reverse_each
103
+ return unless @back
104
+ node = @back
105
+ while node
106
+ yield node.item
107
+ node = node.prev
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
@@ -1,11 +1,99 @@
1
1
  module Algorithmable
2
2
  module DataStructs
3
- module LinkedList
4
- autoload :Node, 'algorithmable/data_structs/linked_list/node'
5
- autoload :Impl, 'algorithmable/data_structs/linked_list/impl'
3
+ class LinkedList
4
+ include Enumerable
5
+ attr_reader :length
6
6
 
7
- def self.new
8
- Impl.new
7
+ def initialize
8
+ @head = nil
9
+ @tail = nil
10
+ @length = 0
11
+ @op_counter = 0
12
+ end
13
+
14
+ def unshift(data)
15
+ link_head_node data
16
+ end
17
+
18
+ def push(data)
19
+ link_tail_node data
20
+ end
21
+
22
+ def first
23
+ @head ? @head.dup : fail_index_error
24
+ end
25
+
26
+ def last
27
+ @tail ? @tail.dup : fail_index_error
28
+ end
29
+
30
+ def each(&block)
31
+ next_node = @head
32
+ nodes = []
33
+ while next_node
34
+ nodes << next_node
35
+ next_node = next_node.succ
36
+ end
37
+ nodes.each(&block)
38
+ end
39
+
40
+ private
41
+
42
+ def link_head_node(data)
43
+ prev_head = @head
44
+ node = make_node data, nil, prev_head
45
+ @head = node
46
+
47
+ if prev_head
48
+ prev_head.pred = node
49
+ else
50
+ @tail = node
51
+ end
52
+
53
+ bump_length!
54
+ bump_op_counter!
55
+ end
56
+
57
+ def link_tail_node(data)
58
+ prev_tail = @tail
59
+ node = make_node data, prev_tail, nil
60
+ @tail = node
61
+
62
+ if prev_tail
63
+ prev_tail.succ = node
64
+ else
65
+ @head = node
66
+ end
67
+
68
+ bump_length!
69
+ bump_op_counter!
70
+ end
71
+
72
+ def make_node(data, pred = nil, succ = nil)
73
+ Node.new data, pred, succ
74
+ end
75
+
76
+ def bump_length!
77
+ @length = @length.next
78
+ end
79
+
80
+ def bump_op_counter!
81
+ @op_counter = @op_counter.next
82
+ end
83
+
84
+ def fail_index_error(message = nil)
85
+ fail IndexError, message
86
+ end
87
+
88
+ class Node
89
+ attr_accessor :pred, :succ
90
+ attr_reader :data
91
+
92
+ def initialize(data, pred = nil, succ = nil)
93
+ @data = data
94
+ @pred = pred
95
+ @succ = succ
96
+ end
9
97
  end
10
98
  end
11
99
  end
@@ -1,84 +1,28 @@
1
- require 'monitor'
2
-
3
1
  module Algorithmable
4
2
  module DataStructs
5
3
  class Queue
4
+ include Algorithmable::Errors
6
5
  include Enumerable
7
- include MonitorMixin
8
- attr_reader :size
9
-
10
- SEPARATOR = ':'
6
+ extend Forwardable
11
7
 
12
- NoSuchElementError = Class.new(RuntimeError)
13
-
14
- def initialize
15
- @first = nil
16
- @last = nil
17
- @size = 0
18
- super
19
- end
8
+ def_delegators :@imp, :empty?, :size, :each
20
9
 
21
- def empty?
22
- !@size.nonzero?
10
+ def initialize(collection = [])
11
+ @imp = Deque.new collection
23
12
  end
24
13
 
25
14
  def peek
26
- synchronize do
27
- fail NoSuchElementError if empty?
28
- @first.item
29
- end
15
+ peek_value = @imp.peek_front
16
+ fail NoSuchElementError unless peek_value
17
+ peek_value
30
18
  end
31
19
 
32
20
  def enqueue(item)
33
- synchronize do
34
- old_last = @last
35
- @last = Node.new item
36
- @last.succ = nil
37
- @first = @last if empty?
38
- old_last.succ = @last unless empty?
39
- @size = @size.next
40
- end
21
+ @imp.push_back(item)
41
22
  end
42
23
 
43
24
  def dequeue
44
- synchronize do
45
- fail NoSuchElementError if empty?
46
- item = @first.item
47
- @first = @first.succ
48
- @size = @size.pred
49
- @last = nil if empty?
50
- item
51
- end
52
- end
53
-
54
- def to_s
55
- synchronize do
56
- to_a.join SEPARATOR
57
- end
58
- end
59
-
60
- def each(&block)
61
- synchronize do
62
- (@first || []).each(&block)
63
- end
64
- end
65
-
66
- class Node
67
- attr_accessor :succ, :item
68
-
69
- def initialize(item)
70
- @item = item
71
- @succ = nil
72
- end
73
-
74
- def to_s
75
- @item.to_s
76
- end
77
-
78
- def each(&block)
79
- yield self
80
- @succ.each(&block) if @succ
81
- end
25
+ @imp.pop_front
82
26
  end
83
27
  end
84
28
  end
@@ -0,0 +1,30 @@
1
+ module Algorithmable
2
+ module DataStructs
3
+ class Stack
4
+ include Algorithmable::Errors
5
+ include Enumerable
6
+ extend Forwardable
7
+
8
+ def_delegators :@imp, :empty?, :size, :each
9
+
10
+ def initialize(collection = [])
11
+ @imp = Deque.new
12
+ collection.each { |item| @imp.push_front item }
13
+ end
14
+
15
+ def peek
16
+ peek_value = @imp.peek_front
17
+ fail NoSuchElementError unless peek_value
18
+ peek_value
19
+ end
20
+
21
+ def push(item)
22
+ @imp.push_front(item)
23
+ end
24
+
25
+ def pop
26
+ @imp.pop_front
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,13 +1,25 @@
1
1
  module Algorithmable
2
2
  module DataStructs
3
+ autoload :Deque, 'algorithmable/data_structs/deque'
3
4
  autoload :Bag, 'algorithmable/data_structs/bag'
4
5
  autoload :LinkedList, 'algorithmable/data_structs/linked_list'
5
6
  autoload :Queue, 'algorithmable/data_structs/queue'
7
+ autoload :Stack, 'algorithmable/data_structs/stack'
6
8
 
7
- class << self
8
- def new_bag
9
- Bag.new
10
- end
9
+ def new_bag
10
+ Bag.new
11
+ end
12
+
13
+ def new_linked_list
14
+ LinkedList.new
15
+ end
16
+
17
+ def new_fifo_queue
18
+ Queue.new
19
+ end
20
+
21
+ def new_lifo_queue
22
+ Stack.new
11
23
  end
12
24
  end
13
25
  end
@@ -0,0 +1,5 @@
1
+ module Algorithmable
2
+ module Errors
3
+ NoSuchElementError = Class.new(RuntimeError)
4
+ end
5
+ end
@@ -38,11 +38,10 @@ module Algorithmable
38
38
  until queue.empty?
39
39
  next_vertex = queue.deq
40
40
  graph.adjacency(next_vertex).each do |neighbour_vertex|
41
- unless visited? neighbour_vertex
42
- @edge_to[neighbour_vertex] = next_vertex
43
- @visited[neighbour_vertex] = true
44
- queue.enq neighbour_vertex
45
- end
41
+ next if visited? neighbour_vertex
42
+ @edge_to[neighbour_vertex] = next_vertex
43
+ @visited[neighbour_vertex] = true
44
+ queue.enq neighbour_vertex
46
45
  end
47
46
  end
48
47
  end
@@ -27,7 +27,7 @@ module Algorithmable
27
27
  end
28
28
 
29
29
  def degree(vertex)
30
- raise "Vertex #{vertex} is not valid." unless valid_vertex?(vertex)
30
+ fail "Vertex #{vertex} is not valid." unless valid_vertex?(vertex)
31
31
  adjacency(vertex).size
32
32
  end
33
33
 
@@ -0,0 +1,50 @@
1
+ module Algorithmable
2
+ module Puzzles
3
+ class DijkstrasTwoStacks
4
+ include Algorithmable::DataStructs
5
+
6
+ MATH_OPS = %w(sqrt cos sin tan atan2 log log2 log10)
7
+ ARITHMETICAL_OPS = %w(+ - * /)
8
+ OPS = ARITHMETICAL_OPS + MATH_OPS
9
+ OPEN_EXP = '('
10
+ CLOSE_EXP = ')'
11
+
12
+ def initialize(expression)
13
+ @expression = expression
14
+ end
15
+
16
+ def solve
17
+ operations = new_lifo_queue
18
+ values = new_lifo_queue
19
+ parse_expression(operations, values)
20
+ values.pop
21
+ end
22
+
23
+ private
24
+
25
+ def parse_expression(operations, values)
26
+ @expression.split.each do |char|
27
+ if OPEN_EXP == char
28
+ # noop
29
+ elsif OPS.include?(char)
30
+ operations.push char
31
+ elsif CLOSE_EXP == char
32
+ operation = operations.pop
33
+ value = values.pop
34
+ compute operation, value, values
35
+ else
36
+ values.push Float(char)
37
+ end
38
+ end
39
+ end
40
+
41
+ def compute(operation, value, values_stack)
42
+ if MATH_OPS.include? operation
43
+ values_stack.push Math.send(operation, value)
44
+ else
45
+ values_stack.push values_stack.pop.send(operation, value)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,25 @@
1
+ module Algorithmable
2
+ module Puzzles
3
+ class JosephusProblem
4
+ include Algorithmable::DataStructs
5
+
6
+ def initialize(prisoners, every)
7
+ @prisoners = prisoners
8
+ @every = every
9
+ end
10
+
11
+ def solve
12
+ queue = new_fifo_queue
13
+ @prisoners.times { |item| queue.enqueue(item) }
14
+ positions = []
15
+ until queue.empty?
16
+ (@every - 1).times do
17
+ queue.enqueue queue.dequeue
18
+ end
19
+ positions << queue.dequeue
20
+ end
21
+ positions
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,10 @@
1
+ module Algorithmable
2
+ module Puzzles
3
+ autoload :JosephusProblem, 'algorithmable/puzzles/josephus_problem'
4
+ autoload :DijkstrasTwoStacks, 'algorithmable/puzzles/dijkstras_two_stacks'
5
+
6
+ def new_josephus_problem(prisoners, every)
7
+ JosephusProblem.new(prisoners, every)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,23 @@
1
+ module Algorithmable
2
+ module Sort
3
+ class BinaryHeap
4
+ def self.sort(collection)
5
+ new.sort(collection)
6
+ end
7
+
8
+ def sort(collection)
9
+ fail NotImplementedError, collection
10
+ end
11
+
12
+ private
13
+
14
+ def swim(node)
15
+ fail NotImplementedError, node
16
+ end
17
+
18
+ def sink(node)
19
+ fail NotImplementedError, node
20
+ end
21
+ end
22
+ end
23
+ end
@@ -2,6 +2,7 @@ module Algorithmable
2
2
  module Sort
3
3
  autoload :Merge, 'algorithmable/sort/merge'
4
4
  autoload :Bubble, 'algorithmable/sort/bubble'
5
+ autoload :BinaryHeap, 'algorithmable/sort/binary_heap'
5
6
 
6
7
  class << self
7
8
  def merge(collection)
@@ -1,3 +1,3 @@
1
1
  module Algorithmable
2
- VERSION = '0.6.0'
2
+ VERSION = '0.7.0'
3
3
  end
data/lib/algorithmable.rb CHANGED
@@ -5,9 +5,11 @@ require 'pathname'
5
5
  require 'English'
6
6
 
7
7
  module Algorithmable
8
+ autoload :Errors, 'algorithmable/errors'
8
9
  autoload :Sort, 'algorithmable/sort'
9
10
  autoload :DataStructs, 'algorithmable/data_structs'
10
11
  autoload :Graphs, 'algorithmable/graphs'
12
+ autoload :Puzzles, 'algorithmable/puzzles'
11
13
 
12
14
  class << self
13
15
  def logger
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: algorithmable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roman Lishtaba
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-01-02 00:00:00.000000000 Z
11
+ date: 2016-01-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -142,17 +142,22 @@ files:
142
142
  - lib/algorithmable.rb
143
143
  - lib/algorithmable/data_structs.rb
144
144
  - lib/algorithmable/data_structs/bag.rb
145
+ - lib/algorithmable/data_structs/deque.rb
145
146
  - lib/algorithmable/data_structs/linked_list.rb
146
- - lib/algorithmable/data_structs/linked_list/impl.rb
147
- - lib/algorithmable/data_structs/linked_list/node.rb
148
147
  - lib/algorithmable/data_structs/queue.rb
148
+ - lib/algorithmable/data_structs/stack.rb
149
+ - lib/algorithmable/errors.rb
149
150
  - lib/algorithmable/graphs.rb
150
151
  - lib/algorithmable/graphs/traversals.rb
151
152
  - lib/algorithmable/graphs/traversals/breadth_first.rb
152
153
  - lib/algorithmable/graphs/traversals/depth_first.rb
153
154
  - lib/algorithmable/graphs/traversals/errors.rb
154
155
  - lib/algorithmable/graphs/undirected.rb
156
+ - lib/algorithmable/puzzles.rb
157
+ - lib/algorithmable/puzzles/dijkstras_two_stacks.rb
158
+ - lib/algorithmable/puzzles/josephus_problem.rb
155
159
  - lib/algorithmable/sort.rb
160
+ - lib/algorithmable/sort/binary_heap.rb
156
161
  - lib/algorithmable/sort/bubble.rb
157
162
  - lib/algorithmable/sort/merge.rb
158
163
  - lib/algorithmable/version.rb
@@ -1,102 +0,0 @@
1
- module Algorithmable
2
- module DataStructs
3
- module LinkedList
4
- class Impl
5
- include Enumerable
6
- attr_reader :length
7
-
8
- def initialize
9
- @head = nil
10
- @tail = nil
11
- @length = 0
12
- @op_counter = 0
13
- end
14
-
15
- def unshift(data)
16
- link_head_node data
17
- end
18
-
19
- def push(data)
20
- link_tail_node data
21
- end
22
-
23
- def first
24
- @head ? @head.dup : fail_index_error
25
- end
26
-
27
- def last
28
- @tail ? @tail.dup : fail_index_error
29
- end
30
-
31
- def each(&block)
32
- next_node = @head
33
- nodes = []
34
- while next_node
35
- nodes << next_node
36
- next_node = next_node.succ
37
- end
38
- nodes.each(&block)
39
- end
40
-
41
- private
42
-
43
- def link_head_node(data)
44
- prev_head = @head
45
- node = make_node data, nil, prev_head
46
- @head = node
47
-
48
- if prev_head
49
- prev_head.pred = node
50
- else
51
- @tail = node
52
- end
53
-
54
- bump_length!
55
- bump_op_counter!
56
- end
57
-
58
- def link_tail_node(data)
59
- prev_tail = @tail
60
- node = make_node data, prev_tail, nil
61
- @tail = node
62
-
63
- if prev_tail
64
- prev_tail.succ = node
65
- else
66
- @head = node
67
- end
68
-
69
- bump_length!
70
- bump_op_counter!
71
- end
72
-
73
- def make_node(data, pred = nil, succ = nil)
74
- Node.new data, pred, succ
75
- end
76
-
77
- def bump_length!
78
- @length = @length.next
79
- end
80
-
81
- def bump_op_counter!
82
- @op_counter = @op_counter.next
83
- end
84
-
85
- def fail_index_error(message = nil)
86
- fail IndexError, message
87
- end
88
-
89
- class Node
90
- attr_accessor :pred, :succ
91
- attr_reader :data
92
-
93
- def initialize(data, pred = nil, succ = nil)
94
- @data = data
95
- @pred = pred
96
- @succ = succ
97
- end
98
- end
99
- end
100
- end
101
- end
102
- end
@@ -1,7 +0,0 @@
1
- module Algorithmable
2
- module DataStructs
3
- module LinkedList
4
-
5
- end
6
- end
7
- end