casegen 1.3.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.
@@ -0,0 +1,164 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ module Enumerable
4
+
5
+ def each_cluster n = 2
6
+ tuple = [nil] * n
7
+
8
+ count = n-1
9
+ each { |x|
10
+ tuple.shift
11
+ tuple.push x
12
+ if count == 0
13
+ yield tuple
14
+ else
15
+ count -= 1
16
+ end
17
+ }
18
+ end
19
+
20
+ def each_with_neighbors n = 1, empty = nil
21
+ nbrs = [empty] * (2 * n + 1)
22
+ offset = n
23
+
24
+ each { |x|
25
+ nbrs.shift
26
+ nbrs.push x
27
+ if offset == 0 # offset is now the offset of the first element, x0,
28
+ yield nbrs # of the sequence from the center of nbrs, or 0,
29
+ else # if x0 has already passed the center.
30
+ offset -= 1
31
+ end
32
+ }
33
+
34
+ n.times {
35
+ nbrs.shift
36
+ nbrs.push empty
37
+ if offset == 0
38
+ yield nbrs
39
+ else
40
+ offset -= 1
41
+ end
42
+ }
43
+
44
+ self
45
+ end
46
+
47
+ end
48
+
49
+
50
+ =begin
51
+
52
+ ==module Enumerable
53
+ ===instance methods
54
+ ---Enumerable#each_cluster n = 2
55
+ ---Enumerable#each_with_neighbors n = 1, empty = nil
56
+
57
+ Both methods iterate over a collection of arrays whose elements are drawn
58
+ in sequence from the original collection.
59
+
60
+ In the case of (({each_cluster})), the iteration yields all contiguous
61
+ subsequences of length ((|n|)). If the argument to (({each_cluster})) is 0
62
+ or larger than the size of the collection, the iteration yields no values.
63
+
64
+ In the case of (({each_with_neighbors})), the iteration yields one
65
+ sequence for each element ((|x|)) of the collection. The yielded sequence
66
+ includes the ((|n|)) elements before and after ((|x|)). Elements out of
67
+ bounds are filled with ((|empty|)). The first argument can be any
68
+ nonnegative integer.
69
+
70
+ ===examples
71
+
72
+ require 'enum/cluster'
73
+
74
+ (0..5).each_with_neighbors { |x| p x }
75
+
76
+ # prints:
77
+ # [nil, 0, 1]
78
+ # [0, 1, 2]
79
+ # [1, 2, 3]
80
+ # [2, 3, 4]
81
+ # [3, 4, 5]
82
+ # [4, 5, nil]
83
+
84
+ [1,2,3,4].each_with_neighbors(8, 0) { |x| p x }
85
+
86
+ # prints:
87
+ # [0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 0, 0]
88
+ # [0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0]
89
+ # [0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0]
90
+ # [0, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0]
91
+
92
+ ('a'..'g').each_cluster(5) { |x| p x.join '' }
93
+
94
+ # prints:
95
+ # "abcde"
96
+ # "bcdef"
97
+ # "cdefg"
98
+
99
+ See the end of the source file for more examples.
100
+
101
+ ==version
102
+
103
+ Enumerable tools 1.6
104
+
105
+ The current version of this software can be found at
106
+ ((<"http://redshift.sourceforge.net/enum
107
+ "|URL:http://redshift.sourceforge.net/enum>)).
108
+
109
+ ==license
110
+ This software is distributed under the Ruby license.
111
+ See ((<"http://www.ruby-lang.org"|URL:http://www.ruby-lang.org>)).
112
+
113
+ ==author
114
+ Joel VanderWerf,
115
+ ((<vjoel@users.sourceforge.net|URL:mailto:vjoel@users.sourceforge.net>))
116
+
117
+ =end
118
+
119
+
120
+ if __FILE__ == $0
121
+
122
+ (0..5).each_with_neighbors { |x| p x }
123
+
124
+ puts
125
+
126
+ [1,2,3,4].each_with_neighbors(8, 0) { |x| p x }
127
+
128
+ puts
129
+
130
+ ('a'..'g').each_cluster(5) { |x| p x.join '' }
131
+
132
+ puts
133
+
134
+ begin
135
+ require 'enum/by'
136
+
137
+ # each_with_neighbors is useful for successive comparisons:
138
+ 2.by {|x| x<10000 && x**2}.each_with_neighbors(1, 1) {
139
+ |prev_x, x, next_x|
140
+ printf "%d - %d = %d\n", x, prev_x, x - prev_x
141
+ }
142
+ puts
143
+
144
+ # Construct a doubly linked list:
145
+ Node = Struct.new "Node", :value, :prev_node, :next_node
146
+
147
+ list = (1..10).collect { |i| Node.new i }
148
+
149
+ list.each_with_neighbors { |prev_node, node, next_node|
150
+ node.prev_node = prev_node
151
+ node.next_node = next_node
152
+ }
153
+
154
+ list[0].by(:next_node).each { |node| print node.value, " " }
155
+ puts
156
+
157
+ # We constructed the list and interated over it without ever
158
+ # explicitly mentioning nil.
159
+
160
+ rescue LoadError
161
+ puts "File enum/by.rb not available. You're missing the best part!"
162
+ end
163
+
164
+ end
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ =begin
4
+ ---Enumerable#inject
5
+ ---Enumerable#sum [block]
6
+
7
+ Code adapted from Pickaxe book, p.102.
8
+ See source file for examples.
9
+
10
+ ==version
11
+
12
+ Enumerable tools 1.6
13
+
14
+ =end
15
+
16
+ module Enumerable
17
+
18
+ def inject n
19
+ each { |i|
20
+ n = yield n, i
21
+ }
22
+ n
23
+ end
24
+ alias :accumulate :inject
25
+
26
+ def sum
27
+ if block_given?
28
+ inject(0) { |n, i| n + yield(i) }
29
+ else
30
+ inject(0) { |n, i| n + i }
31
+ end
32
+ end
33
+
34
+ def product
35
+ if block_given?
36
+ inject(1) { |n, i| n * yield(i) }
37
+ else
38
+ inject(1) { |n, i| n * i }
39
+ end
40
+ end
41
+
42
+ end
43
+
44
+ if __FILE__ == $0
45
+
46
+ x = (0..9).collect { |i| [i, i*i] }
47
+ p x
48
+ p x.sum { |v| v[1] }
49
+
50
+ end
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rbconfig'
4
+ require 'getoptlong'
5
+ require 'ftools'
6
+
7
+ destdir = Config::CONFIG['sitedir']
8
+ noharm = false
9
+
10
+ Usage = <<END
11
+ Usage: ruby install.rb [options]
12
+
13
+ option argument action
14
+ ------ -------- ------
15
+ --destdir dir Destination dir
16
+ -d (default is #{destdir})
17
+
18
+ --help Print this help
19
+ -h
20
+
21
+ --noharm Do not install, just print commands
22
+ -n
23
+
24
+ Installs all .rb files from current dir and below, preserving
25
+ directory structure, into a subdir of the destination dir. The name
26
+ of this subdir is formed by stripping the version number off the end
27
+ of the current dir. The version number is the largest suffix that
28
+ contains no dashes.
29
+
30
+ END
31
+
32
+ opts = GetoptLong.new(
33
+ [ "--destdir", "-d", GetoptLong::REQUIRED_ARGUMENT ],
34
+ [ "--help", "-h", GetoptLong::NO_ARGUMENT ],
35
+ [ "--noharm", "-n", GetoptLong::NO_ARGUMENT ]
36
+ )
37
+
38
+ opts.each do |opt, arg|
39
+ case opt
40
+ when '--destdir', '-d'
41
+ destdir = arg
42
+ when '--help', '-h'
43
+ print Usage, "\n"
44
+ exit
45
+ when '--noharm', '-n'
46
+ noharm = true
47
+ else
48
+ raise "unrecognized option: ", opt
49
+ end
50
+ end
51
+
52
+ raise ArgumentError,
53
+ "unrecognized arguments #{ARGV.join(' ')}" unless ARGV == []
54
+
55
+ basedir = (File.split(Dir.getwd))[1].sub(/-[^-]*\z/, "")
56
+ files = Dir.glob("**/*.rb").map { |file| file.sub(/\A\.\//, "") }
57
+ files = files.reject {|file| file == __FILE__ }
58
+ files.map! { |file|
59
+ [file,
60
+ File.join(destdir, basedir, file)]
61
+ }
62
+
63
+ dirs = {}
64
+ for src, dest in files
65
+ d = File.dirname dest
66
+ unless dirs[d]
67
+ puts "File.makedir #{d}"
68
+ File.makedirs d unless noharm
69
+ dirs[d] = true
70
+ end
71
+ puts "File.install #{src}, #{dest}, 0644, true"
72
+ File.install(src, dest, 0644, true) unless noharm
73
+ end
@@ -0,0 +1,117 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ module Enumerable
4
+
5
+ def nest(&compare)
6
+ ary = to_a
7
+ s = ary.size
8
+ i = 0
9
+
10
+ # wrap into Array::Iterator?
11
+ items_left = proc { i < s }
12
+ get_cur = proc { ary[i] }
13
+ go_next = proc { i += 1 }
14
+
15
+ result = nil
16
+ while items_left[]
17
+ level_ary = Enumerable.nest items_left, get_cur, go_next, compare
18
+ result = result ? level_ary.unshift(result) : level_ary
19
+ end
20
+ result || []
21
+ end
22
+
23
+ # Handles a single level, recursing when the depth increases and
24
+ # backing out when the depth decreases.
25
+ def Enumerable.nest items_left, get_cur, go_next, compare
26
+ # should handle compare.arity == 2 like a <=> proc
27
+ result = []; item = depth = nil
28
+ while items_left[]
29
+ item = get_cur[]
30
+ depth = compare[item]
31
+ base_depth ||= depth
32
+
33
+ if depth < base_depth
34
+ break
35
+ elsif depth > base_depth
36
+ result << nest(items_left, get_cur, go_next, compare)
37
+ else
38
+ result << item; go_next[]
39
+ end
40
+ end
41
+ return result
42
+ end
43
+
44
+ def group(&test)
45
+ nest { |x| test[x] ? 1 : 0 }
46
+ end
47
+ end
48
+
49
+ =begin
50
+
51
+ =module Enumerable
52
+ ==instance methods
53
+ ---Enumerable#nest &compare
54
+
55
+ (({nest})) is an inverse for (({Array#flatten})). (Well, actually only a right
56
+ inverse since (({flatten})) is not injective.) You give it a proc that
57
+ calculates the depth of each item, and it returns a nesting of arrays in which
58
+ each item has the desired depth. It can be used to parse strings with
59
+ Python-like indentation syntax, but it isn't limited to strings.
60
+
61
+ The main improvement in this version is that the compare block can return
62
+ a lower value for an element after the first, with the expected effect. See the first example at the end of the source file.
63
+
64
+ ===version
65
+
66
+ Enumerable tools 1.6
67
+
68
+ The current version of this software can be found at
69
+ ((<"http://redshift.sourceforge.net/enum
70
+ "|URL:http://redshift.sourceforge.net/enum>)).
71
+
72
+ ===license
73
+ This software is distributed under the Ruby license.
74
+ See ((<"http://www.ruby-lang.org"|URL:http://www.ruby-lang.org>)).
75
+
76
+ ===author
77
+ Joel VanderWerf,
78
+ ((<vjoel@users.sourceforge.net|URL:mailto:vjoel@users.sourceforge.net>))
79
+
80
+ =end
81
+
82
+ if __FILE__ == $0
83
+
84
+ str = <<END
85
+ a
86
+ aa
87
+ ab
88
+ aba
89
+ abb
90
+ abba
91
+ abbaa
92
+ abbb
93
+ ac
94
+ ad
95
+ ada
96
+ adaa
97
+ adb
98
+ b
99
+ ba
100
+ bb
101
+ c
102
+ ca
103
+ X
104
+ Y
105
+ Z
106
+ END
107
+
108
+ lines = str.split "\n"
109
+ nested = lines.nest { |line| /\S/ =~ line }
110
+ p nested
111
+ flat = nested.flatten
112
+ p flat
113
+ p flat == lines
114
+
115
+ p [1, 2, "three", "four", 5, "six"].group { |x| x.is_a? String }
116
+
117
+ end
@@ -0,0 +1,283 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'enum/inject'
4
+
5
+ module EnumerableOperator
6
+
7
+ class Product
8
+ include Enumerable
9
+
10
+ attr_reader :factors, :dim
11
+
12
+ def initialize(*factors)
13
+ @factors = factors
14
+ @dim = @factors.length
15
+ end
16
+
17
+ def each tuple = [nil]*@dim, i = 0, &block
18
+ if i == @dim - 1 then
19
+ @factors[i].each { |x| tuple[i] = x; yield tuple.dup }
20
+ elsif i > 0
21
+ @factors[i].each { |x| tuple[i] = x; each tuple, i + 1, &block }
22
+ else
23
+ @factors[i].each { |x| tuple[i] = x; each tuple, i + 1, &block }
24
+ self
25
+ end
26
+ end
27
+
28
+ def size
29
+ @factors.product { |enum| enum.size }
30
+ end
31
+
32
+ end
33
+
34
+ class Sum
35
+ include Enumerable
36
+
37
+ attr_reader :summands
38
+
39
+ def initialize(*summands)
40
+ @summands = summands
41
+ end
42
+
43
+ def each(&block)
44
+ @summands.each { |enum| enum.each(&block) }
45
+ self
46
+ end
47
+
48
+ def size
49
+ @summands.sum { |enum| enum.size }
50
+ end
51
+
52
+ end
53
+
54
+ class Diagonal
55
+ include Enumerable
56
+
57
+ attr_reader :factors, :dim
58
+
59
+ def initialize(*factors)
60
+ @factors = factors
61
+ @dim = @factors.length
62
+ end
63
+
64
+ def each
65
+ factors = @factors.map { |factor|
66
+ if factor.kind_of? Array then factor else factor.entries end
67
+ }
68
+ minlength = factors.min { |f, g| f.length <=> g.length }.length
69
+ for i in 0..(minlength-1)
70
+ yield factors.map { |factor| factor[i] }
71
+ end
72
+ self
73
+ end
74
+ end
75
+
76
+
77
+ def product(*factors, &block)
78
+ if block
79
+ Product.new(*factors).each(&block)
80
+ else
81
+ Product.new(*factors)
82
+ end
83
+ end
84
+ alias :tuples :product
85
+
86
+ def sum(*summands, &block)
87
+ if block
88
+ Sum.new(*summands).each(&block)
89
+ else
90
+ Sum.new(*summands)
91
+ end
92
+ end
93
+ alias :concatenation :sum
94
+ alias :cat :sum
95
+
96
+ def diagonal(*factors, &block)
97
+ if block
98
+ Diagonal.new(*factors).each(&block)
99
+ else
100
+ Diagonal.new(*factors)
101
+ end
102
+ end
103
+
104
+ module_function :product, :sum, :diagonal
105
+ end
106
+
107
+ =begin
108
+
109
+ ==module EnumerableOperator
110
+ ===instance methods and module methods
111
+ ---EnumerableOperator#product *factors, &block
112
+ ---EnumerableOperator#sum *summands, &block
113
+
114
+ The (({product})) operator iterates over the Cartesian product of the factors,
115
+ each of which must be (({Enumerable})).
116
+
117
+ The (({sum})) operator iterates over the concatenation of the summands, each of
118
+ which must be (({Enumerable})).
119
+
120
+ Both operators have aliases: (({tuples})) for (({product}));
121
+ (({concatenation})) and (({cat})) for (({sum})).
122
+
123
+ Called with a block, the operators yield one element of the sequence at a time
124
+ to the block.
125
+
126
+ With or without a block, the operators return an (({Enumerable})) which
127
+ delegates to the original (({Enumerables})), but does not explicitly construct
128
+ the entire collection. Calling another (({Enumerable})) method, such as
129
+ (({select})) or (({collect})), on this return value is an efficient way of
130
+ chaining these operators with other methods. Simply call (({entries})) to get
131
+ the whole collection. Also, because the operators return an (({Enumerable})),
132
+ they can be used with the (({for})) syntax; see the examples.
133
+
134
+ ---EnumerableOperator#diagonal *factors, &block
135
+
136
+ The (({diagonal})) operator iterates over the diagonal of the Cartesian product
137
+ of the factors, each of which must be (({Enumerable})). In other words, the
138
+ n-th entry of the diagonal is an array of the n-th entries of each factor. The
139
+ resulting sequence terminates when any one factor terminates. Hence the
140
+ sequence has the same length as the shortest factor.
141
+
142
+ Called with a block, (({diagonal})) yields one element of the sequence at a
143
+ time to the block.
144
+
145
+ With or without a block, (({diagonal})) returns an (({Enumerable})) object
146
+ which is ((*independent*)) of the original (({Enumerables})). As with
147
+ (({product})) and (({sum})), this allows chaining with other iterators and
148
+ using the (({for})) syntax. Unlike (({product})) and (({sum})), however, the
149
+ entire collection is generated and stored in the object returned by
150
+ (({diagonal})).
151
+
152
+ Internally, (({diagonal})) does not enumerate the sequences in parallel, but in
153
+ the order in which they are given. If the sequences have side-effects of
154
+ enumeration, this may result in different behavior than if the sequences were
155
+ truly enumerated in parallel (e.g., see matz's approach using threads in the
156
+ Ruby FAQ: ((<"http://www.rubycentral.com/faq/rubyfaq-5.html#ss5.5
157
+ "|URL:http://www.rubycentral.com/faq/rubyfaq-5.html#ss5.5>))).
158
+
159
+ ===usage
160
+
161
+ include EnumerableOperator
162
+ diagonal enum0, enum1, ...
163
+ or
164
+ EnumerableOperator.diagonal enum0, enum1, ...
165
+ and similarly for product and sum.
166
+
167
+ ===examples
168
+
169
+ require 'enum/op'
170
+ include EnumerableOperator
171
+
172
+ # using the 'for ... in ... end' construct:
173
+ for i, j in product 1..4, "bar".."baz"
174
+ printf "%6s", i.to_s + j; puts if j == "baz"
175
+ end
176
+ puts
177
+
178
+ # prints:
179
+ # 1bar 1bas 1bat 1bau 1bav 1baw 1bax 1bay 1baz
180
+ # 2bar 2bas 2bat 2bau 2bav 2baw 2bax 2bay 2baz
181
+ # 3bar 3bas 3bat 3bau 3bav 3baw 3bax 3bay 3baz
182
+
183
+ # directly passing a block:
184
+ sum 1..5, 'a'..'c', 90..92 do |i|
185
+ printf "%4s", i.to_s
186
+ end
187
+ puts "\n\n"
188
+
189
+ # prints:
190
+ # 1 2 3 4 5 a b c 90 91 92
191
+
192
+ for i, j, k in diagonal 1..4, 'a'..'d', ?a..?d
193
+ printf "%4d. %s is 0x%x\n", i, j, k
194
+ end
195
+ puts
196
+
197
+ # prints:
198
+ # 1. a is 0x61
199
+ # 2. b is 0x62
200
+ # 3. c is 0x63
201
+ # 4. d is 0x64
202
+
203
+ # chaining with other iterators:
204
+ names = %w{ Ludwig Rudolf Bertrand Willard }
205
+ more_names = %w{ Jean-Paul Albert Martin Soren }
206
+ puts sum(names, more_names).sort.join ', '
207
+ puts
208
+
209
+ # prints:
210
+ # Albert, Bertrand, Jean-Paul, Ludwig, Martin, Rudolf, Soren, Willard
211
+
212
+ # note that chaining avoids constructing the intermediate collection:
213
+ big_product = product 1..10, 1..10, 1..10
214
+ big_product.select { |x, y, z|
215
+ x <= y and x**2 + y**2 == z**2
216
+ }.each { |x, y, z|
217
+ printf "#{x}**2 + #{y}**2 == #{z}**2\n"
218
+ }
219
+
220
+ # prints:
221
+ # 3**2 + 4**2 == 5**2
222
+ # 6**2 + 8**2 == 10**2
223
+
224
+ ==version
225
+
226
+ Enumerable tools 1.6
227
+
228
+ The current version of this software can be found at
229
+ ((<"http://redshift.sourceforge.net/enum
230
+ "|URL:http://redshift.sourceforge.net/enum>)).
231
+
232
+ ==license
233
+ This software is distributed under the Ruby license.
234
+ See ((<"http://www.ruby-lang.org"|URL:http://www.ruby-lang.org>)).
235
+
236
+ ==author
237
+ Joel VanderWerf,
238
+ ((<vjoel@users.sourceforge.net|URL:mailto:vjoel@users.sourceforge.net>))
239
+
240
+ =end
241
+
242
+
243
+ if __FILE__ == $0
244
+
245
+ include EnumerableOperator
246
+
247
+ # using the 'for ... in ... end' construct:
248
+ for i, j in product 1..4, "bar".."baz"
249
+ printf "%6s", i.to_s + j; puts if j == "baz"
250
+ end
251
+ puts
252
+
253
+ # directly passing a block:
254
+ sum 1..5, 'a'..'c', 90..92 do |i|
255
+ printf "%4s", i.to_s
256
+ end
257
+ puts "\n\n"
258
+
259
+ for i, j, k in diagonal 1..4, 'a'..'d', ?a..?d
260
+ printf "%4d. %s is 0x%x\n", i, j, k
261
+ end
262
+ puts
263
+
264
+ # chaining with other iterators:
265
+ names = %w{ Ludwig Rudolf Bertrand Willard }
266
+ more_names = %w{ Jean-Paul Albert Martin Soren }
267
+ puts sum(names, more_names).sort.join(', ')
268
+ puts
269
+
270
+ # note that chaining avoids constructing the intermediate collection:
271
+ big_product = product 1..10, 1..10, 1..10
272
+ big_product.select { |x, y, z|
273
+ x <= y and x**2 + y**2 == z**2
274
+ }.each { |x, y, z|
275
+ printf "#{x}**2 + #{y}**2 == #{z}**2\n"
276
+ }
277
+ puts
278
+
279
+ # size
280
+ puts "sum(1..10,11..20).size = #{sum(1..10,11..20).size}"
281
+ puts "product(1..10,11..20).size = #{product(1..10,11..20).size}"
282
+ puts "product([1,2,3],[]).size = #{product([1,2,3],[]).size}"
283
+ end