casegen 1.3.0

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