setfu 1.0.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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +154 -0
- data/Rakefile +2 -0
- data/lib/setfu/version.rb +3 -0
- data/lib/setfu.rb +494 -0
- data/setfu.gemspec +31 -0
- metadata +115 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8b90873f3986a2bdf496d15f1f7aaa65802e51e3
|
4
|
+
data.tar.gz: 098b84b480360abe537007d4e84a4ba32f7b7933
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1e0dc3f17d1649ca8694a112128b3f609b7f81970eb1d1c8a3688f5e76e7b36082938dc23461644475faceef05470a2fd4605b08827f61e2010942fadd11b68d
|
7
|
+
data.tar.gz: afe4241c4c9f2c7bd266b4761860a76ddf3c09129e903d5e8c284fb11999e027731bc3e5989f6c7fe6e9a13418e7f0cc9098b4cf3ae330bb7aaf4a24d9f17c85
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Bryan Colvin
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
# Setfu
|
2
|
+
|
3
|
+
Purpose: A general purpose object implementing sets.
|
4
|
+
|
5
|
+
Construction:
|
6
|
+
Set.new >> creates an empty set
|
7
|
+
Set.new(p) >> creates a set initialized with elements p
|
8
|
+
Set.new.add!(p) >> chained with #add method
|
9
|
+
::parameter p::
|
10
|
+
"abcxyz" >> ordinate values of each character added to set
|
11
|
+
'a'..'z' >> ordinate values of each range element added to set
|
12
|
+
[6,19,'g'..'k'] >> items in an array added to set (recursively)
|
13
|
+
375 >> element number `375` added to set
|
14
|
+
or set instance
|
15
|
+
[v0,v1,...].to_set >> converts array to set instance
|
16
|
+
::array values::
|
17
|
+
set instance
|
18
|
+
array literal, array instance >> recursive values must comply to first-level rules
|
19
|
+
string literal, string instance
|
20
|
+
range literal, range instance
|
21
|
+
positive small integers including zero, integer instance
|
22
|
+
"a7P".to_set >> converts ordinate values of each char to set members
|
23
|
+
('a'..'k').to_set >> converts ordinate values of each char in range to set members
|
24
|
+
parenthesis needed for literal. parenthesis not needed for instance variable
|
25
|
+
|
26
|
+
Operators:
|
27
|
+
a < b >> true if `a` is a "proper" subset of `b` ... a !=b and a in b
|
28
|
+
a <= b >> true if `a` is a subset of `b`
|
29
|
+
a - b >> set difference ... removes elements from a found in b
|
30
|
+
a & b >> set intersection
|
31
|
+
a | b >> set union
|
32
|
+
a ^ b >> exclusive union
|
33
|
+
s == a >> equality ... both sets contain exactly the same elements
|
34
|
+
a === s >> case equality ... where `s` applies to case variable, and `a` applies to when clause
|
35
|
+
see: .set_case(sym) for additonal configuration
|
36
|
+
s != a >> inequality ... sets are different
|
37
|
+
~a >> inversion
|
38
|
+
a ** b >> intersection test ... true if one or more elements are common to both sets
|
39
|
+
s[i] >> true if 'i' is an element of the set
|
40
|
+
s[i]=k >> if k==true, adds element `i` to set, otherwise removes element `i` from set
|
41
|
+
where a,b === instances of Set, String, Array, Range
|
42
|
+
s === instance of Set
|
43
|
+
i === member index ... positive integer (0,1,2,3...) or char ('a')
|
44
|
+
character indexes use #ord to convert to integer
|
45
|
+
k === boolean
|
46
|
+
|
47
|
+
Methods:
|
48
|
+
.count >> returns number of elements in set
|
49
|
+
.each_member {block} >> iterates on element ordinate of each element in set
|
50
|
+
.add!(p) >> includes additional members to current set
|
51
|
+
.include?(p) >> true if `p` is a subset of current set
|
52
|
+
.empty? >> true if there are no elements in set
|
53
|
+
.zap! >> removes all elements of set and resets entropy to zero
|
54
|
+
.add_parse_chars! >> adds [0..47, 58..64, 91..96, 123..126] to set
|
55
|
+
.dup >> creates a copy of the current set
|
56
|
+
.to_i >> returns internal integer representing all bits of the set space
|
57
|
+
.to_s >> returns a string representation of all elements
|
58
|
+
.to_a >> returns an array of all elements (in integers)
|
59
|
+
.set_bits!(n) >> replaces set with each set bit of integer `n` ... negative numbers are not allowed!
|
60
|
+
.recalculate_entropy! >> calculates new entropy value based on current elements on set.
|
61
|
+
recommended to call this method after #set_bits! is called.
|
62
|
+
not necessary to be called for normal operation. Returns newly calculated entropy.
|
63
|
+
.min >> returns element of smallest ordinate value, or nil if empty set
|
64
|
+
.max >> returns element of highest ordinate value, or nil if empty set
|
65
|
+
.to_set >> returns self ... Also exported to String, Range, and Array which creates an instance of Set
|
66
|
+
.set_case(sym) >> sets case--when behavior as follows:
|
67
|
+
:mode_equal (default) case(s) -> when a ... validates on a ==s
|
68
|
+
:mode_intersection case(s) -> when a ... validates on a ** s
|
69
|
+
:mode_sub case(s) -> when a ... validates on a <= s
|
70
|
+
:mode_proper case(s) -> when a ... validates on a < s
|
71
|
+
:mode_super case(s) -> when a ... validates on s <= a
|
72
|
+
:mode_superproper case(s) -> when a ... validates on s < a
|
73
|
+
|
74
|
+
Properties:
|
75
|
+
.entropy >> Total number of possible states. Like the universe, can only get bigger.
|
76
|
+
Can be set to a higher number. Property may be read.
|
77
|
+
|
78
|
+
## Installation
|
79
|
+
|
80
|
+
Add this line to your application's Gemfile:
|
81
|
+
|
82
|
+
gem 'setfu'
|
83
|
+
|
84
|
+
And then execute:
|
85
|
+
|
86
|
+
$ bundle
|
87
|
+
|
88
|
+
Or install it yourself as:
|
89
|
+
|
90
|
+
$ gem install setfu
|
91
|
+
|
92
|
+
## Usage
|
93
|
+
|
94
|
+
The Set class defines a group of
|
95
|
+
positive integers including zero. Unlike the array, there is no implied order
|
96
|
+
to each element of the set other than their chronological order implied by their ordinate value.
|
97
|
+
Each set instance may not duplicate elements. The upper bounds of an element is only limited
|
98
|
+
to the size of (1 << element) that a Bignum may hold. Performance degrades with elements
|
99
|
+
larger than 65536. This is due to the amount of processing required to operate on large integers.
|
100
|
+
One bit of storage is required to hold all possible values a set may hold. Internally, a Bignum
|
101
|
+
instance is used to hold all the bits up to the highest ordinate value.
|
102
|
+
|
103
|
+
Sets can simplify many programming paradigms. Instead of writing code like this:
|
104
|
+
|
105
|
+
def valid_password_chars(str)
|
106
|
+
str.each_char do |ch|
|
107
|
+
return false unless (ch>='a' && ch <='z') || (ch>='A' && ch <='Z') || (ch>='0' && ch <='9') || (ch=='#') || (ch=='_') || (ch=='!')
|
108
|
+
end
|
109
|
+
return true
|
110
|
+
end
|
111
|
+
|
112
|
+
valid_password_chars "Not a valid password at all!" # false
|
113
|
+
valid_password_chars "Secret#15_!" # true
|
114
|
+
|
115
|
+
You can instead do this:
|
116
|
+
|
117
|
+
valid_char_set = Set.new ['a'..'z','A'..'Z','0'..'9','#','_','!']
|
118
|
+
|
119
|
+
"Not a valid password at all!" <= valid_char_set # false
|
120
|
+
"Secret#15_!" <= valid_char_set # true
|
121
|
+
|
122
|
+
Depending on the operator, the string expression above is converted in to a set instance.
|
123
|
+
Fast bitwise math is then performed internally.
|
124
|
+
|
125
|
+
Sets can often offer improved performance over regular expressions and arrays.
|
126
|
+
This is possible thanks to very fast bit-wise operations on its internal Bignum representation.
|
127
|
+
Each bit represents a placeholder for a possible element.
|
128
|
+
|
129
|
+
Sets can be used within case statements. The entire case statement can be configured to use
|
130
|
+
one of six different comparison modes. The case variable defines the modes of operation for the entire case statement.
|
131
|
+
An alternate configuration is to set the same comparison modes on each when clause.
|
132
|
+
Note that the case variable takes precedence over each and every when clause.
|
133
|
+
The case variable must be of type `Set`. The left side of the comparison is always the case variable.
|
134
|
+
An example is as follows:
|
135
|
+
|
136
|
+
case [2,4,6..13].to_set.set_case(:mode_sub)
|
137
|
+
when [1..31]
|
138
|
+
puts "subset detected!"
|
139
|
+
end
|
140
|
+
|
141
|
+
In ruby, case statements use the `===` operator when evaluating the when clause.
|
142
|
+
The `case` variable sits on the left, and the `when` clause sits on the right.
|
143
|
+
The Set class overloads the `===` operator and decides what operations are performed on
|
144
|
+
the left and right side of the operator. The `#set_case` method takes one of six symbol
|
145
|
+
arguments to perform one of 6 comparison modes.
|
146
|
+
Comparison modes can be set on either the left or the right, but the right takes precedence.
|
147
|
+
|
148
|
+
## Contributing
|
149
|
+
|
150
|
+
1. Fork it
|
151
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
152
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
153
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
154
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/lib/setfu.rb
ADDED
@@ -0,0 +1,494 @@
|
|
1
|
+
require "setfu/version"
|
2
|
+
|
3
|
+
class Set
|
4
|
+
attr_reader :entropy
|
5
|
+
|
6
|
+
def entropy=(ent) # entropy only gets bigger, just like the universe!
|
7
|
+
@entropy = ent unless @entropy > ent
|
8
|
+
end
|
9
|
+
|
10
|
+
def mode
|
11
|
+
return @mode
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(data=nil)
|
15
|
+
@bits = 0
|
16
|
+
@entropy = 0
|
17
|
+
add!(data) unless data.nil?
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
def zap!
|
22
|
+
@bits = 0
|
23
|
+
@entropy = 0
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def recalculate_entropy!
|
28
|
+
@entropy = 0
|
29
|
+
bits = @bits
|
30
|
+
num = 1 << 8192
|
31
|
+
while(bits > num)
|
32
|
+
@entropy += 8192
|
33
|
+
bits >>= 8192
|
34
|
+
end
|
35
|
+
num = 1 << 256
|
36
|
+
while(bits > num)
|
37
|
+
@entropy += 256
|
38
|
+
bits >>= 256
|
39
|
+
end
|
40
|
+
num = 1 << 16
|
41
|
+
while(bits > num)
|
42
|
+
@entropy += 16
|
43
|
+
bits >>= 16
|
44
|
+
end
|
45
|
+
while(bits > 0)
|
46
|
+
@entropy += 1
|
47
|
+
bits >>= 1
|
48
|
+
end
|
49
|
+
#@entropy += 1
|
50
|
+
@entropy
|
51
|
+
end
|
52
|
+
|
53
|
+
def add_parse_chars!
|
54
|
+
add [0..47, 58..64, 91..96, 123..126]
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
# this only works on integer ... String, Array, Range does not implement: &, |, ^
|
59
|
+
def coerce(other)
|
60
|
+
#puts "TESTING ... coerce called!"
|
61
|
+
return [self, other] # does not seem to get called ...
|
62
|
+
end
|
63
|
+
|
64
|
+
def dup
|
65
|
+
rtn = Set.new
|
66
|
+
rtn.set_bits!(@bits)
|
67
|
+
rtn
|
68
|
+
end
|
69
|
+
|
70
|
+
def ^(item)
|
71
|
+
rtn = self.dup
|
72
|
+
if(item.class==Set)
|
73
|
+
rtn.set_bits!(rtn.to_i ^ item.to_i)
|
74
|
+
else
|
75
|
+
rtn = Set.new(item)
|
76
|
+
rtn.set_bits!(@bits ^ rtn.to_i)
|
77
|
+
end
|
78
|
+
rtn
|
79
|
+
end
|
80
|
+
|
81
|
+
def |(item)
|
82
|
+
rtn = self.dup
|
83
|
+
if(item.class==Set)
|
84
|
+
rtn.set_bits!(rtn.to_i | item.to_i)
|
85
|
+
self.entropy=item.entropy
|
86
|
+
else
|
87
|
+
rtn = Set.new(item)
|
88
|
+
rtn.set_bits!(@bits | rtn.to_i)
|
89
|
+
end
|
90
|
+
rtn
|
91
|
+
end
|
92
|
+
|
93
|
+
def &(item)
|
94
|
+
rtn = self.dup
|
95
|
+
if(item.class==Set)
|
96
|
+
rtn.set_bits!(rtn.to_i & item.to_i)
|
97
|
+
else
|
98
|
+
rtn = Set.new(item)
|
99
|
+
rtn.set_bits!(@bits & rtn.to_i)
|
100
|
+
end
|
101
|
+
rtn
|
102
|
+
end
|
103
|
+
|
104
|
+
def -(item)
|
105
|
+
rtn = Set.new
|
106
|
+
rtn.entropy = self.entropy
|
107
|
+
a = self.to_i
|
108
|
+
if(item.class==Set)
|
109
|
+
b = item.to_i
|
110
|
+
rtn.entropy = item.entropy
|
111
|
+
else
|
112
|
+
b = Set.new(item)
|
113
|
+
rtn.entropy = b.entropy
|
114
|
+
b = b.to_i
|
115
|
+
end
|
116
|
+
c = a & b
|
117
|
+
d = c ^ a
|
118
|
+
rtn.set_bits!(d)
|
119
|
+
rtn
|
120
|
+
end
|
121
|
+
|
122
|
+
def **(item) # intersection test
|
123
|
+
set_item = Set.new(item)
|
124
|
+
return false if (self & set_item).empty?
|
125
|
+
return true
|
126
|
+
end
|
127
|
+
|
128
|
+
# comparison operators:
|
129
|
+
def ==(item)
|
130
|
+
if(item.class==Set)
|
131
|
+
rtn = item.to_i == self.to_i
|
132
|
+
else
|
133
|
+
rtn = Set.new(item).to_i == self.to_i
|
134
|
+
end
|
135
|
+
rtn
|
136
|
+
end
|
137
|
+
|
138
|
+
def !=(item)
|
139
|
+
if(item.class==Set)
|
140
|
+
rtn = item.to_i != self.to_i
|
141
|
+
else
|
142
|
+
rtn = Set.new(item).to_i != self.to_i
|
143
|
+
end
|
144
|
+
rtn
|
145
|
+
end
|
146
|
+
|
147
|
+
def set_case(mode=:mode_equal)
|
148
|
+
@mode = mode
|
149
|
+
self
|
150
|
+
end
|
151
|
+
|
152
|
+
def ===(item)
|
153
|
+
# self ... when clause ...
|
154
|
+
# item ... case clause ... case(item)
|
155
|
+
# Note: coerce does not work in this context ...
|
156
|
+
|
157
|
+
md = item.to_set.mode || @mode
|
158
|
+
|
159
|
+
case md
|
160
|
+
when :mode_intersection
|
161
|
+
return item ** self
|
162
|
+
when :mode_sub
|
163
|
+
return item <= self
|
164
|
+
when :mode_proper
|
165
|
+
return item < self
|
166
|
+
when :mode_super
|
167
|
+
return self <= item
|
168
|
+
when :mode_superproper
|
169
|
+
return self < item
|
170
|
+
else
|
171
|
+
return self == item
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def <=(item)
|
176
|
+
si = Set.new item
|
177
|
+
return si.include?(self)
|
178
|
+
end
|
179
|
+
|
180
|
+
def <(item)
|
181
|
+
si = Set.new item
|
182
|
+
return false if (si == self) # not a 'proper' subset
|
183
|
+
return si.include?(self)
|
184
|
+
end
|
185
|
+
|
186
|
+
def add!(items)
|
187
|
+
if(items.class==Set)
|
188
|
+
@bits |= items.to_i
|
189
|
+
entropy = items.entropy
|
190
|
+
elsif(items.class==Range)
|
191
|
+
f=items.first.ord
|
192
|
+
l=items.last.ord
|
193
|
+
f,l = l,f if f>l
|
194
|
+
t = (l-f)+1
|
195
|
+
t = (1 << t)-1
|
196
|
+
@bits |= t << f
|
197
|
+
self.entropy = l+1
|
198
|
+
elsif(items.respond_to? :each_char)
|
199
|
+
items.each_char do |item|
|
200
|
+
@bits |= 1 << item.ord
|
201
|
+
self.entropy = item.ord+1
|
202
|
+
end
|
203
|
+
elsif(items.respond_to? :each)
|
204
|
+
items.each do |item|
|
205
|
+
add! item
|
206
|
+
end
|
207
|
+
else #assume number
|
208
|
+
raise "negative numbers are not allowed" if items < 0
|
209
|
+
pos = 1 << items
|
210
|
+
@bits |= pos
|
211
|
+
self.entropy = items+1
|
212
|
+
end
|
213
|
+
self
|
214
|
+
end
|
215
|
+
|
216
|
+
def empty?
|
217
|
+
@bits == 0
|
218
|
+
end
|
219
|
+
|
220
|
+
def include?(items)
|
221
|
+
if(items.class==Set)
|
222
|
+
return (@bits & items.to_i) == items.to_i
|
223
|
+
elsif(items.class==Range)
|
224
|
+
f=items.first.ord
|
225
|
+
l=items.last.ord
|
226
|
+
f,l = l,f if f>l
|
227
|
+
t = (l-f)+1
|
228
|
+
t = (1 << t)-1
|
229
|
+
t = t << f
|
230
|
+
return (@bits & t) == t
|
231
|
+
elsif(items.respond_to? :each_char)
|
232
|
+
items.each_char do |item|
|
233
|
+
t = 1 << item.ord
|
234
|
+
return false if 0 == (t & @bits)
|
235
|
+
end
|
236
|
+
elsif(items.respond_to? :each)
|
237
|
+
items.each do |item|
|
238
|
+
return false if false==include?(item)
|
239
|
+
end
|
240
|
+
else #assume number
|
241
|
+
t = 1 << items.abs
|
242
|
+
return false if 0 == (t & @bits)
|
243
|
+
end
|
244
|
+
return true
|
245
|
+
end
|
246
|
+
|
247
|
+
def each_member
|
248
|
+
bits = @bits
|
249
|
+
pos = 0
|
250
|
+
while bits > 0
|
251
|
+
yield pos if ((bits & 1) == 1)
|
252
|
+
pos += 1
|
253
|
+
bits >>= 1
|
254
|
+
end
|
255
|
+
self
|
256
|
+
end
|
257
|
+
|
258
|
+
def to_i
|
259
|
+
return @bits
|
260
|
+
end
|
261
|
+
|
262
|
+
def count
|
263
|
+
cnt = 0
|
264
|
+
each_member do |toss|
|
265
|
+
cnt += 1
|
266
|
+
end
|
267
|
+
cnt
|
268
|
+
end
|
269
|
+
|
270
|
+
def to_s
|
271
|
+
rtn = ""
|
272
|
+
each_member do |ch|
|
273
|
+
rtn += ch.chr
|
274
|
+
end
|
275
|
+
rtn
|
276
|
+
end
|
277
|
+
|
278
|
+
def to_a
|
279
|
+
rtn = []
|
280
|
+
each_member do |num|
|
281
|
+
rtn.push num
|
282
|
+
end
|
283
|
+
rtn
|
284
|
+
end
|
285
|
+
|
286
|
+
def set_bits!(bits)
|
287
|
+
raise "negative numbers are not allowed" if bits.to_i < 0
|
288
|
+
@bits = bits.to_i
|
289
|
+
end
|
290
|
+
|
291
|
+
def ~@()
|
292
|
+
rtn = dup
|
293
|
+
mask = (1 << @entropy) - 1
|
294
|
+
rtn.set_bits!(mask ^ @bits)
|
295
|
+
rtn
|
296
|
+
end
|
297
|
+
|
298
|
+
def [](pos)
|
299
|
+
idx = pos.ord if pos.class==String
|
300
|
+
idx = pos.to_i
|
301
|
+
raise "Negative indexes are illegal for Set" if idx < 0
|
302
|
+
self.entropy = idx+1
|
303
|
+
y = @bits & (1<<idx)
|
304
|
+
return true if y > 0
|
305
|
+
false
|
306
|
+
end
|
307
|
+
|
308
|
+
def []=(pos,value)
|
309
|
+
idx = pos.ord if pos.class==String
|
310
|
+
idx = pos.to_i
|
311
|
+
raise "Negative indexes are illegal for Set" if idx < 0
|
312
|
+
state = value ? true : false
|
313
|
+
self.entropy = idx+1
|
314
|
+
if state # set bit
|
315
|
+
@bits |= 1 << idx
|
316
|
+
else # clear bit
|
317
|
+
mask = 1 << idx
|
318
|
+
@bits |= mask
|
319
|
+
@bits ^= mask
|
320
|
+
end
|
321
|
+
return state
|
322
|
+
end
|
323
|
+
|
324
|
+
def min
|
325
|
+
return nil if empty?
|
326
|
+
range = (self.entropy)..(0)
|
327
|
+
while((range.first - range.last) >= 2) do
|
328
|
+
mid = ((range.first - range.last) >> 1) + range.last
|
329
|
+
top = (range.first)..(mid)
|
330
|
+
bot = (mid)..(range.last)
|
331
|
+
range = self ** bot ? bot : top
|
332
|
+
end
|
333
|
+
#byebug
|
334
|
+
return range.last if (self[range.last])
|
335
|
+
range.first
|
336
|
+
end
|
337
|
+
|
338
|
+
def max #look from left
|
339
|
+
#byebug
|
340
|
+
return nil if empty?
|
341
|
+
range = (self.entropy)..(0)
|
342
|
+
while((range.first - range.last) >= 2) do
|
343
|
+
mid = ((range.first - range.last) >> 1) + range.last
|
344
|
+
top = (range.first)..(mid)
|
345
|
+
bot = (mid)..(range.last)
|
346
|
+
range = self ** top ? top : bot
|
347
|
+
end
|
348
|
+
#byebug
|
349
|
+
return range.first if (self[range.first])
|
350
|
+
range.last
|
351
|
+
end
|
352
|
+
end # end Set
|
353
|
+
|
354
|
+
module SetFuMixinBinaryAndOperator
|
355
|
+
def &(item)
|
356
|
+
a = Set.new(self)
|
357
|
+
b = Set.new(item)
|
358
|
+
return a & b
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
module SetFuMixinBinaryOrOperator
|
363
|
+
def |(item)
|
364
|
+
a = Set.new(self)
|
365
|
+
b = Set.new(item)
|
366
|
+
return a | b
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
module SetFuMixinBinaryXorOperator
|
371
|
+
def ^(item)
|
372
|
+
a = Set.new(self)
|
373
|
+
b = Set.new(item)
|
374
|
+
return a ^ b
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
module SetFuMixinBinaryIntersectionOperator
|
379
|
+
def **(item) # intersection test
|
380
|
+
a = Set.new(self)
|
381
|
+
b = Set.new(item)
|
382
|
+
return a ** b
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
module SetFuMixinToSetMethod
|
387
|
+
def to_set
|
388
|
+
rtn = Set.new(self)
|
389
|
+
# byebug
|
390
|
+
return rtn
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
module SetFuMixinTrippleEqualsOperator
|
395
|
+
alias_method :old_triple_equal4Set, :===
|
396
|
+
def ===(item)
|
397
|
+
return old_triple_equal4Set(item) unless (item.class==Set)
|
398
|
+
return self.to_set === item
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
module SetFuMixinBinarySubtractOperator
|
403
|
+
def -(item)
|
404
|
+
a = Set.new(self)
|
405
|
+
b = Set.new(item)
|
406
|
+
return a - b
|
407
|
+
end
|
408
|
+
end
|
409
|
+
|
410
|
+
module SetFuMixinBinarySubsetOperator
|
411
|
+
def <=(item)
|
412
|
+
a = Set.new(self)
|
413
|
+
b = Set.new(item)
|
414
|
+
return a <= b
|
415
|
+
end
|
416
|
+
end
|
417
|
+
|
418
|
+
module SetFuMixinBinaryProperOperator
|
419
|
+
def <(item)
|
420
|
+
a = Set.new(self)
|
421
|
+
b = Set.new(item)
|
422
|
+
return a < b
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
426
|
+
class String
|
427
|
+
alias_method :old_string_lt4set, :<
|
428
|
+
alias_method :old_string_lte4set, :<=
|
429
|
+
|
430
|
+
include SetFuMixinBinaryAndOperator
|
431
|
+
include SetFuMixinBinaryOrOperator
|
432
|
+
include SetFuMixinBinaryXorOperator
|
433
|
+
include SetFuMixinBinaryIntersectionOperator
|
434
|
+
include SetFuMixinToSetMethod
|
435
|
+
include SetFuMixinTrippleEqualsOperator
|
436
|
+
include SetFuMixinBinarySubtractOperator
|
437
|
+
|
438
|
+
def <=(item)
|
439
|
+
return old_string_lte4set(item) if (item.class==String)
|
440
|
+
a = Set.new(self)
|
441
|
+
b = Set.new(item)
|
442
|
+
return a <= b
|
443
|
+
end
|
444
|
+
def <(item)
|
445
|
+
return old_string_lt4set(item) if (item.class==String)
|
446
|
+
a = Set.new(self)
|
447
|
+
b = Set.new(item)
|
448
|
+
return a < b
|
449
|
+
end
|
450
|
+
end
|
451
|
+
|
452
|
+
class Array
|
453
|
+
alias_method :old_subtract_method4set, :-
|
454
|
+
alias_method :old_and_method4set, :&
|
455
|
+
alias_method :old_or_method4set, :|
|
456
|
+
|
457
|
+
include SetFuMixinBinaryXorOperator
|
458
|
+
include SetFuMixinBinaryIntersectionOperator
|
459
|
+
include SetFuMixinToSetMethod
|
460
|
+
include SetFuMixinTrippleEqualsOperator
|
461
|
+
include SetFuMixinBinarySubsetOperator
|
462
|
+
include SetFuMixinBinaryProperOperator
|
463
|
+
|
464
|
+
def -(item)
|
465
|
+
return old_subtract_method4set(item) if (item.class==Array)
|
466
|
+
a = Set.new(self)
|
467
|
+
b = Set.new(item)
|
468
|
+
return a - b
|
469
|
+
end
|
470
|
+
def &(item)
|
471
|
+
return old_and_method4set(item) if (item.class==Array)
|
472
|
+
a = Set.new(self)
|
473
|
+
b = Set.new(item)
|
474
|
+
return a & b
|
475
|
+
end
|
476
|
+
def |(item)
|
477
|
+
return old_or_method4set(item) if (item.class==Array)
|
478
|
+
a = Set.new(self)
|
479
|
+
b = Set.new(item)
|
480
|
+
return a | b
|
481
|
+
end
|
482
|
+
end
|
483
|
+
|
484
|
+
class Range
|
485
|
+
include SetFuMixinBinaryAndOperator
|
486
|
+
include SetFuMixinBinaryOrOperator
|
487
|
+
include SetFuMixinBinaryXorOperator
|
488
|
+
include SetFuMixinBinaryIntersectionOperator
|
489
|
+
include SetFuMixinToSetMethod
|
490
|
+
include SetFuMixinTrippleEqualsOperator
|
491
|
+
include SetFuMixinBinarySubtractOperator
|
492
|
+
include SetFuMixinBinarySubsetOperator
|
493
|
+
include SetFuMixinBinaryProperOperator
|
494
|
+
end
|
data/setfu.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'setfu/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "setfu"
|
8
|
+
spec.version = Setfu::VERSION
|
9
|
+
spec.authors = ["Bryan Colvin"]
|
10
|
+
spec.email = ["bryan@bdlsys.com"]
|
11
|
+
spec.description = %q{
|
12
|
+
Creates a Set class with methods that allow you to construct and opperate on
|
13
|
+
set instances. A 'Bignum' instance is used internally to store each element
|
14
|
+
of the set. This allows very fast operations when comparing two set instances.
|
15
|
+
Member elements can be represented as positive small integers, or characters.
|
16
|
+
Sets can be constructed with integers, strings, characters, ranges, and arrays.
|
17
|
+
When characters are used, the ordinate value sets the element bit of the internal Bignum.}
|
18
|
+
spec.summary = %q{Set class}
|
19
|
+
spec.homepage = ""
|
20
|
+
spec.license = "MIT"
|
21
|
+
|
22
|
+
spec.files = `git ls-files`.split($/)
|
23
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
24
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
25
|
+
spec.require_paths = ["lib"]
|
26
|
+
|
27
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
28
|
+
spec.add_development_dependency "rake"
|
29
|
+
spec.add_development_dependency 'rspec'
|
30
|
+
spec.add_development_dependency 'byebug'
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: setfu
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Bryan Colvin
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-10-13 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.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: byebug
|
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: |2-
|
70
|
+
|
71
|
+
Creates a Set class with methods that allow you to construct and opperate on
|
72
|
+
set instances. A 'Bignum' instance is used internally to store each element
|
73
|
+
of the set. This allows very fast operations when comparing two set instances.
|
74
|
+
Member elements can be represented as positive small integers, or characters.
|
75
|
+
Sets can be constructed with integers, strings, characters, ranges, and arrays.
|
76
|
+
When characters are used, the ordinate value sets the element bit of the internal Bignum.
|
77
|
+
email:
|
78
|
+
- bryan@bdlsys.com
|
79
|
+
executables: []
|
80
|
+
extensions: []
|
81
|
+
extra_rdoc_files: []
|
82
|
+
files:
|
83
|
+
- ".gitignore"
|
84
|
+
- Gemfile
|
85
|
+
- LICENSE.txt
|
86
|
+
- README.md
|
87
|
+
- Rakefile
|
88
|
+
- lib/setfu.rb
|
89
|
+
- lib/setfu/version.rb
|
90
|
+
- setfu.gemspec
|
91
|
+
homepage: ''
|
92
|
+
licenses:
|
93
|
+
- MIT
|
94
|
+
metadata: {}
|
95
|
+
post_install_message:
|
96
|
+
rdoc_options: []
|
97
|
+
require_paths:
|
98
|
+
- lib
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
requirements: []
|
110
|
+
rubyforge_project:
|
111
|
+
rubygems_version: 2.4.8
|
112
|
+
signing_key:
|
113
|
+
specification_version: 4
|
114
|
+
summary: Set class
|
115
|
+
test_files: []
|