fat_core 2.0.1 → 3.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 +4 -4
- data/.ruby-version +1 -1
- data/bin/console +14 -0
- data/fat_core.gemspec +1 -0
- data/lib/fat_core/all.rb +14 -0
- data/lib/fat_core/array.rb +29 -22
- data/lib/fat_core/big_decimal.rb +12 -0
- data/lib/fat_core/date.rb +951 -938
- data/lib/fat_core/enumerable.rb +19 -3
- data/lib/fat_core/hash.rb +48 -43
- data/lib/fat_core/kernel.rb +4 -2
- data/lib/fat_core/nil.rb +13 -13
- data/lib/fat_core/numeric.rb +82 -86
- data/lib/fat_core/range.rb +164 -160
- data/lib/fat_core/string.rb +247 -242
- data/lib/fat_core/symbol.rb +17 -11
- data/lib/fat_core/version.rb +2 -2
- data/lib/fat_core.rb +0 -21
- data/spec/lib/array_spec.rb +2 -0
- data/spec/lib/big_decimal_spec.rb +7 -0
- data/spec/lib/date_spec.rb +7 -26
- data/spec/lib/enumerable_spec.rb +26 -1
- data/spec/lib/hash_spec.rb +2 -0
- data/spec/lib/kernel_spec.rb +2 -0
- data/spec/lib/nil_spec.rb +6 -0
- data/spec/lib/numeric_spec.rb +1 -5
- data/spec/lib/range_spec.rb +1 -1
- data/spec/lib/string_spec.rb +1 -6
- data/spec/lib/symbol_spec.rb +1 -1
- data/spec/spec_helper.rb +0 -2
- metadata +9 -8
- data/lib/fat_core/boolean.rb +0 -25
- data/lib/fat_core/latex_eruby.rb +0 -11
- data/lib/fat_core/period.rb +0 -533
- data/spec/lib/period_spec.rb +0 -677
data/lib/fat_core/range.rb
CHANGED
@@ -1,194 +1,198 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
1
|
+
module FatCore
|
2
|
+
module Range
|
3
|
+
# Return a range that concatenates this range with other; return nil
|
4
|
+
# if the ranges are not contiguous.
|
5
|
+
def join(other)
|
6
|
+
if left_contiguous?(other)
|
7
|
+
::Range.new(min, other.max)
|
8
|
+
elsif right_contiguous?(other)
|
9
|
+
::Range.new(other.min, max)
|
10
|
+
end
|
9
11
|
end
|
10
|
-
end
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
# Is self on the left of and contiguous to other?
|
14
|
+
def left_contiguous?(other)
|
15
|
+
if max.respond_to?(:succ)
|
16
|
+
max.succ == other.min
|
17
|
+
else
|
18
|
+
max == other.min
|
19
|
+
end
|
18
20
|
end
|
19
|
-
end
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
22
|
+
# Is self on the right of and contiguous to other?
|
23
|
+
def right_contiguous?(other)
|
24
|
+
if other.max.respond_to?(:succ)
|
25
|
+
other.max.succ == min
|
26
|
+
else
|
27
|
+
other.max == min
|
28
|
+
end
|
27
29
|
end
|
28
|
-
end
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
31
|
+
def contiguous?(other)
|
32
|
+
left_contiguous?(other) || right_contiguous?(other)
|
33
|
+
end
|
33
34
|
|
34
|
-
|
35
|
-
|
36
|
-
|
35
|
+
def subset_of?(other)
|
36
|
+
min >= other.min && max <= other.max
|
37
|
+
end
|
37
38
|
|
38
|
-
|
39
|
-
|
40
|
-
|
39
|
+
def proper_subset_of?(other)
|
40
|
+
min > other.min && max < other.max
|
41
|
+
end
|
41
42
|
|
42
|
-
|
43
|
-
|
44
|
-
|
43
|
+
def superset_of?(other)
|
44
|
+
min <= other.min && max >= other.max
|
45
|
+
end
|
45
46
|
|
46
|
-
|
47
|
-
|
48
|
-
|
47
|
+
def proper_superset_of?(other)
|
48
|
+
min < other.min && max > other.max
|
49
|
+
end
|
49
50
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
51
|
+
def overlaps?(other)
|
52
|
+
(cover?(other.min) || cover?(other.max) ||
|
53
|
+
other.cover?(min) || other.cover?(max))
|
54
|
+
end
|
54
55
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
56
|
+
def intersection(other)
|
57
|
+
return nil unless overlaps?(other)
|
58
|
+
([min, other.min].max..[max, other.max].min)
|
59
|
+
end
|
60
|
+
alias & intersection
|
60
61
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
end
|
65
|
-
alias + union
|
66
|
-
|
67
|
-
# The difference method, -, removes the overlapping part of the other
|
68
|
-
# argument from self. Because in the case where self is a superset of the
|
69
|
-
# other range, this will result in the difference being two non-contiguous
|
70
|
-
# ranges, this returns an array of ranges. If there is no overlap or if
|
71
|
-
# self is a subset of the other range, return an array of self
|
72
|
-
def difference(other)
|
73
|
-
unless max.respond_to?(:succ) && min.respond_to?(:pred) &&
|
74
|
-
other.max.respond_to?(:succ) && other.min.respond_to?(:pred)
|
75
|
-
raise 'Range difference requires objects have pred and succ methods'
|
76
|
-
end
|
77
|
-
if subset_of?(other)
|
78
|
-
# (4..7) - (0..10)
|
79
|
-
[]
|
80
|
-
elsif proper_superset_of?(other)
|
81
|
-
# (4..7) - (5..5) -> [(4..4), (6..7)]
|
82
|
-
[(min..other.min.pred), (other.max.succ..max)]
|
83
|
-
elsif overlaps?(other) && other.min <= min
|
84
|
-
# (4..7) - (2..5) -> (6..7)
|
85
|
-
[(other.max.succ..max)]
|
86
|
-
elsif overlaps?(other) && other.max >= max
|
87
|
-
# (4..7) - (6..10) -> (4..5)
|
88
|
-
[(min..other.min.pred)]
|
89
|
-
else
|
90
|
-
[self]
|
62
|
+
def union(other)
|
63
|
+
return nil unless overlaps?(other) || contiguous?(other)
|
64
|
+
([min, other.min].min..[max, other.max].max)
|
91
65
|
end
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
66
|
+
alias + union
|
67
|
+
|
68
|
+
# The difference method, -, removes the overlapping part of the other
|
69
|
+
# argument from self. Because in the case where self is a superset of the
|
70
|
+
# other range, this will result in the difference being two non-contiguous
|
71
|
+
# ranges, this returns an array of ranges. If there is no overlap or if
|
72
|
+
# self is a subset of the other range, return an array of self
|
73
|
+
def difference(other)
|
74
|
+
unless max.respond_to?(:succ) && min.respond_to?(:pred) &&
|
75
|
+
other.max.respond_to?(:succ) && other.min.respond_to?(:pred)
|
76
|
+
raise 'Range difference requires objects have pred and succ methods'
|
77
|
+
end
|
78
|
+
if subset_of?(other)
|
79
|
+
# (4..7) - (0..10)
|
80
|
+
[]
|
81
|
+
elsif proper_superset_of?(other)
|
82
|
+
# (4..7) - (5..5) -> [(4..4), (6..7)]
|
83
|
+
[(min..other.min.pred), (other.max.succ..max)]
|
84
|
+
elsif overlaps?(other) && other.min <= min
|
85
|
+
# (4..7) - (2..5) -> (6..7)
|
86
|
+
[(other.max.succ..max)]
|
87
|
+
elsif overlaps?(other) && other.max >= max
|
88
|
+
# (4..7) - (6..10) -> (4..5)
|
89
|
+
[(min..other.min.pred)]
|
90
|
+
else
|
91
|
+
[self]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
alias - difference
|
95
|
+
|
96
|
+
# Return whether any of the ranges that are within self overlap one
|
97
|
+
# another
|
98
|
+
def has_overlaps_within?(ranges)
|
99
|
+
result = false
|
100
|
+
unless ranges.empty?
|
101
|
+
ranges.each do |r1|
|
102
|
+
next unless overlaps?(r1)
|
103
|
+
result =
|
104
|
+
ranges.any? do |r2|
|
104
105
|
r1.object_id != r2.object_id && overlaps?(r2) &&
|
105
106
|
r1.overlaps?(r2)
|
106
107
|
end
|
107
|
-
|
108
|
+
return true if result
|
109
|
+
end
|
108
110
|
end
|
111
|
+
result
|
109
112
|
end
|
110
|
-
result
|
111
|
-
end
|
112
113
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
114
|
+
# Return true if the given ranges collectively cover this range
|
115
|
+
# without overlaps.
|
116
|
+
def spanned_by?(ranges)
|
117
|
+
joined_range = nil
|
118
|
+
ranges.sort_by(&:min).each do |r|
|
119
|
+
unless joined_range
|
120
|
+
joined_range = r
|
121
|
+
next
|
122
|
+
end
|
123
|
+
joined_range = joined_range.join(r)
|
124
|
+
break if joined_range.nil?
|
125
|
+
end
|
126
|
+
if !joined_range.nil?
|
127
|
+
joined_range.min <= min && joined_range.max >= max
|
128
|
+
else
|
129
|
+
false
|
121
130
|
end
|
122
|
-
joined_range = joined_range.join(r)
|
123
|
-
break if joined_range.nil?
|
124
|
-
end
|
125
|
-
if !joined_range.nil?
|
126
|
-
joined_range.min <= min && joined_range.max >= max
|
127
|
-
else
|
128
|
-
false
|
129
131
|
end
|
130
|
-
end
|
131
132
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
133
|
+
# If this range is not spanned by the ranges collectively, return an array
|
134
|
+
# of ranges representing the gaps in coverage. Otherwise return an empty
|
135
|
+
# array.
|
136
|
+
def gaps(ranges)
|
137
|
+
if ranges.empty?
|
138
|
+
[clone]
|
139
|
+
elsif spanned_by?(ranges)
|
140
|
+
[]
|
141
|
+
else
|
142
|
+
ranges = ranges.sort_by(&:min)
|
143
|
+
gaps = []
|
144
|
+
cur_point = min
|
145
|
+
ranges.each do |rr|
|
146
|
+
break if rr.min > max
|
147
|
+
if rr.min > cur_point
|
148
|
+
start_point = cur_point
|
149
|
+
end_point = rr.min.pred
|
150
|
+
gaps << (start_point..end_point)
|
151
|
+
cur_point = rr.max.succ
|
152
|
+
elsif rr.max >= cur_point
|
153
|
+
cur_point = rr.max.succ
|
154
|
+
end
|
153
155
|
end
|
156
|
+
gaps << (cur_point..max) if cur_point <= max
|
157
|
+
gaps
|
154
158
|
end
|
155
|
-
gaps << (cur_point..max) if cur_point <= max
|
156
|
-
gaps
|
157
159
|
end
|
158
|
-
end
|
159
160
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
161
|
+
# Similar to gaps, but within this range return the /overlaps/ among the
|
162
|
+
# given ranges. If there are no overlaps, return an empty array. Don't
|
163
|
+
# consider overlaps in the ranges that occur outside of self.
|
164
|
+
def overlaps(ranges)
|
165
|
+
if ranges.empty? || spanned_by?(ranges)
|
166
|
+
[]
|
167
|
+
else
|
168
|
+
ranges = ranges.sort_by(&:min)
|
169
|
+
overlaps = []
|
170
|
+
cur_point = nil
|
171
|
+
ranges.each do |rr|
|
172
|
+
# Skip ranges outside of self
|
173
|
+
next if rr.max < min || rr.min > max
|
174
|
+
# Initialize cur_point to max of first range
|
175
|
+
if cur_point.nil?
|
176
|
+
cur_point = rr.max
|
177
|
+
next
|
178
|
+
end
|
179
|
+
# We are on the second or later range
|
180
|
+
if rr.min < cur_point
|
181
|
+
start_point = rr.min
|
182
|
+
end_point = cur_point
|
183
|
+
overlaps << (start_point..end_point)
|
184
|
+
end
|
175
185
|
cur_point = rr.max
|
176
|
-
next
|
177
|
-
end
|
178
|
-
# We are on the second or later range
|
179
|
-
if rr.min < cur_point
|
180
|
-
start_point = rr.min
|
181
|
-
end_point = cur_point
|
182
|
-
overlaps << (start_point..end_point)
|
183
186
|
end
|
184
|
-
|
187
|
+
overlaps
|
185
188
|
end
|
186
|
-
overlaps
|
187
189
|
end
|
188
|
-
end
|
189
190
|
|
190
|
-
|
191
|
-
|
192
|
-
|
191
|
+
# Allow erb documents can directly interpolate ranges
|
192
|
+
def tex_quote
|
193
|
+
to_s
|
194
|
+
end
|
193
195
|
end
|
194
196
|
end
|
197
|
+
|
198
|
+
Range.include FatCore::Range
|