penguin_queue 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +25 -0
- data/LICENSE.txt +21 -0
- data/README.md +56 -0
- data/Rakefile +18 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/ext/penguin_queue/extconf.rb +3 -0
- data/ext/penguin_queue/penguin_queue.c +340 -0
- data/lib/penguin_queue/version.rb +3 -0
- data/lib/penguin_queue.rb +2 -0
- data/penguin_queue.gemspec +29 -0
- metadata +114 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f65e549283761f28cc27557bf240cec2af939de8
|
4
|
+
data.tar.gz: addaa9864d8e81e27b6e343c0a3369eca80c2676
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e9849295843bd1822f9fed629cb9ecef7bfbed28fae71397c8aad19f27088e08e9f02c80e1dec43d20ddeca9b1621e7ced1dc87e8188af6632dcef94d3babd3d
|
7
|
+
data.tar.gz: cedd93953d40ef6bab937840e2eeec5521b0fd0ed0cee2412a6748512441a4cb2460fb72c13706cf15cca588365af08a676f607a4e39bf6786d626b1a50bf1ee
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
penguin_queue (0.1.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
minitest (5.10.1)
|
10
|
+
rake (10.5.0)
|
11
|
+
rake-compiler (1.0.3)
|
12
|
+
rake
|
13
|
+
|
14
|
+
PLATFORMS
|
15
|
+
ruby
|
16
|
+
|
17
|
+
DEPENDENCIES
|
18
|
+
bundler (~> 1.13)
|
19
|
+
minitest (~> 5.0)
|
20
|
+
penguin_queue!
|
21
|
+
rake (~> 10.0)
|
22
|
+
rake-compiler
|
23
|
+
|
24
|
+
BUNDLED WITH
|
25
|
+
1.13.7
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 tompng
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# Priority Queue
|
2
|
+
```ruby
|
3
|
+
10000.times { array << rand; array.delete(array.min) } #=> slow when array.size is large
|
4
|
+
10000.times { pq << rand; pq.deq } #=> fast even if pq.size is large
|
5
|
+
```
|
6
|
+
|
7
|
+
# Install
|
8
|
+
```ruby
|
9
|
+
# Gemfile
|
10
|
+
gem 'penguin_queue', git: 'https://github.com/tompng/penguin_queue'
|
11
|
+
```
|
12
|
+
|
13
|
+
# Usage
|
14
|
+
```ruby
|
15
|
+
require 'penguin_queue'
|
16
|
+
pq = PenguinQueue.new
|
17
|
+
10.times.to_a.shuffle.each { |i| pq << i }
|
18
|
+
10.times.map { pq.deq } #=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
19
|
+
|
20
|
+
# custom priority
|
21
|
+
pq.enq 'hello', priority: 0
|
22
|
+
pq.first #=> "hello"
|
23
|
+
pq.first_with_priority #=> ["hello", 0]
|
24
|
+
pq.deq_with_priority #=> ["hello", 0]
|
25
|
+
|
26
|
+
# update priority, remove node
|
27
|
+
nodes = 10.times.to_a.shuffle.map { |i| pq << i }
|
28
|
+
nodes.each { |n| n.priority = -n.priority }
|
29
|
+
nodes.each_with_index{ |n| n.remove if n.value.odd? }
|
30
|
+
pq.size.times.map { pq.deq } #=> [8, 6, 4, 2, 0]
|
31
|
+
```
|
32
|
+
|
33
|
+
# Methods
|
34
|
+
```ruby
|
35
|
+
# PenguinQueue
|
36
|
+
PenguinQueue.new PenguinQueue.new(&calc_priority_from_element_proc)
|
37
|
+
# enqueue multiple
|
38
|
+
push(e1, e2, ...) unshift(e1, e2, ...)
|
39
|
+
# enqueue
|
40
|
+
<<(e) enq(e)
|
41
|
+
# enqueue with custom priority
|
42
|
+
enq(e, priority: p)
|
43
|
+
# dequeue
|
44
|
+
deq shift pop deque_with_priority
|
45
|
+
# dequeue multiple
|
46
|
+
deq(n) shift(n) pop(n)
|
47
|
+
# fetch
|
48
|
+
first first_with_priority first_node
|
49
|
+
# remove
|
50
|
+
remove(node) delete(node)
|
51
|
+
# other
|
52
|
+
to_s inspect size empty?
|
53
|
+
|
54
|
+
# PenguinQueue::Node
|
55
|
+
remove delete value value= priority priority=
|
56
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rake/testtask"
|
3
|
+
|
4
|
+
Rake::TestTask.new(:test) do |t|
|
5
|
+
t.libs << "test"
|
6
|
+
t.libs << "lib"
|
7
|
+
t.test_files = FileList['test/**/*_test.rb']
|
8
|
+
end
|
9
|
+
|
10
|
+
require "rake/extensiontask"
|
11
|
+
|
12
|
+
task :build => :compile
|
13
|
+
|
14
|
+
Rake::ExtensionTask.new("penguin_queue") do |ext|
|
15
|
+
ext.lib_dir = "lib/penguin_queue"
|
16
|
+
end
|
17
|
+
|
18
|
+
task :default => [:clobber, :compile, :test]
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "penguin_queue"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
@@ -0,0 +1,340 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
|
3
|
+
static ID id_priority, id_cmp, id_call;
|
4
|
+
#define RB_STR_BUF_CAT(rstr, cstr) rb_str_buf_cat((rstr), (cstr), sizeof(cstr)-1);
|
5
|
+
struct node {
|
6
|
+
long index, id;
|
7
|
+
VALUE heap, priority, value;
|
8
|
+
};
|
9
|
+
VALUE node_class;
|
10
|
+
void node_mark(struct node *ptr){
|
11
|
+
rb_gc_mark(ptr->heap);
|
12
|
+
rb_gc_mark(ptr->priority);
|
13
|
+
rb_gc_mark(ptr->value);
|
14
|
+
}
|
15
|
+
VALUE node_alloc_internal(long index, long id, VALUE heap, VALUE priority, VALUE value){
|
16
|
+
struct node *ptr = ALLOC(struct node);
|
17
|
+
ptr->index = index;
|
18
|
+
ptr->id = id;
|
19
|
+
ptr->heap = heap;
|
20
|
+
ptr->priority = priority;
|
21
|
+
ptr->value = value;
|
22
|
+
return Data_Wrap_Struct(node_class, node_mark, -1, ptr);
|
23
|
+
}
|
24
|
+
#define NODE_PREPARE(self, name) struct node *name;Data_Get_Struct(self, struct node, name);
|
25
|
+
VALUE node_pri(VALUE self){
|
26
|
+
NODE_PREPARE(self, ptr);
|
27
|
+
return ptr->priority;
|
28
|
+
}
|
29
|
+
VALUE node_val(VALUE self){
|
30
|
+
NODE_PREPARE(self, ptr);
|
31
|
+
return ptr->value;
|
32
|
+
}
|
33
|
+
VALUE node_val_set(VALUE self, VALUE val){
|
34
|
+
NODE_PREPARE(self, ptr);
|
35
|
+
return ptr->value = val;
|
36
|
+
}
|
37
|
+
VALUE node_inspect(VALUE self){
|
38
|
+
NODE_PREPARE(self, nptr);
|
39
|
+
VALUE str = rb_str_buf_new(0);
|
40
|
+
rb_str_buf_append(str, rb_class_name(CLASS_OF(self)));
|
41
|
+
RB_STR_BUF_CAT(str, "{priority: ");
|
42
|
+
rb_str_buf_append(str, rb_inspect(nptr->priority));
|
43
|
+
RB_STR_BUF_CAT(str, ", value: ");
|
44
|
+
rb_str_buf_append(str, rb_inspect(nptr->value));
|
45
|
+
RB_STR_BUF_CAT(str, "}");
|
46
|
+
return str;
|
47
|
+
}
|
48
|
+
|
49
|
+
struct queue_data{
|
50
|
+
long counter;
|
51
|
+
VALUE heap, compare_by;
|
52
|
+
};
|
53
|
+
|
54
|
+
long compare(VALUE a, VALUE b){
|
55
|
+
if(RB_FIXNUM_P(a)&&RB_FIXNUM_P(b))
|
56
|
+
return (long)a > (long)b ? 1 : (long)a < (long)b ? -1 : 0;
|
57
|
+
if(RB_FLOAT_TYPE_P(a)&&RB_FLOAT_TYPE_P(b)){
|
58
|
+
double fa=RFLOAT_VALUE(a),fb=RFLOAT_VALUE(b);
|
59
|
+
return fa>fb?1:fa<fb?-1:0;
|
60
|
+
}
|
61
|
+
if(RB_TYPE_P(a, T_STRING)&&RB_TYPE_P(b, T_STRING))
|
62
|
+
return rb_str_cmp(a, b);
|
63
|
+
return rb_fix2long(rb_funcall(a, id_cmp, 1, b));
|
64
|
+
}
|
65
|
+
long compare_id(long a, long b){return a>b?1:a<b?-1:0;}
|
66
|
+
void heap_mark(struct queue_data *st){
|
67
|
+
rb_gc_mark(st->heap);
|
68
|
+
rb_gc_mark(st->compare_by);
|
69
|
+
}
|
70
|
+
void heap_free(struct queue_data *st){free(st);}
|
71
|
+
VALUE heap_alloc(VALUE klass){
|
72
|
+
struct queue_data *ptr=ALLOC(struct queue_data);
|
73
|
+
ptr->counter = 0;
|
74
|
+
ptr->heap = rb_ary_new_capa(1);
|
75
|
+
rb_ary_push(ptr->heap, Qnil);
|
76
|
+
if(rb_block_given_p()){
|
77
|
+
ptr->compare_by = rb_block_proc();
|
78
|
+
}else{
|
79
|
+
ptr->compare_by = Qnil;
|
80
|
+
}
|
81
|
+
return Data_Wrap_Struct(klass, heap_mark, heap_free, ptr);
|
82
|
+
}
|
83
|
+
|
84
|
+
#define QUEUE_PREPARE(self, name) struct queue_data *name;Data_Get_Struct(self, struct queue_data, name);
|
85
|
+
|
86
|
+
void heap_up(VALUE self, VALUE node){
|
87
|
+
QUEUE_PREPARE(self, ptr);
|
88
|
+
RARRAY_PTR_USE(ptr->heap, heap, {
|
89
|
+
NODE_PREPARE(node, nptr);
|
90
|
+
long index = nptr->index;
|
91
|
+
while(index > 1){
|
92
|
+
long pindex = index/2;
|
93
|
+
VALUE pnode = heap[pindex];
|
94
|
+
NODE_PREPARE(pnode, pptr);
|
95
|
+
long cmp = compare(pptr->priority, nptr->priority);
|
96
|
+
if(!cmp)cmp=compare_id(pptr->id, nptr->id);
|
97
|
+
if(cmp<0)break;
|
98
|
+
pptr->index = index;
|
99
|
+
heap[index] = pnode;
|
100
|
+
index = pindex;
|
101
|
+
}
|
102
|
+
nptr->index = index;
|
103
|
+
heap[index] = node;
|
104
|
+
});
|
105
|
+
}
|
106
|
+
|
107
|
+
void heap_down(VALUE self, VALUE node){
|
108
|
+
QUEUE_PREPARE(self, ptr);
|
109
|
+
long length = RARRAY_LEN(ptr->heap);
|
110
|
+
RARRAY_PTR_USE(ptr->heap, heap, {
|
111
|
+
NODE_PREPARE(node, nptr);
|
112
|
+
long index = nptr->index;
|
113
|
+
while(2*index < length){
|
114
|
+
long lindex = 2*index;
|
115
|
+
VALUE lnode = heap[lindex];
|
116
|
+
NODE_PREPARE(lnode, lptr);
|
117
|
+
if(lindex+1 < length){
|
118
|
+
VALUE rnode = heap[lindex+1];
|
119
|
+
NODE_PREPARE(rnode, rptr);
|
120
|
+
long cmp = compare(lptr->priority, rptr->priority);
|
121
|
+
if(!cmp)cmp=compare_id(lptr->id, rptr->id);
|
122
|
+
if(cmp >= 0){
|
123
|
+
lindex += 1;
|
124
|
+
lnode = rnode;
|
125
|
+
lptr = rptr;
|
126
|
+
}
|
127
|
+
}
|
128
|
+
long cmp = compare(nptr->priority, lptr->priority);
|
129
|
+
if(!cmp)cmp=compare_id(nptr->id, lptr->id);
|
130
|
+
if(cmp <= 0)break;
|
131
|
+
lptr->index = index;
|
132
|
+
heap[index] = lnode;
|
133
|
+
index = lindex;
|
134
|
+
}
|
135
|
+
nptr->index = index;
|
136
|
+
heap[index] = node;
|
137
|
+
});
|
138
|
+
}
|
139
|
+
|
140
|
+
VALUE heap_remove_node(VALUE self, VALUE node){
|
141
|
+
if(!rb_obj_is_kind_of(node, node_class))return Qnil;
|
142
|
+
QUEUE_PREPARE(self, ptr);
|
143
|
+
NODE_PREPARE(node, nptr);
|
144
|
+
long length = RARRAY_LEN(ptr->heap);
|
145
|
+
if(nptr->index >= length || RARRAY_AREF(ptr->heap, nptr->index) != node)return Qnil;
|
146
|
+
RARRAY_PTR_USE(ptr->heap, heap, {
|
147
|
+
VALUE replace_node = rb_ary_pop(ptr->heap);
|
148
|
+
if(replace_node == node)return Qnil;
|
149
|
+
NODE_PREPARE(replace_node, rptr);
|
150
|
+
heap[nptr->index] = replace_node;
|
151
|
+
rptr->index = nptr->index;
|
152
|
+
long cmp = compare(rptr->priority, nptr->priority);
|
153
|
+
if(!cmp)cmp = compare_id(rptr->id, nptr->id);
|
154
|
+
if(cmp > 0){
|
155
|
+
heap_down(nptr->heap, replace_node);
|
156
|
+
}else{
|
157
|
+
heap_up(nptr->heap, replace_node);
|
158
|
+
}
|
159
|
+
});
|
160
|
+
return Qnil;
|
161
|
+
}
|
162
|
+
|
163
|
+
VALUE node_remove(VALUE self){
|
164
|
+
NODE_PREPARE(self, nptr);
|
165
|
+
heap_remove_node(nptr->heap, self);
|
166
|
+
return Qnil;
|
167
|
+
}
|
168
|
+
|
169
|
+
VALUE node_update_priority(VALUE node, VALUE priority){
|
170
|
+
NODE_PREPARE(node, nptr);
|
171
|
+
QUEUE_PREPARE(nptr->heap, ptr);
|
172
|
+
VALUE priority_was = nptr->priority;
|
173
|
+
nptr->priority = priority;
|
174
|
+
long cmp = compare(priority, priority_was);
|
175
|
+
if(cmp == 0)return Qnil;
|
176
|
+
RARRAY_PTR_USE(ptr->heap, heap, {
|
177
|
+
if(heap[nptr->index] != node)return Qnil;
|
178
|
+
});
|
179
|
+
if(cmp < 0){
|
180
|
+
heap_up(nptr->heap, node);
|
181
|
+
}else{
|
182
|
+
heap_down(nptr->heap, node);
|
183
|
+
}
|
184
|
+
return Qnil;
|
185
|
+
}
|
186
|
+
|
187
|
+
VALUE heap_enq_vp(VALUE self, VALUE value, VALUE priority){
|
188
|
+
QUEUE_PREPARE(self, ptr);
|
189
|
+
if(ptr->compare_by != Qnil){
|
190
|
+
priority = rb_funcall(ptr->compare_by, id_call, 1, value);
|
191
|
+
}
|
192
|
+
long length = RARRAY_LEN(ptr->heap);
|
193
|
+
VALUE node = node_alloc_internal(length, ptr->counter, self, priority, value);
|
194
|
+
ptr->counter++;
|
195
|
+
rb_ary_push(ptr->heap, node);
|
196
|
+
heap_up(self, node);
|
197
|
+
return node;
|
198
|
+
}
|
199
|
+
|
200
|
+
#define OPTHASH_GIVEN_P(opts) \
|
201
|
+
(argc > 0 && !NIL_P((opts) = rb_check_hash_type(argv[argc-1])) && (--argc, 1))
|
202
|
+
|
203
|
+
VALUE heap_enq(int argc, VALUE *argv, VALUE self){
|
204
|
+
VALUE value, opts, priority, pri = Qundef;
|
205
|
+
if (OPTHASH_GIVEN_P(opts)) {
|
206
|
+
ID keyword_ids[] = {id_priority};
|
207
|
+
rb_get_kwargs(opts, keyword_ids, 0, 1, &pri);
|
208
|
+
}
|
209
|
+
rb_scan_args(argc, argv, "1", &value);
|
210
|
+
priority = (pri == Qundef) ? value : pri;
|
211
|
+
return heap_enq_vp(self, value, priority);
|
212
|
+
}
|
213
|
+
VALUE heap_push(VALUE self, VALUE value){
|
214
|
+
return heap_enq_vp(self, value, value);
|
215
|
+
}
|
216
|
+
VALUE heap_push_multiple(int argc, VALUE *argv, VALUE self){
|
217
|
+
VALUE nodes = rb_ary_new_capa(argc);
|
218
|
+
for(int i=0;i<argc;i++)rb_ary_push(nodes, heap_push(self, argv[i]));
|
219
|
+
return nodes;
|
220
|
+
}
|
221
|
+
|
222
|
+
VALUE heap_first_node(VALUE self){
|
223
|
+
QUEUE_PREPARE(self, ptr);
|
224
|
+
long length = RARRAY_LEN(ptr->heap);
|
225
|
+
if(length == 1)return Qnil;
|
226
|
+
RARRAY_PTR_USE(ptr->heap, heap, {
|
227
|
+
return heap[1];
|
228
|
+
});
|
229
|
+
}
|
230
|
+
VALUE heap_first(VALUE self){
|
231
|
+
VALUE node = heap_first_node(self);
|
232
|
+
if(node == Qnil)return Qnil;
|
233
|
+
NODE_PREPARE(node, nptr);
|
234
|
+
return nptr->value;
|
235
|
+
}
|
236
|
+
VALUE heap_first_with_priority(VALUE self){
|
237
|
+
VALUE node = heap_first_node(self);
|
238
|
+
if(node == Qnil)return Qnil;
|
239
|
+
NODE_PREPARE(node, nptr);
|
240
|
+
return rb_ary_new_from_args(2, nptr->value, nptr->priority);
|
241
|
+
}
|
242
|
+
|
243
|
+
VALUE heap_deq_node(VALUE self){
|
244
|
+
QUEUE_PREPARE(self, ptr);
|
245
|
+
long length = RARRAY_LEN(ptr->heap);
|
246
|
+
if(length == 1)return Qnil;
|
247
|
+
RARRAY_PTR_USE(ptr->heap, heap, {
|
248
|
+
VALUE first = heap[1];
|
249
|
+
VALUE node = rb_ary_pop(ptr->heap);
|
250
|
+
NODE_PREPARE(node, nptr);
|
251
|
+
if(length > 1){
|
252
|
+
nptr->index = 1;
|
253
|
+
heap_down(self, node);
|
254
|
+
}
|
255
|
+
return first;
|
256
|
+
});
|
257
|
+
}
|
258
|
+
VALUE heap_deq(int argc, VALUE *argv, VALUE self){
|
259
|
+
if(argc == 0){
|
260
|
+
VALUE node = heap_deq_node(self);
|
261
|
+
if(node == Qnil)return Qnil;
|
262
|
+
NODE_PREPARE(node, nptr);
|
263
|
+
return nptr->value;
|
264
|
+
}else{
|
265
|
+
VALUE nv;
|
266
|
+
rb_scan_args(argc, argv, "1", &nv);
|
267
|
+
long n = NUM2LONG(nv);
|
268
|
+
if(n<0)rb_raise(rb_eArgError, "negative array size");
|
269
|
+
QUEUE_PREPARE(self, ptr);
|
270
|
+
long length = RARRAY_LEN(ptr->heap)-1;
|
271
|
+
if(n>length)n=length;
|
272
|
+
VALUE result = rb_ary_new_capa(n);
|
273
|
+
for(int i=0;i<n;i++){
|
274
|
+
VALUE node = heap_deq_node(self);
|
275
|
+
NODE_PREPARE(node, nptr);
|
276
|
+
rb_ary_push(result, nptr->value);
|
277
|
+
}
|
278
|
+
return result;
|
279
|
+
}
|
280
|
+
}
|
281
|
+
VALUE heap_deq_with_priority(VALUE self){
|
282
|
+
VALUE node = heap_deq_node(self);
|
283
|
+
if(node == Qnil)return Qnil;
|
284
|
+
NODE_PREPARE(node, nptr);
|
285
|
+
return rb_ary_new_from_args(2, nptr->value, nptr->priority);
|
286
|
+
}
|
287
|
+
|
288
|
+
VALUE heap_size(VALUE self){
|
289
|
+
QUEUE_PREPARE(self, ptr);
|
290
|
+
return LONG2FIX(RARRAY_LEN(ptr->heap)-1);
|
291
|
+
}
|
292
|
+
VALUE heap_is_empty(VALUE self){
|
293
|
+
QUEUE_PREPARE(self, ptr);
|
294
|
+
return RARRAY_LEN(ptr->heap) == 1 ? Qtrue : Qfalse;
|
295
|
+
}
|
296
|
+
VALUE heap_inspect(VALUE self){
|
297
|
+
VALUE str = rb_str_buf_new(0);
|
298
|
+
rb_str_buf_append(str, rb_class_name(CLASS_OF(self)));
|
299
|
+
RB_STR_BUF_CAT(str, "{size: ");
|
300
|
+
rb_str_buf_append(str, rb_inspect(heap_size(self)));
|
301
|
+
RB_STR_BUF_CAT(str, "}");
|
302
|
+
return str;
|
303
|
+
}
|
304
|
+
|
305
|
+
void Init_penguin_queue(void){
|
306
|
+
id_priority = rb_intern("priority");
|
307
|
+
id_call = rb_intern("call");
|
308
|
+
id_cmp = rb_intern("<=>");
|
309
|
+
|
310
|
+
VALUE heap_class = rb_define_class("PenguinQueue", rb_cObject);
|
311
|
+
rb_define_alloc_func(heap_class, heap_alloc);
|
312
|
+
rb_define_method(heap_class, "size", heap_size, 0);
|
313
|
+
rb_define_method(heap_class, "empty?", heap_is_empty, 0);
|
314
|
+
rb_define_method(heap_class, "inspect", heap_inspect, 0);
|
315
|
+
rb_define_method(heap_class, "first", heap_first, 0);
|
316
|
+
rb_define_method(heap_class, "first_node", heap_first_node, 0);
|
317
|
+
rb_define_method(heap_class, "first_with_priority", heap_first_with_priority, 0);
|
318
|
+
rb_define_method(heap_class, "to_s", heap_inspect, 0);
|
319
|
+
rb_define_method(heap_class, "push", heap_push_multiple, -1);
|
320
|
+
rb_define_method(heap_class, "<<", heap_push, 1);
|
321
|
+
rb_define_method(heap_class, "enq", heap_enq, -1);
|
322
|
+
rb_define_method(heap_class, "unshift", heap_push_multiple, -1);
|
323
|
+
rb_define_method(heap_class, "pop", heap_deq, -1);
|
324
|
+
rb_define_method(heap_class, "shift", heap_deq, -1);
|
325
|
+
rb_define_method(heap_class, "deq", heap_deq, -1);
|
326
|
+
rb_define_method(heap_class, "deq_with_priority", heap_deq_with_priority, 0);
|
327
|
+
rb_define_method(heap_class, "delete", heap_remove_node, 1);
|
328
|
+
rb_define_method(heap_class, "remove", heap_remove_node, 1);
|
329
|
+
|
330
|
+
node_class = rb_define_class_under(heap_class, "Node", rb_cObject);
|
331
|
+
rb_undef_alloc_func(node_class);
|
332
|
+
rb_define_method(node_class, "priority", node_pri, 0);
|
333
|
+
rb_define_method(node_class, "priority=", node_update_priority, 1);
|
334
|
+
rb_define_method(node_class, "value", node_val, 0);
|
335
|
+
rb_define_method(node_class, "value=", node_val_set, 1);
|
336
|
+
rb_define_method(node_class, "inspect", node_inspect, 0);
|
337
|
+
rb_define_method(node_class, "to_s", node_inspect, 0);
|
338
|
+
rb_define_method(node_class, "remove", node_remove, 0);
|
339
|
+
rb_define_method(node_class, "delete", node_remove, 0);
|
340
|
+
}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'penguin_queue/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "penguin_queue"
|
8
|
+
spec.version = PenguinQueue::VERSION
|
9
|
+
spec.authors = ["tompng"]
|
10
|
+
spec.email = ["tomoyapenguin@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{C Ext Priority Queue}
|
13
|
+
spec.description = %q{C Ext Priority Queue (binary heap)}
|
14
|
+
spec.homepage = "https://github.com/tompng/penguin_queue"
|
15
|
+
spec.license = "MIT"
|
16
|
+
spec.extensions = %w[ext/penguin_queue/extconf.rb]
|
17
|
+
|
18
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
19
|
+
f.match(%r{^(test|spec|features)/})
|
20
|
+
end
|
21
|
+
spec.bindir = "exe"
|
22
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
23
|
+
spec.require_paths = ["lib"]
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.13"
|
26
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
27
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
28
|
+
spec.add_development_dependency "rake-compiler"
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: penguin_queue
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- tompng
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-02-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.13'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.13'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '5.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '5.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake-compiler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: C Ext Priority Queue (binary heap)
|
70
|
+
email:
|
71
|
+
- tomoyapenguin@gmail.com
|
72
|
+
executables: []
|
73
|
+
extensions:
|
74
|
+
- ext/penguin_queue/extconf.rb
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- ".gitignore"
|
78
|
+
- Gemfile
|
79
|
+
- Gemfile.lock
|
80
|
+
- LICENSE.txt
|
81
|
+
- README.md
|
82
|
+
- Rakefile
|
83
|
+
- bin/console
|
84
|
+
- bin/setup
|
85
|
+
- ext/penguin_queue/extconf.rb
|
86
|
+
- ext/penguin_queue/penguin_queue.c
|
87
|
+
- lib/penguin_queue.rb
|
88
|
+
- lib/penguin_queue/version.rb
|
89
|
+
- penguin_queue.gemspec
|
90
|
+
homepage: https://github.com/tompng/penguin_queue
|
91
|
+
licenses:
|
92
|
+
- MIT
|
93
|
+
metadata: {}
|
94
|
+
post_install_message:
|
95
|
+
rdoc_options: []
|
96
|
+
require_paths:
|
97
|
+
- lib
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
requirements: []
|
109
|
+
rubyforge_project:
|
110
|
+
rubygems_version: 2.6.8
|
111
|
+
signing_key:
|
112
|
+
specification_version: 4
|
113
|
+
summary: C Ext Priority Queue
|
114
|
+
test_files: []
|