casegen 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/casegen +11 -0
- data/src/agents/sets.rb +336 -0
- data/src/agents/sets/enum/by.rb +244 -0
- data/src/agents/sets/enum/cluster.rb +164 -0
- data/src/agents/sets/enum/inject.rb +50 -0
- data/src/agents/sets/enum/install.rb +73 -0
- data/src/agents/sets/enum/nest.rb +117 -0
- data/src/agents/sets/enum/op.rb +283 -0
- data/src/agents/sets/enum/pipe.rb +160 -0
- data/src/agents/sets/enum/tree.rb +442 -0
- data/src/calc.sample.txt +13 -0
- data/src/cart.sample.txt +33 -0
- data/src/casegen.rb +191 -0
- data/src/ruby_array.sample.txt +20 -0
- metadata +66 -0
@@ -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
|