mendel 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.
@@ -0,0 +1,48 @@
1
+ require "priority_queue" # gem
2
+ require 'json'
3
+
4
+ # Wrapper to allow swapping implementations
5
+ module Mendel
6
+ class MinPriorityQueue
7
+
8
+ def initialize
9
+ self.wrapped_queue = PriorityQueue.new
10
+ end
11
+
12
+ def push(item, priority)
13
+ wrapped_queue.push(item, priority)
14
+ end
15
+
16
+ def pop
17
+ wrapped_queue.delete_min
18
+ end
19
+
20
+ def length
21
+ wrapped_queue.length
22
+ end
23
+
24
+ def dump
25
+ [].tap {|items|
26
+ items << pop while length > 0
27
+ }
28
+ end
29
+
30
+ def dump_json
31
+ JSON.dump(dump)
32
+ end
33
+
34
+ # TODO - make the load methods class methods
35
+ def load(items)
36
+ items.each do |item|
37
+ push(*item)
38
+ end
39
+ end
40
+
41
+ def load_json(json)
42
+ load(JSON.parse(json))
43
+ end
44
+
45
+ private
46
+ attr_accessor :wrapped_queue
47
+ end
48
+ end
@@ -0,0 +1,24 @@
1
+ require "mendel/combiner"
2
+
3
+ module Mendel
4
+ class ObservableCombiner
5
+ include Mendel::Combiner
6
+ include Observable
7
+
8
+ def queueable_item_for(coordinates)
9
+ super.tap {|combo| notify(:scored, combo) }
10
+ end
11
+
12
+ def pop_queue
13
+ super.tap { |pair|
14
+ return if pair.nil?
15
+ coords = pair[0].fetch('coordinates')
16
+ notify(:returned, {'coordinates' => coords, 'score' => pair[1]}) unless pair.nil?
17
+ }
18
+ end
19
+
20
+ def notify(*args)
21
+ changed && notify_observers(*args)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,3 @@
1
+ module Mendel
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,54 @@
1
+ require_relative 'base'
2
+ require 'colorize'
3
+
4
+ module Mendel
5
+ module Visualizers
6
+ class ASCII < Base
7
+
8
+ def initialize(*args)
9
+ super
10
+ @point_width = 8
11
+ end
12
+
13
+ def output
14
+ horizontal_space = ' '
15
+ output_lines = []
16
+ grid.each_with_index do |line, y|
17
+ x_label = axis_label_for(list1[y])
18
+ line_string = x_label
19
+ points_on_line = line.each_with_index.map { |column, x|
20
+ grid_point_for(*grid[y][x])
21
+ }
22
+ line_string.concat(points_on_line.join(horizontal_space))
23
+ output_lines.unshift(line_string)
24
+ end
25
+ y_labels = list2.map {|item| axis_label_for(item) }
26
+
27
+ footer_line = "#{fix_point_width('')}#{y_labels.join(horizontal_space)}"
28
+ output_lines = output_lines.join("\n\n\n")
29
+ output_lines.concat("\n#{footer_line}\n")
30
+ end
31
+
32
+ def axis_label_for(list_item)
33
+ fix_point_width(list_item.to_s)
34
+ end
35
+
36
+ def grid_point_for(status, score=nil)
37
+ case status
38
+ when :unscored then fix_point_width('')
39
+ when :scored then fix_point_width(score.to_s).green
40
+ when :returned then fix_point_width(score.to_s).blue
41
+ else raise UnknownPointType, status.inspect
42
+ end
43
+ end
44
+
45
+ def fix_point_width(string)
46
+ string[0...point_width].rjust(point_width, ' ')
47
+ end
48
+
49
+ private
50
+
51
+ attr_reader :point_width
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,41 @@
1
+ module Mendel
2
+ module Visualizers
3
+ class Base
4
+ attr_accessor :combiner, :list1, :list2
5
+ attr_reader :grid
6
+
7
+ def self.max_list_length
8
+ 10 # To be decided
9
+ end
10
+
11
+ def initialize(combiner)
12
+ self.combiner = combiner
13
+ combiner.add_observer(self)
14
+ lists = combiner.lists
15
+ check_list_validity(lists)
16
+ self.list1, self.list2 = lists
17
+ self.grid = Array.new(list1.size) { Array.new(list2.size, [:unscored]) }
18
+ end
19
+
20
+ def update(status, combo)
21
+ y, x = combo.fetch('coordinates')
22
+ score = combo.fetch('score')
23
+ grid[y][x] = [status, score]
24
+ end
25
+
26
+ private
27
+
28
+ attr_writer :grid
29
+
30
+ def check_list_validity(lists)
31
+ raise InvalidListCount, "Can only graph in 2 dimensions" unless lists.length == 2
32
+ raise ListsTooLarge, "Need to fit on screen" if lists.any? {|l| l.length > self.class.max_list_length }
33
+ end
34
+
35
+ InvalidListCount = Class.new(StandardError)
36
+ ListsTooLarge = Class.new(StandardError)
37
+
38
+ UnknownPointType = Class.new(StandardError)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'mendel/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "mendel"
8
+ spec.version = Mendel::VERSION
9
+ spec.authors = ["Nathan Long"]
10
+ spec.email = ["nathanmlong@gmail.com"]
11
+ spec.summary = %q{Mendel breeds the best combinations of lists that you provide.}
12
+ spec.description = %q{Mendel breeds the best combinations of N lists without building all possible combinations.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "PriorityQueue", "~> 0.1.2"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.5"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "rspec", "~> 3.4"
26
+ spec.add_development_dependency "pry", "~> 0.10"
27
+ spec.add_development_dependency "colorize", "~> 0.7.7"
28
+ end
@@ -0,0 +1,13 @@
1
+ EXAMPLE_INPUT = {
2
+ incrementing_integers: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100],
3
+
4
+ incrementing_decimals: [1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1, 8.1, 9.1, 10.1, 11.1, 12.1, 13.1, 14.1, 15.1, 16.1, 17.1, 18.1, 19.1, 20.1, 21.1, 22.1, 23.1, 24.1, 25.1, 26.1, 27.1, 28.1, 29.1, 30.1, 31.1, 32.1, 33.1, 34.1, 35.1, 36.1, 37.1, 38.1, 39.1, 40.1, 41.1, 42.1, 43.1, 44.1, 45.1, 46.1, 47.1, 48.1, 49.1, 50.1, 51.1, 52.1, 53.1, 54.1, 55.1, 56.1, 57.1, 58.1, 59.1, 60.1, 61.1, 62.1, 63.1, 64.1, 65.1, 66.1, 67.1, 68.1, 69.1, 70.1, 71.1, 72.1, 73.1, 74.1, 75.1, 76.1, 77.1, 78.1, 79.1, 80.1, 81.1, 82.1, 83.1, 84.1, 85.1, 86.1, 87.1, 88.1, 89.1, 90.1, 91.1, 92.1, 93.1, 94.1, 95.1, 96.1, 97.1, 98.1, 99.1, 100.1],
5
+
6
+ repeats: [1, 2, 3, 3, 4, 5, 5, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 33, 34, 35, 36, 36, 37, 38, 38, 38, 39, 40, 41, 41, 42, 43, 44, 44, 45, 46, 46, 47, 48, 49, 50, 50, 51, 52, 53, 54, 54, 55, 56, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 70, 71, 72, 73, 74, 75, 76, 77, 78, 78, 79, 80, 80, 81, 82, 83],
7
+
8
+ skips: [0, 2, 3, 4, 5, 7, 9, 10, 11, 12, 13, 15, 16, 17, 19, 20, 23, 24, 25, 26, 27, 29, 32, 33, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 49, 50, 51, 53, 54, 55, 56, 58, 59, 60, 62, 63, 64, 65, 66, 67, 68, 70, 71, 72, 73, 74, 75, 76, 78, 83, 87, 88, 90, 92, 94, 95, 99, 101, 102, 104, 105, 106, 107, 110, 111, 112, 114, 115, 116, 117, 119, 120, 121, 122, 125, 126, 127, 128, 130, 131, 133, 134, 135, 136, 137, 138, 139, 140, 145],
9
+
10
+ repeats_and_skips: [1, 2, 2, 9, 11, 11, 13, 14, 15, 16, 17, 17, 18, 20, 20, 22, 23, 24, 24, 25, 26, 26, 26, 30, 30, 32, 33, 34, 34, 35, 35, 35, 35, 37, 38, 39, 39, 39, 40, 40, 41, 42, 42, 44, 44, 45, 46, 46, 46, 48, 49, 50, 50, 51, 52, 53, 54, 55, 57, 57, 61, 61, 62, 66, 66, 69, 72, 73, 73, 74, 76, 76, 77, 79, 82, 82, 82, 83, 83, 85, 87, 88, 88, 91, 91, 92, 92, 92, 93, 93, 93, 94, 95, 95, 95, 97, 97, 98, 98, 98],
11
+
12
+ short_list: [1, 2, 3],
13
+ }
@@ -0,0 +1,303 @@
1
+ $different_lengths =
2
+ [
3
+ [[1, 1], 2],
4
+ [[1, 2], 3],
5
+ [[2, 1], 3],
6
+ [[1, 3], 4],
7
+ [[3, 1], 4],
8
+ [[2, 2], 4],
9
+ [[2, 3], 5],
10
+ [[4, 1], 5],
11
+ [[3, 2], 5],
12
+ [[3, 3], 6],
13
+ [[4, 2], 6],
14
+ [[5, 1], 6],
15
+ [[6, 1], 7],
16
+ [[5, 2], 7],
17
+ [[4, 3], 7],
18
+ [[5, 3], 8],
19
+ [[6, 2], 8],
20
+ [[7, 1], 8],
21
+ [[6, 3], 9],
22
+ [[8, 1], 9],
23
+ [[7, 2], 9],
24
+ [[9, 1], 10],
25
+ [[8, 2], 10],
26
+ [[7, 3], 10],
27
+ [[8, 3], 11],
28
+ [[9, 2], 11],
29
+ [[10, 1], 11],
30
+ [[9, 3], 12],
31
+ [[11, 1], 12],
32
+ [[10, 2], 12],
33
+ [[12, 1], 13],
34
+ [[11, 2], 13],
35
+ [[10, 3], 13],
36
+ [[13, 1], 14],
37
+ [[12, 2], 14],
38
+ [[11, 3], 14],
39
+ [[12, 3], 15],
40
+ [[13, 2], 15],
41
+ [[14, 1], 15],
42
+ [[15, 1], 16],
43
+ [[14, 2], 16],
44
+ [[13, 3], 16],
45
+ [[14, 3], 17],
46
+ [[15, 2], 17],
47
+ [[16, 1], 17],
48
+ [[15, 3], 18],
49
+ [[17, 1], 18],
50
+ [[16, 2], 18],
51
+ [[18, 1], 19],
52
+ [[17, 2], 19],
53
+ [[16, 3], 19],
54
+ [[17, 3], 20],
55
+ [[19, 1], 20],
56
+ [[18, 2], 20],
57
+ [[18, 3], 21],
58
+ [[19, 2], 21],
59
+ [[20, 1], 21],
60
+ [[19, 3], 22],
61
+ [[21, 1], 22],
62
+ [[20, 2], 22],
63
+ [[22, 1], 23],
64
+ [[21, 2], 23],
65
+ [[20, 3], 23],
66
+ [[21, 3], 24],
67
+ [[22, 2], 24],
68
+ [[23, 1], 24],
69
+ [[22, 3], 25],
70
+ [[24, 1], 25],
71
+ [[23, 2], 25],
72
+ [[23, 3], 26],
73
+ [[25, 1], 26],
74
+ [[24, 2], 26],
75
+ [[24, 3], 27],
76
+ [[25, 2], 27],
77
+ [[26, 1], 27],
78
+ [[27, 1], 28],
79
+ [[26, 2], 28],
80
+ [[25, 3], 28],
81
+ [[26, 3], 29],
82
+ [[27, 2], 29],
83
+ [[28, 1], 29],
84
+ [[27, 3], 30],
85
+ [[29, 1], 30],
86
+ [[28, 2], 30],
87
+ [[30, 1], 31],
88
+ [[29, 2], 31],
89
+ [[28, 3], 31],
90
+ [[29, 3], 32],
91
+ [[31, 1], 32],
92
+ [[30, 2], 32],
93
+ [[30, 3], 33],
94
+ [[31, 2], 33],
95
+ [[32, 1], 33],
96
+ [[31, 3], 34],
97
+ [[33, 1], 34],
98
+ [[32, 2], 34],
99
+ [[32, 3], 35],
100
+ [[34, 1], 35],
101
+ [[33, 2], 35],
102
+ [[33, 3], 36],
103
+ [[34, 2], 36],
104
+ [[35, 1], 36],
105
+ [[34, 3], 37],
106
+ [[36, 1], 37],
107
+ [[35, 2], 37],
108
+ [[37, 1], 38],
109
+ [[36, 2], 38],
110
+ [[35, 3], 38],
111
+ [[38, 1], 39],
112
+ [[37, 2], 39],
113
+ [[36, 3], 39],
114
+ [[37, 3], 40],
115
+ [[38, 2], 40],
116
+ [[39, 1], 40],
117
+ [[40, 1], 41],
118
+ [[39, 2], 41],
119
+ [[38, 3], 41],
120
+ [[39, 3], 42],
121
+ [[40, 2], 42],
122
+ [[41, 1], 42],
123
+ [[40, 3], 43],
124
+ [[42, 1], 43],
125
+ [[41, 2], 43],
126
+ [[43, 1], 44],
127
+ [[42, 2], 44],
128
+ [[41, 3], 44],
129
+ [[44, 1], 45],
130
+ [[43, 2], 45],
131
+ [[42, 3], 45],
132
+ [[43, 3], 46],
133
+ [[44, 2], 46],
134
+ [[45, 1], 46],
135
+ [[44, 3], 47],
136
+ [[46, 1], 47],
137
+ [[45, 2], 47],
138
+ [[45, 3], 48],
139
+ [[46, 2], 48],
140
+ [[47, 1], 48],
141
+ [[46, 3], 49],
142
+ [[48, 1], 49],
143
+ [[47, 2], 49],
144
+ [[47, 3], 50],
145
+ [[49, 1], 50],
146
+ [[48, 2], 50],
147
+ [[48, 3], 51],
148
+ [[49, 2], 51],
149
+ [[50, 1], 51],
150
+ [[49, 3], 52],
151
+ [[50, 2], 52],
152
+ [[51, 1], 52],
153
+ [[50, 3], 53],
154
+ [[51, 2], 53],
155
+ [[52, 1], 53],
156
+ [[51, 3], 54],
157
+ [[53, 1], 54],
158
+ [[52, 2], 54],
159
+ [[54, 1], 55],
160
+ [[53, 2], 55],
161
+ [[52, 3], 55],
162
+ [[53, 3], 56],
163
+ [[55, 1], 56],
164
+ [[54, 2], 56],
165
+ [[54, 3], 57],
166
+ [[55, 2], 57],
167
+ [[56, 1], 57],
168
+ [[55, 3], 58],
169
+ [[57, 1], 58],
170
+ [[56, 2], 58],
171
+ [[56, 3], 59],
172
+ [[58, 1], 59],
173
+ [[57, 2], 59],
174
+ [[57, 3], 60],
175
+ [[58, 2], 60],
176
+ [[59, 1], 60],
177
+ [[58, 3], 61],
178
+ [[60, 1], 61],
179
+ [[59, 2], 61],
180
+ [[61, 1], 62],
181
+ [[60, 2], 62],
182
+ [[59, 3], 62],
183
+ [[62, 1], 63],
184
+ [[61, 2], 63],
185
+ [[60, 3], 63],
186
+ [[61, 3], 64],
187
+ [[62, 2], 64],
188
+ [[63, 1], 64],
189
+ [[62, 3], 65],
190
+ [[64, 1], 65],
191
+ [[63, 2], 65],
192
+ [[63, 3], 66],
193
+ [[64, 2], 66],
194
+ [[65, 1], 66],
195
+ [[64, 3], 67],
196
+ [[66, 1], 67],
197
+ [[65, 2], 67],
198
+ [[67, 1], 68],
199
+ [[66, 2], 68],
200
+ [[65, 3], 68],
201
+ [[66, 3], 69],
202
+ [[68, 1], 69],
203
+ [[67, 2], 69],
204
+ [[67, 3], 70],
205
+ [[68, 2], 70],
206
+ [[69, 1], 70],
207
+ [[68, 3], 71],
208
+ [[70, 1], 71],
209
+ [[69, 2], 71],
210
+ [[71, 1], 72],
211
+ [[70, 2], 72],
212
+ [[69, 3], 72],
213
+ [[70, 3], 73],
214
+ [[71, 2], 73],
215
+ [[72, 1], 73],
216
+ [[71, 3], 74],
217
+ [[73, 1], 74],
218
+ [[72, 2], 74],
219
+ [[72, 3], 75],
220
+ [[74, 1], 75],
221
+ [[73, 2], 75],
222
+ [[73, 3], 76],
223
+ [[74, 2], 76],
224
+ [[75, 1], 76],
225
+ [[74, 3], 77],
226
+ [[75, 2], 77],
227
+ [[76, 1], 77],
228
+ [[75, 3], 78],
229
+ [[76, 2], 78],
230
+ [[77, 1], 78],
231
+ [[76, 3], 79],
232
+ [[78, 1], 79],
233
+ [[77, 2], 79],
234
+ [[79, 1], 80],
235
+ [[78, 2], 80],
236
+ [[77, 3], 80],
237
+ [[78, 3], 81],
238
+ [[80, 1], 81],
239
+ [[79, 2], 81],
240
+ [[79, 3], 82],
241
+ [[80, 2], 82],
242
+ [[81, 1], 82],
243
+ [[80, 3], 83],
244
+ [[82, 1], 83],
245
+ [[81, 2], 83],
246
+ [[81, 3], 84],
247
+ [[83, 1], 84],
248
+ [[82, 2], 84],
249
+ [[82, 3], 85],
250
+ [[83, 2], 85],
251
+ [[84, 1], 85],
252
+ [[83, 3], 86],
253
+ [[85, 1], 86],
254
+ [[84, 2], 86],
255
+ [[86, 1], 87],
256
+ [[85, 2], 87],
257
+ [[84, 3], 87],
258
+ [[87, 1], 88],
259
+ [[86, 2], 88],
260
+ [[85, 3], 88],
261
+ [[86, 3], 89],
262
+ [[87, 2], 89],
263
+ [[88, 1], 89],
264
+ [[87, 3], 90],
265
+ [[89, 1], 90],
266
+ [[88, 2], 90],
267
+ [[88, 3], 91],
268
+ [[89, 2], 91],
269
+ [[90, 1], 91],
270
+ [[89, 3], 92],
271
+ [[91, 1], 92],
272
+ [[90, 2], 92],
273
+ [[92, 1], 93],
274
+ [[91, 2], 93],
275
+ [[90, 3], 93],
276
+ [[93, 1], 94],
277
+ [[92, 2], 94],
278
+ [[91, 3], 94],
279
+ [[92, 3], 95],
280
+ [[93, 2], 95],
281
+ [[94, 1], 95],
282
+ [[93, 3], 96],
283
+ [[94, 2], 96],
284
+ [[95, 1], 96],
285
+ [[94, 3], 97],
286
+ [[95, 2], 97],
287
+ [[96, 1], 97],
288
+ [[95, 3], 98],
289
+ [[97, 1], 98],
290
+ [[96, 2], 98],
291
+ [[96, 3], 99],
292
+ [[97, 2], 99],
293
+ [[98, 1], 99],
294
+ [[97, 3], 100],
295
+ [[98, 2], 100],
296
+ [[99, 1], 100],
297
+ [[98, 3], 101],
298
+ [[100, 1], 101],
299
+ [[99, 2], 101],
300
+ [[99, 3], 102],
301
+ [[100, 2], 102],
302
+ [[100, 3], 103],
303
+ ]