algorithmable 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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