facets 2.6.0 → 2.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.
- data/HISTORY.rdoc +331 -35
- data/MANIFEST +685 -826
- data/{doc/guide/notes.rd → NOTES} +0 -0
- data/README.rdoc +73 -25
- data/Rakefile +245 -2
- data/TODO +5 -0
- data/demo/hook.rd +47 -0
- data/demo/scenario_require.rd +9 -0
- data/doc/README.more +24 -6
- data/doc/manual/about.rb +47 -0
- data/doc/manual/annotations.rdoc +60 -0
- data/doc/manual/associations.rdoc +55 -0
- data/doc/manual/blockups.rdoc +101 -0
- data/doc/manual/capsule.rdoc +34 -0
- data/doc/manual/command.rdoc +177 -0
- data/doc/manual/core.rdoc +37 -0
- data/doc/manual/faq.rdoc +32 -0
- data/doc/manual/typecast.html +112 -0
- data/lib/core/facets.rb +359 -11
- data/lib/core/facets/array/combination.rb +3 -3
- data/lib/core/facets/array/index.rb +4 -1
- data/lib/core/facets/array/permutation.rb +2 -2
- data/lib/core/facets/array/product.rb +1 -1
- data/lib/core/facets/binding/eval.rb +1 -1
- data/lib/core/facets/denumerable.rb +76 -0
- data/lib/core/facets/duplicable.rb +34 -0
- data/lib/core/facets/enumerable/count.rb +10 -4
- data/lib/core/facets/enumerable/defer.rb +77 -0
- data/lib/core/facets/enumerable/each_by.rb +1 -1
- data/lib/core/facets/enumerable/every.rb +35 -0
- data/lib/{more/facets/elementwise.rb → core/facets/enumerable/ewise.rb} +0 -0
- data/lib/core/facets/enumerable/filter.rb +25 -0
- data/lib/core/facets/enumerable/group_by.rb +1 -1
- data/lib/core/facets/enumerable/none.rb +3 -2
- data/lib/core/facets/enumerable/one.rb +3 -2
- data/lib/core/facets/enumerable/per.rb +61 -0
- data/lib/core/facets/exception/raised.rb +14 -0
- data/lib/core/facets/integer/odd.rb +5 -1
- data/lib/core/facets/kernel/__dir__.rb +13 -3
- data/lib/core/facets/kernel/__here__.rb +14 -0
- data/lib/core/facets/kernel/__method__.rb +9 -3
- data/lib/core/facets/kernel/ask.rb +1 -0
- data/lib/core/facets/kernel/equate.rb +13 -0
- data/lib/core/facets/kernel/extension.rb +9 -0
- data/lib/core/facets/kernel/identical.rb +4 -0
- data/lib/core/facets/kernel/instance_exec.rb +2 -1
- data/lib/core/facets/kernel/method.rb +49 -0
- data/lib/core/facets/kernel/object_send.rb +2 -2
- data/lib/core/facets/kernel/{state.rb → object_state.rb} +23 -12
- data/lib/core/facets/kernel/require_all.rb +6 -1
- data/lib/core/facets/kernel/require_local.rb +8 -1
- data/lib/core/facets/kernel/require_relative.rb +52 -0
- data/lib/core/facets/kernel/source_location.rb +13 -0
- data/lib/core/facets/kernel/tap.rb +13 -6
- data/lib/core/facets/module/attr_setter.rb +57 -0
- data/lib/core/facets/module/instance_method.rb +24 -0
- data/lib/core/facets/module/module_load.rb +60 -44
- data/lib/core/facets/module/module_require.rb +1 -0
- data/lib/core/facets/nilclass/to_f.rb +1 -1
- data/lib/core/facets/objectspace/op_fetch.rb +3 -0
- data/lib/core/facets/proc/curry.rb +4 -3
- data/lib/core/facets/string/bytes.rb +10 -4
- data/lib/core/facets/string/camelcase.rb +6 -5
- data/lib/core/facets/string/chars.rb +5 -1
- data/lib/core/facets/string/each_char.rb +1 -1
- data/lib/core/facets/string/each_word.rb +1 -1
- data/lib/core/facets/string/lines.rb +11 -4
- data/lib/core/facets/string/start_with.rb +9 -2
- data/lib/core/facets/string/unfold.rb +27 -0
- data/lib/core/facets/symbol/succ.rb +3 -3
- data/lib/core/facets/symbol/thrown.rb +20 -0
- data/lib/core/facets/symbol/to_proc.rb +3 -2
- data/lib/core/facets/time/to_time.rb +1 -1
- data/lib/core/facets/to_hash.rb +41 -100
- data/lib/core/facets/unboundmethod/name.rb +20 -23
- data/lib/more/facets/ansicode.rb +1 -10
- data/lib/more/facets/autoarray.rb +3 -31
- data/lib/more/facets/basicobject.rb +73 -0
- data/lib/more/facets/blankslate.rb +2 -66
- data/lib/{lore → more}/facets/cgi.rb +0 -0
- data/lib/more/facets/class_extend.rb +1 -0
- data/lib/{lore → more}/facets/continuation.rb +0 -0
- data/lib/{lore → more}/facets/date.rb +3 -3
- data/lib/more/facets/enumargs.rb +192 -0
- data/lib/more/facets/enumerablepass.rb +2 -216
- data/lib/more/facets/enumerator.rb +62 -0
- data/lib/more/facets/{equatable.rb → equitable.rb} +11 -11
- data/lib/more/facets/expirable.rb +13 -41
- data/lib/{lore → more}/facets/fileutils.rb +0 -0
- data/lib/{lore → more}/facets/fileutils/head.rb +0 -0
- data/lib/{lore → more}/facets/fileutils/safe_ln.rb +0 -0
- data/lib/{lore → more}/facets/fileutils/slice.rb +0 -0
- data/lib/{lore → more}/facets/fileutils/tail.rb +0 -0
- data/lib/{lore → more}/facets/fileutils/wc.rb +0 -0
- data/lib/{lore → more}/facets/fileutils/whereis.rb +0 -0
- data/lib/{lore → more}/facets/fileutils/which.rb +0 -0
- data/lib/{lore → more}/facets/getoptlong.rb +0 -0
- data/lib/more/facets/hook.rb +2 -29
- data/lib/more/facets/inheritor.rb +2 -2
- data/lib/more/facets/instance_eval.rb +50 -0
- data/lib/more/facets/instance_function.rb +78 -0
- data/lib/more/facets/main.rb +20 -15
- data/lib/more/facets/memoize.rb +1 -113
- data/lib/more/facets/module/attr.rb +83 -0
- data/lib/more/facets/module/attr_tester.rb +44 -0
- data/lib/more/facets/module/attr_toggler.rb +59 -0
- data/lib/more/facets/module/attr_validator.rb +34 -0
- data/lib/more/facets/{class_extension.rb → module/class_extend.rb} +21 -13
- data/lib/more/facets/once.rb +59 -0
- data/lib/more/facets/openmodule.rb +1 -0
- data/lib/more/facets/orderedhash.rb +1 -33
- data/lib/{lore → more}/facets/ostruct.rb +0 -0
- data/lib/more/facets/ostructable.rb +1 -4
- data/lib/more/facets/partial.rb +18 -16
- data/lib/{lore → more}/facets/pathname.rb +0 -0
- data/lib/more/facets/preinitialize.rb +157 -0
- data/lib/{lore → more}/facets/rbconfig.rb +0 -0
- data/lib/more/facets/recorder.rb +1 -2
- data/lib/{lore → more}/facets/set.rb +0 -0
- data/lib/{lore → more}/facets/shellwords.rb +0 -0
- data/lib/{lore → more}/facets/uri.rb +0 -0
- data/lib/{lore → more}/facets/yaml.rb +0 -0
- data/lib/{lore → more}/facets/zlib.rb +0 -0
- data/meta/loadpath +0 -1
- data/meta/sitemap +4 -0
- data/meta/version +1 -1
- data/test/core/enumerable/test_count.rb +1 -1
- data/test/{more/test_filter.rb → core/enumerable/test_defer.rb} +24 -22
- data/test/{more/test_elementor.rb → core/enumerable/test_every.rb} +2 -15
- data/test/core/enumerable/test_ewise.rb +23 -0
- data/test/core/enumerable/test_per.rb +18 -0
- data/test/core/enumerable/test_take.rb +13 -0
- data/test/core/kernel/test_deepcopy.rb +1 -1
- data/test/{more/test_1stclassmethod.rb → core/kernel/test_method.rb} +2 -7
- data/test/core/kernel/test_tap.rb +1 -1
- data/test/core/proc/test_curry.rb +11 -0
- data/test/core/string/test_bytes.rb +1 -1
- data/test/core/string/test_camelcase.rb +23 -6
- data/test/core/string/test_lines.rb +1 -1
- data/test/core/string/test_unfold.rb +14 -0
- data/test/{more → core}/test_blank.rb +0 -0
- data/test/{more → core}/test_boolean.rb +0 -0
- data/test/{more → core}/test_functor.rb +0 -0
- data/test/{lore → more}/test_basicobject.rb +0 -0
- data/test/more/{test_class_extension.rb → test_class_extend.rb} +6 -6
- data/test/{lore → more}/test_continuation.rb +0 -0
- data/test/{lore → more}/test_date.rb +0 -0
- data/test/more/{test_enumerablepass.rb → test_enumargs.rb} +2 -4
- data/test/more/{test_equatable.rb → test_equitable.rb} +2 -2
- data/test/more/{test_instantise.rb → test_instance_function.rb} +3 -2
- data/test/more/test_memoize.rb +1 -1
- data/test/{lore → more}/test_ostruct.rb +0 -0
- metadata +865 -1016
- data/RELEASE +0 -38
- data/doc/README.lore +0 -51
- data/doc/log/basic_stats/index.html +0 -39
- data/doc/log/changelog.html +0 -648
- data/doc/log/changelog.txt +0 -217
- data/doc/log/stats/index.html +0 -39
- data/doc/log/testlog.txt +0 -278
- data/doc/notes/CHANGES +0 -2529
- data/doc/rdoc/lore/classes/Array.html +0 -176
- data/doc/rdoc/lore/classes/CGI.html +0 -191
- data/doc/rdoc/lore/classes/Config.html +0 -135
- data/doc/rdoc/lore/classes/Continuation.html +0 -113
- data/doc/rdoc/lore/classes/Date.html +0 -631
- data/doc/rdoc/lore/classes/DateTime.html +0 -583
- data/doc/rdoc/lore/classes/Enumerable.html +0 -89
- data/doc/rdoc/lore/classes/Enumerable/Enumerator.html +0 -147
- data/doc/rdoc/lore/classes/File.html +0 -128
- data/doc/rdoc/lore/classes/FileUtils.html +0 -434
- data/doc/rdoc/lore/classes/GetoptLong.html +0 -118
- data/doc/rdoc/lore/classes/GetoptLong/DSL.html +0 -208
- data/doc/rdoc/lore/classes/Kernel.html +0 -135
- data/doc/rdoc/lore/classes/Logger.html +0 -229
- data/doc/rdoc/lore/classes/Logger/Ansicolor.html +0 -277
- data/doc/rdoc/lore/classes/Logger/LogDevice.html +0 -121
- data/doc/rdoc/lore/classes/NilClass.html +0 -119
- data/doc/rdoc/lore/classes/OpenStruct.html +0 -432
- data/doc/rdoc/lore/classes/Pathname.html +0 -353
- data/doc/rdoc/lore/classes/Set.html +0 -117
- data/doc/rdoc/lore/classes/Shellwords.html +0 -111
- data/doc/rdoc/lore/classes/String.html +0 -140
- data/doc/rdoc/lore/classes/Time.html +0 -154
- data/doc/rdoc/lore/classes/URI.html +0 -454
- data/doc/rdoc/lore/classes/URI/Hash.html +0 -105
- data/doc/rdoc/lore/classes/URI/Kernel.html +0 -122
- data/doc/rdoc/lore/classes/Zlib.html +0 -188
- data/doc/rdoc/lore/created.rid +0 -1
- data/doc/rdoc/lore/files/README.html +0 -286
- data/doc/rdoc/lore/files/doc/README_lore.html +0 -155
- data/doc/rdoc/lore/files/lib/lore/facets/basicobject_rb.html +0 -118
- data/doc/rdoc/lore/files/lib/lore/facets/cgi_rb.html +0 -111
- data/doc/rdoc/lore/files/lib/lore/facets/continuation_rb.html +0 -147
- data/doc/rdoc/lore/files/lib/lore/facets/date_rb.html +0 -97
- data/doc/rdoc/lore/files/lib/lore/facets/enumerator_rb.html +0 -111
- data/doc/rdoc/lore/files/lib/lore/facets/fileutils/head_rb.html +0 -96
- data/doc/rdoc/lore/files/lib/lore/facets/fileutils/safe_ln_rb.html +0 -96
- data/doc/rdoc/lore/files/lib/lore/facets/fileutils/slice_rb.html +0 -96
- data/doc/rdoc/lore/files/lib/lore/facets/fileutils/tail_rb.html +0 -96
- data/doc/rdoc/lore/files/lib/lore/facets/fileutils/wc_rb.html +0 -96
- data/doc/rdoc/lore/files/lib/lore/facets/fileutils/whereis_rb.html +0 -96
- data/doc/rdoc/lore/files/lib/lore/facets/fileutils/which_rb.html +0 -96
- data/doc/rdoc/lore/files/lib/lore/facets/fileutils_rb.html +0 -131
- data/doc/rdoc/lore/files/lib/lore/facets/getoptlong_rb.html +0 -135
- data/doc/rdoc/lore/files/lib/lore/facets/logger_rb.html +0 -142
- data/doc/rdoc/lore/files/lib/lore/facets/ostruct_rb.html +0 -135
- data/doc/rdoc/lore/files/lib/lore/facets/pathname_rb.html +0 -145
- data/doc/rdoc/lore/files/lib/lore/facets/rbconfig_rb.html +0 -124
- data/doc/rdoc/lore/files/lib/lore/facets/set_rb.html +0 -96
- data/doc/rdoc/lore/files/lib/lore/facets/shellwords_rb.html +0 -124
- data/doc/rdoc/lore/files/lib/lore/facets/uri_rb.html +0 -125
- data/doc/rdoc/lore/files/lib/lore/facets/yaml_rb.html +0 -146
- data/doc/rdoc/lore/files/lib/lore/facets/zlib_rb.html +0 -97
- data/doc/rdoc/lore/fr_class_index.html +0 -73
- data/doc/rdoc/lore/fr_file_index.html +0 -71
- data/doc/rdoc/lore/fr_method_index.html +0 -177
- data/doc/rdoc/lore/index.html +0 -26
- data/doc/rdoc/lore/rdoc-style.css +0 -177
- data/doc/release-notes/RELEASE-2.0.5 +0 -8
- data/doc/release-notes/RELEASE-2.1.0 +0 -9
- data/doc/release-notes/RELEASE-2.1.1 +0 -5
- data/doc/release-notes/RELEASE-2.1.2 +0 -6
- data/doc/release-notes/RELEASE-2.1.3 +0 -5
- data/doc/release-notes/RELEASE-2.2.0 +0 -14
- data/doc/release-notes/RELEASE-2.2.1 +0 -4
- data/doc/release-notes/RELEASE-2.3.0 +0 -6
- data/doc/release-notes/RELEASE-2.4.0 +0 -70
- data/doc/release-notes/RELEASE-2.4.1 +0 -8
- data/doc/release-notes/RELEASE-2.4.2 +0 -4
- data/doc/release-notes/RELEASE-2.4.3 +0 -78
- data/doc/release-notes/RELEASE-2.4.4 +0 -38
- data/doc/release-notes/RELEASE-2.4.5 +0 -37
- data/doc/release-notes/RELEASE-2.5.0 +0 -83
- data/lib/core/facets/kernel/instance.rb +0 -19
- data/lib/lore/facets/basicobject.rb +0 -14
- data/lib/lore/facets/enumerator.rb +0 -67
- data/lib/lore/facets/logger.rb +0 -291
- data/lib/more/facets/1stclassmethod.rb +0 -140
- data/lib/more/facets/advisable.rb +0 -162
- data/lib/more/facets/association.rb +0 -210
- data/lib/more/facets/attr.rb +0 -209
- data/lib/more/facets/basex.rb +0 -37
- data/lib/more/facets/bbcode.rb +0 -397
- data/lib/more/facets/bicrypt.rb +0 -265
- data/lib/more/facets/binreadable.rb +0 -221
- data/lib/more/facets/censor.rb +0 -97
- data/lib/more/facets/classmethods.rb +0 -199
- data/lib/more/facets/consoleutils.rb +0 -99
- data/lib/more/facets/crypt.rb +0 -166
- data/lib/more/facets/dependency.rb +0 -151
- data/lib/more/facets/downloader.rb +0 -281
- data/lib/more/facets/duplicable.rb +0 -43
- data/lib/more/facets/elementor.rb +0 -133
- data/lib/more/facets/filter.rb +0 -121
- data/lib/more/facets/heap.rb +0 -22
- data/lib/more/facets/infinity.rb +0 -193
- data/lib/more/facets/ini.rb +0 -264
- data/lib/more/facets/instantise.rb +0 -1
- data/lib/more/facets/instantize.rb +0 -95
- data/lib/more/facets/interval.rb +0 -282
- data/lib/more/facets/iteration.rb +0 -65
- data/lib/more/facets/linkedlist.rb +0 -222
- data/lib/more/facets/lrucache.rb +0 -157
- data/lib/more/facets/matcher.rb +0 -140
- data/lib/more/facets/memoizer.rb +0 -74
- data/lib/more/facets/minitar.rb +0 -1063
- data/lib/more/facets/nackclass.rb +0 -41
- data/lib/more/facets/net/smtp_tls.rb +0 -131
- data/lib/more/facets/nilstatus.rb +0 -48
- data/lib/more/facets/overload.rb +0 -94
- data/lib/more/facets/paramix.rb +0 -202
- data/lib/more/facets/pool.rb +0 -91
- data/lib/more/facets/pqueue.rb +0 -449
- data/lib/more/facets/pry.rb +0 -32
- data/lib/more/facets/reflection.rb +0 -145
- data/lib/more/facets/semaphore.rb +0 -92
- data/lib/more/facets/settings.rb +0 -248
- data/lib/more/facets/snapshot.rb +0 -209
- data/lib/more/facets/sparse_array.rb +0 -809
- data/lib/more/facets/string/mask.rb +0 -278
- data/lib/more/facets/string/obfuscate.rb +0 -65
- data/lib/more/facets/string/stylize.rb +0 -169
- data/lib/more/facets/string/words.rb +0 -167
- data/lib/more/facets/syncarray.rb +0 -114
- data/lib/more/facets/synchash.rb +0 -157
- data/lib/more/facets/typecast.rb +0 -261
- data/lib/more/facets/uninheritable.rb +0 -50
- data/lib/more/facets/xmlhash.rb +0 -112
- data/lib/more/facets/xoxo.rb +0 -259
- data/lib/more/facets/ziputils.rb +0 -490
- data/task/conflicts +0 -63
- data/task/coverage.rake +0 -37
- data/task/methods +0 -49
- data/task/rdoc.rake +0 -17
- data/task/setup.rake +0 -38
- data/task/test.rake +0 -145
- data/test/more/test_advisable.rb +0 -71
- data/test/more/test_association.rb +0 -38
- data/test/more/test_bbcode.rb +0 -21
- data/test/more/test_binreadable.rb +0 -50
- data/test/more/test_buildable.rb +0 -73
- data/test/more/test_classmethods.rb +0 -56
- data/test/more/test_crypt.rb +0 -32
- data/test/more/test_dependency.rb +0 -69
- data/test/more/test_elementwise.rb +0 -25
- data/test/more/test_infinity.rb +0 -40
- data/test/more/test_interval.rb +0 -151
- data/test/more/test_linkedlist.rb +0 -41
- data/test/more/test_lrucache.rb +0 -14
- data/test/more/test_overload.rb +0 -160
- data/test/more/test_paramix.rb +0 -170
- data/test/more/test_prototype.rb +0 -35
- data/test/more/test_snapshot.rb +0 -21
- data/test/more/test_sparsearray.rb +0 -279
- data/test/more/test_syncarray.rb +0 -15
- data/test/more/test_synchash.rb +0 -16
- data/test/more/test_typecast.rb +0 -54
- data/test/more/test_uninheritable.rb +0 -31
- data/test/more/test_xoxo.rb +0 -274
- data/test/test_facets.rb +0 -9
data/lib/more/facets/pool.rb
DELETED
@@ -1,91 +0,0 @@
|
|
1
|
-
# = Pool
|
2
|
-
#
|
3
|
-
# Generalized object pool implementation. Implemented as a thread
|
4
|
-
# safe stack. Exclusive locking is needed both for push and pop.
|
5
|
-
#
|
6
|
-
# == Author
|
7
|
-
#
|
8
|
-
# * George Moschovitis
|
9
|
-
#
|
10
|
-
# == Todo
|
11
|
-
#
|
12
|
-
# * Could use the SizedQueue/Queue?
|
13
|
-
#
|
14
|
-
# == Copying
|
15
|
-
#
|
16
|
-
# Copyright (c) 2004 George Moschovitis
|
17
|
-
#
|
18
|
-
# Ruby License
|
19
|
-
#
|
20
|
-
# This module is free software. You may use, modify, and/or redistribute this
|
21
|
-
# software under the same terms as Ruby.
|
22
|
-
#
|
23
|
-
# This program is distributed in the hope that it will be useful, but WITHOUT
|
24
|
-
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
25
|
-
# FOR A PARTICULAR PURPOSE.
|
26
|
-
|
27
|
-
require 'thread'
|
28
|
-
require 'monitor'
|
29
|
-
|
30
|
-
# = Pool
|
31
|
-
#
|
32
|
-
# Generalized object pool implementation. Implemented as a thread
|
33
|
-
# safe stack. Exclusive locking is needed both for push and pop.
|
34
|
-
#
|
35
|
-
class Pool < Array
|
36
|
-
|
37
|
-
include MonitorMixin
|
38
|
-
|
39
|
-
def initialize
|
40
|
-
super
|
41
|
-
@cv = new_cond()
|
42
|
-
end
|
43
|
-
|
44
|
-
# Add, restore an object to the pool.
|
45
|
-
|
46
|
-
def push(obj)
|
47
|
-
synchronize do
|
48
|
-
super
|
49
|
-
@cv.signal()
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
# Obtain an object from the pool.
|
54
|
-
|
55
|
-
def pop
|
56
|
-
synchronize do
|
57
|
-
@cv.wait_while { empty? }
|
58
|
-
super
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
# Obtains an object, passes it to a block for processing
|
63
|
-
# and restores it to the pool.
|
64
|
-
|
65
|
-
def obtain
|
66
|
-
result = nil
|
67
|
-
begin
|
68
|
-
obj = pop()
|
69
|
-
result = yield(obj)
|
70
|
-
ensure
|
71
|
-
push(obj)
|
72
|
-
end
|
73
|
-
return result
|
74
|
-
end
|
75
|
-
|
76
|
-
end
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
# _____ _
|
81
|
-
# |_ _|__ ___| |_
|
82
|
-
# | |/ _ \/ __| __|
|
83
|
-
# | | __/\__ \ |_
|
84
|
-
# |_|\___||___/\__|
|
85
|
-
#
|
86
|
-
|
87
|
-
# TODO
|
88
|
-
|
89
|
-
=begin #testing
|
90
|
-
|
91
|
-
=end
|
data/lib/more/facets/pqueue.rb
DELETED
@@ -1,449 +0,0 @@
|
|
1
|
-
# = PQueue
|
2
|
-
#
|
3
|
-
# Priority queue with array based heap.
|
4
|
-
#
|
5
|
-
# A priority queue is like a standard queue, except that each inserted
|
6
|
-
# elements is given a certain priority, based on the result of the
|
7
|
-
# comparison block given at instantiation time. Also, retrieving an element
|
8
|
-
# from the queue will always return the one with the highest priority
|
9
|
-
# (see #pop and #top).
|
10
|
-
#
|
11
|
-
# The default is to compare the elements in repect to their #> method.
|
12
|
-
# For example, Numeric elements with higher values will have higher
|
13
|
-
# priorities.
|
14
|
-
#
|
15
|
-
# == Thanks
|
16
|
-
#
|
17
|
-
# Rick Bradley 2003/02/02, patch for Ruby 1.6.5. Thank you!
|
18
|
-
#
|
19
|
-
# == Authors
|
20
|
-
#
|
21
|
-
# * Olivier Renaud
|
22
|
-
# * K.Kodama (Created original PQueue.rb)
|
23
|
-
# * Ronald Butler (reated original Heap.rb)
|
24
|
-
#
|
25
|
-
# == Copying
|
26
|
-
#
|
27
|
-
# Copyright (c) 2005 K.Kodama, Ronald Butler, Olivier Renaud
|
28
|
-
|
29
|
-
# = PQueue
|
30
|
-
#
|
31
|
-
# Priority queue with array based heap.
|
32
|
-
#
|
33
|
-
# A priority queue is like a standard queue, except that each inserted
|
34
|
-
# elements is given a certain priority, based on the result of the
|
35
|
-
# comparison block given at instantiation time. Also, retrieving an element
|
36
|
-
# from the queue will always return the one with the highest priority
|
37
|
-
# (see #pop and #top).
|
38
|
-
#
|
39
|
-
# The default is to compare the elements in repect to their #> method.
|
40
|
-
# For example, Numeric elements with higher values will have higher
|
41
|
-
# priorities.
|
42
|
-
#
|
43
|
-
class PQueue
|
44
|
-
|
45
|
-
# number of elements
|
46
|
-
attr_reader :size
|
47
|
-
# compare Proc
|
48
|
-
attr_reader :gt
|
49
|
-
attr_reader :qarray #:nodoc:
|
50
|
-
protected :qarray
|
51
|
-
|
52
|
-
# Returns a new priority queue.
|
53
|
-
#
|
54
|
-
# If elements are given, build the priority queue with these initial
|
55
|
-
# values. The elements object must respond to #to_a.
|
56
|
-
#
|
57
|
-
# If a block is given, it will be used to determine the priority between
|
58
|
-
# the elements.
|
59
|
-
#
|
60
|
-
# By default, the priority queue retrieves maximum elements first
|
61
|
-
# (using the #> method).
|
62
|
-
def initialize(elements=nil, &block) # :yields: a, b
|
63
|
-
@qarray = [nil]
|
64
|
-
@size = 0
|
65
|
-
@gt = block || lambda {|a,b| a > b}
|
66
|
-
replace(elements) if elements
|
67
|
-
end
|
68
|
-
|
69
|
-
private
|
70
|
-
|
71
|
-
# Assumes that the tree is a heap, for nodes < k.
|
72
|
-
#
|
73
|
-
# The element at index k will go up until it finds its place.
|
74
|
-
def upheap(k)
|
75
|
-
k2 = k.div(2)
|
76
|
-
v = @qarray[k]
|
77
|
-
while k2 > 0 && @gt[v, @qarray[k2]]
|
78
|
-
@qarray[k] = @qarray[k2]
|
79
|
-
k = k2
|
80
|
-
k2 = k2.div(2)
|
81
|
-
end
|
82
|
-
@qarray[k] = v
|
83
|
-
end
|
84
|
-
|
85
|
-
# Assumes the entire tree is a heap.
|
86
|
-
#
|
87
|
-
# The element at index k will go down until it finds its place.
|
88
|
-
def downheap(k)
|
89
|
-
v = @qarray[k]
|
90
|
-
q2 = @size.div(2)
|
91
|
-
loop {
|
92
|
-
break if k > q2
|
93
|
-
j = 2 * k
|
94
|
-
if j < @size && @gt[@qarray[j+1], @qarray[j]]
|
95
|
-
j += 1
|
96
|
-
end
|
97
|
-
break if @gt[v, @qarray[j]]
|
98
|
-
@qarray[k] = @qarray[j]
|
99
|
-
k = j
|
100
|
-
}
|
101
|
-
@qarray[k] = v;
|
102
|
-
end
|
103
|
-
|
104
|
-
|
105
|
-
# Recursive version of heapify. I kept the code, since it may be
|
106
|
-
# easier to understand than the non-recursive one.
|
107
|
-
# def heapify
|
108
|
-
# @size.div(2).downto(1) {|i| h(i)}
|
109
|
-
# end
|
110
|
-
# def h(t)
|
111
|
-
# l = 2 * t
|
112
|
-
# r = l + 1
|
113
|
-
# hi = if r > @size || @gt[@qarray[l],@qarray[r]] then l else r end
|
114
|
-
# if @gt[@qarray[hi],@qarray[t]]
|
115
|
-
# @qarray[hi], @qarray[t] = @qarray[t], @qarray[hi]
|
116
|
-
# h(hi) if hi <= @size.div(2)
|
117
|
-
# end
|
118
|
-
# end
|
119
|
-
|
120
|
-
# Make a heap out of an unordered array.
|
121
|
-
def heapify
|
122
|
-
@size.div(2).downto(1) do |t|
|
123
|
-
begin
|
124
|
-
l = 2 * t
|
125
|
-
r = l + 1
|
126
|
-
hi = if r > @size || @gt[@qarray[l],@qarray[r]] then l else r end
|
127
|
-
if @gt[@qarray[hi],@qarray[t]]
|
128
|
-
@qarray[hi], @qarray[t] = @qarray[t], @qarray[hi]
|
129
|
-
if hi <= @size.div(2)
|
130
|
-
t = hi
|
131
|
-
redo
|
132
|
-
end # if
|
133
|
-
end #if
|
134
|
-
end #begin
|
135
|
-
end # downto
|
136
|
-
end
|
137
|
-
|
138
|
-
public
|
139
|
-
|
140
|
-
# Add an element in the priority queue.
|
141
|
-
#
|
142
|
-
# The insertion time is O(log n), with n the size of the queue.
|
143
|
-
def push(v)
|
144
|
-
@size += 1
|
145
|
-
@qarray[@size] = v
|
146
|
-
upheap(@size)
|
147
|
-
return self
|
148
|
-
end
|
149
|
-
|
150
|
-
alias :<< :push
|
151
|
-
|
152
|
-
# Return the element with the highest priority and remove it from
|
153
|
-
# the queue.
|
154
|
-
#
|
155
|
-
# The highest priority is determined by the block given at instanciation
|
156
|
-
# time.
|
157
|
-
#
|
158
|
-
# The deletion time is O(log n), with n the size of the queue.
|
159
|
-
#
|
160
|
-
# Return nil if the queue is empty.
|
161
|
-
def pop
|
162
|
-
return nil if empty?
|
163
|
-
res = @qarray[1]
|
164
|
-
@qarray[1] = @qarray[@size]
|
165
|
-
@size -= 1
|
166
|
-
downheap(1)
|
167
|
-
return res
|
168
|
-
end
|
169
|
-
|
170
|
-
# Return the element with the highest priority.
|
171
|
-
def top
|
172
|
-
return nil if empty?
|
173
|
-
return @qarray[1]
|
174
|
-
end
|
175
|
-
|
176
|
-
# Add more than one element at the same time. See #push.
|
177
|
-
#
|
178
|
-
# The elements object must respond to #to_a, or to be a PQueue itself.
|
179
|
-
def push_all(elements)
|
180
|
-
if empty?
|
181
|
-
if elements.kind_of?(PQueue)
|
182
|
-
initialize_copy(elements)
|
183
|
-
else
|
184
|
-
replace(elements)
|
185
|
-
end
|
186
|
-
else
|
187
|
-
if elements.kind_of?(PQueue)
|
188
|
-
@qarray[@size + 1, elements.size] = elements.qarray[1..-1]
|
189
|
-
elements.size.times{ @size += 1; upheap(@size)}
|
190
|
-
else
|
191
|
-
ary = elements.to_a
|
192
|
-
@qarray[@size + 1, ary.size] = ary
|
193
|
-
ary.size.times{ @size += 1; upheap(@size)}
|
194
|
-
end
|
195
|
-
end
|
196
|
-
return self
|
197
|
-
end
|
198
|
-
|
199
|
-
alias :merge :push_all
|
200
|
-
|
201
|
-
|
202
|
-
# Return top n-element as a sorted array.
|
203
|
-
def pop_array(n=@size)
|
204
|
-
ary = []
|
205
|
-
n.times{ary.push(pop)}
|
206
|
-
return ary
|
207
|
-
end
|
208
|
-
|
209
|
-
|
210
|
-
# True if there is no more elements left in the priority queue.
|
211
|
-
def empty?
|
212
|
-
return @size.zero?
|
213
|
-
end
|
214
|
-
|
215
|
-
# Remove all elements from the priority queue.
|
216
|
-
def clear
|
217
|
-
@qarray.replace([nil])
|
218
|
-
@size = 0
|
219
|
-
return self
|
220
|
-
end
|
221
|
-
|
222
|
-
# Replace the content of the heap by the new elements.
|
223
|
-
#
|
224
|
-
# The elements object must respond to #to_a, or to be a PQueue itself.
|
225
|
-
def replace(elements)
|
226
|
-
if elements.kind_of?(PQueue)
|
227
|
-
initialize_copy(elements)
|
228
|
-
else
|
229
|
-
@qarray.replace([nil] + elements.to_a)
|
230
|
-
@size = @qarray.size - 1
|
231
|
-
heapify
|
232
|
-
end
|
233
|
-
return self
|
234
|
-
end
|
235
|
-
|
236
|
-
# Return a sorted array, with highest priority first.
|
237
|
-
def to_a
|
238
|
-
old_qarray = @qarray.dup
|
239
|
-
old_size = @size
|
240
|
-
res = pop_array
|
241
|
-
@qarray = old_qarray
|
242
|
-
@size = old_size
|
243
|
-
return res
|
244
|
-
end
|
245
|
-
|
246
|
-
alias :sort :to_a
|
247
|
-
|
248
|
-
# Replace the top element with the given one, and return this top element.
|
249
|
-
#
|
250
|
-
# Equivalent to successively calling #pop and #push(v).
|
251
|
-
def replace_top(v)
|
252
|
-
# replace top element
|
253
|
-
if empty?
|
254
|
-
@qarray[1] = v
|
255
|
-
@size += 1
|
256
|
-
return nil
|
257
|
-
else
|
258
|
-
res = @qarray[1]
|
259
|
-
@qarray[1] = v
|
260
|
-
downheap(1)
|
261
|
-
return res
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
265
|
-
# Return true if the given object is present in the queue.
|
266
|
-
def include?(element)
|
267
|
-
return @qarray.include?(element)
|
268
|
-
end
|
269
|
-
|
270
|
-
# Iterate over the ordered elements, destructively.
|
271
|
-
def each_pop #:yields: popped
|
272
|
-
until empty?
|
273
|
-
yield pop
|
274
|
-
end
|
275
|
-
return nil
|
276
|
-
end
|
277
|
-
|
278
|
-
# Pretty print
|
279
|
-
def inspect
|
280
|
-
"<#{self.class}: size=#{@size}, top=#{top || "nil"}>"
|
281
|
-
end
|
282
|
-
|
283
|
-
###########################
|
284
|
-
### Override Object methods
|
285
|
-
|
286
|
-
# Return true if the queues contain equal elements.
|
287
|
-
def ==(other)
|
288
|
-
return size == other.size && to_a == other.to_a
|
289
|
-
end
|
290
|
-
|
291
|
-
private
|
292
|
-
|
293
|
-
def initialize_copy(other)
|
294
|
-
@gt = other.gt
|
295
|
-
@qarray = other.qarray.dup
|
296
|
-
@size = other.size
|
297
|
-
end
|
298
|
-
end # class PQueue
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
# _____ _
|
303
|
-
# |_ _|__ ___| |_
|
304
|
-
# | |/ _ \/ __| __|
|
305
|
-
# | | __/\__ \ |_
|
306
|
-
# |_|\___||___/\__|
|
307
|
-
#
|
308
|
-
|
309
|
-
=begin #test
|
310
|
-
|
311
|
-
require 'test/unit'
|
312
|
-
|
313
|
-
class TC_PQueue < Test::Unit::TestCase
|
314
|
-
ARY_TEST = [2,6,1,3,8,15,0,-4,7,8,10]
|
315
|
-
ARY_TEST_2 = [25,10,5,13,16,9,16,12]
|
316
|
-
|
317
|
-
def test_initialize
|
318
|
-
assert_nothing_raised { PQueue.new }
|
319
|
-
assert_nothing_raised { PQueue.new([3]) }
|
320
|
-
assert_nothing_raised { PQueue.new(ARY_TEST) }
|
321
|
-
assert_nothing_raised { PQueue.new {|a,b| a<b} }
|
322
|
-
assert_nothing_raised { PQueue.new([3]) {|a,b| a<b} }
|
323
|
-
assert_nothing_raised { PQueue.new(ARY_TEST) {|a,b| a<b} }
|
324
|
-
end
|
325
|
-
|
326
|
-
def test_top
|
327
|
-
assert_equal(ARY_TEST.max, PQueue.new(ARY_TEST).top)
|
328
|
-
assert_nil(PQueue.new.top)
|
329
|
-
end
|
330
|
-
|
331
|
-
def test_pop
|
332
|
-
sorted_ary = ARY_TEST.sort
|
333
|
-
q = PQueue.new(ARY_TEST)
|
334
|
-
ARY_TEST.size.times do
|
335
|
-
assert_equal(sorted_ary.pop, q.pop)
|
336
|
-
end
|
337
|
-
assert_equal(0, q.size)
|
338
|
-
assert_nil(PQueue.new.pop)
|
339
|
-
end
|
340
|
-
|
341
|
-
def test_insertion
|
342
|
-
q = PQueue.new(ARY_TEST)
|
343
|
-
assert_equal(ARY_TEST.size, q.size)
|
344
|
-
|
345
|
-
ret = q.push(24)
|
346
|
-
assert_equal(q, ret)
|
347
|
-
assert_equal(ARY_TEST.size+1, q.size)
|
348
|
-
|
349
|
-
ret = q.push_all(ARY_TEST_2)
|
350
|
-
assert_equal(q, ret)
|
351
|
-
assert_equal(ARY_TEST.size+1+ARY_TEST_2.size, q.size)
|
352
|
-
|
353
|
-
q = PQueue.new(ARY_TEST)
|
354
|
-
r = PQueue.new(ARY_TEST_2)
|
355
|
-
q.push_all(r)
|
356
|
-
assert_equal(ARY_TEST.size + ARY_TEST_2.size, q.size)
|
357
|
-
end
|
358
|
-
|
359
|
-
def test_clear
|
360
|
-
q = PQueue.new(ARY_TEST).clear
|
361
|
-
assert_equal(q, q.clear)
|
362
|
-
assert_equal(0, q.size)
|
363
|
-
end
|
364
|
-
|
365
|
-
def test_replace
|
366
|
-
q = PQueue.new(ARY_TEST)
|
367
|
-
q.replace(ARY_TEST_2)
|
368
|
-
assert_equal(ARY_TEST_2.size, q.size)
|
369
|
-
|
370
|
-
q = PQueue.new(ARY_TEST)
|
371
|
-
q.replace(PQueue.new(ARY_TEST_2))
|
372
|
-
assert_equal(ARY_TEST_2.size, q.size)
|
373
|
-
end
|
374
|
-
|
375
|
-
def test_inspect
|
376
|
-
assert_equal("<PQueue: size=#{ARY_TEST.size}, top=#{ARY_TEST.max}>",
|
377
|
-
PQueue.new(ARY_TEST).inspect)
|
378
|
-
end
|
379
|
-
|
380
|
-
def test_to_a
|
381
|
-
q = PQueue.new(ARY_TEST)
|
382
|
-
assert_equal(ARY_TEST.sort.reverse, q.sort)
|
383
|
-
q = PQueue.new(0..4)
|
384
|
-
assert_equal([4,3,2,1,0], q.sort)
|
385
|
-
end
|
386
|
-
|
387
|
-
def pop_array
|
388
|
-
q = PQueue.new(ARY_TEST)
|
389
|
-
assert_equal(ARY_TEST.sort.reverse[0..5], q.pop_array(5))
|
390
|
-
q = PQueue.new(ARY_TEST)
|
391
|
-
assert_equal(ARY_TEST.sort.reverse, q.pop_array)
|
392
|
-
end
|
393
|
-
|
394
|
-
def test_include
|
395
|
-
q = PQueue.new(ARY_TEST + [21] + ARY_TEST_2)
|
396
|
-
assert_equal(true, q.include?(21))
|
397
|
-
|
398
|
-
q = PQueue.new(ARY_TEST - [15])
|
399
|
-
assert_equal(false, q.include?(15))
|
400
|
-
end
|
401
|
-
|
402
|
-
def test_assert_equal
|
403
|
-
assert_equal(PQueue.new, PQueue.new)
|
404
|
-
assert_equal(PQueue.new(ARY_TEST), PQueue.new(ARY_TEST.sort_by{rand}))
|
405
|
-
end
|
406
|
-
|
407
|
-
def test_replace_top
|
408
|
-
q = PQueue.new
|
409
|
-
assert_nil(q.replace_top(6))
|
410
|
-
assert_equal(6, q.top)
|
411
|
-
|
412
|
-
q = PQueue.new(ARY_TEST)
|
413
|
-
h = PQueue.new(ARY_TEST)
|
414
|
-
q.pop; q.push(11)
|
415
|
-
h.replace_top(11)
|
416
|
-
assert_equal(q, h)
|
417
|
-
end
|
418
|
-
|
419
|
-
def test_dup
|
420
|
-
q = PQueue.new(ARY_TEST)
|
421
|
-
assert_equal(q, q.dup)
|
422
|
-
end
|
423
|
-
|
424
|
-
def test_array_copied
|
425
|
-
ary = ARY_TEST.dup
|
426
|
-
q = PQueue.new(ary)
|
427
|
-
q.pop
|
428
|
-
assert_equal(ARY_TEST, ary)
|
429
|
-
|
430
|
-
ary = ARY_TEST.dup
|
431
|
-
q = PQueue.new
|
432
|
-
q.replace(ary)
|
433
|
-
q.pop
|
434
|
-
assert_equal(ARY_TEST, ary)
|
435
|
-
|
436
|
-
ary = ARY_TEST.dup
|
437
|
-
q = PQueue.new([1])
|
438
|
-
q.push_all(ary)
|
439
|
-
q.pop
|
440
|
-
assert_equal(ARY_TEST, ary)
|
441
|
-
|
442
|
-
q = PQueue.new(ARY_TEST)
|
443
|
-
r = q.dup
|
444
|
-
q.pop
|
445
|
-
assert_not_equal(q, r)
|
446
|
-
end
|
447
|
-
end
|
448
|
-
|
449
|
-
=end
|