binary_puzzle_solver 0.0.1

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,582 @@
1
+ # Copyright (c) 2012 Shlomi Fish
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person
4
+ # obtaining a copy of this software and associated documentation
5
+ # files (the "Software"), to deal in the Software without
6
+ # restriction, including without limitation the rights to use,
7
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the
9
+ # Software is furnished to do so, subject to the following
10
+ # conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ # OTHER DEALINGS IN THE SOFTWARE.
23
+ #
24
+ # ----------------------------------------------------------------------------
25
+ #
26
+ # This is the MIT/X11 Licence. For more information see:
27
+ #
28
+ # 1. http://www.opensource.org/licenses/mit-license.php
29
+ #
30
+ # 2. http://en.wikipedia.org/wiki/MIT_License
31
+
32
+ require "binary_puzzle_solver.rb"
33
+ require "rspec"
34
+ require "pry"
35
+
36
+ class Object
37
+ def ok()
38
+ self.should == true
39
+ end
40
+ def not_ok()
41
+ self.should == false
42
+ end
43
+ end
44
+
45
+ def compare_boards(got, expected)
46
+ got.max_idx(:x).should == expected.max_idx(:x)
47
+ got.max_idx(:y).should == expected.max_idx(:y)
48
+
49
+ (0 .. got.max_idx(:y)).each do |y|
50
+ (0 .. got.max_idx(:x)).each do |x|
51
+ coord = Binary_Puzzle_Solver::Coord.new(:x => x, :y => y)
52
+ begin
53
+ got.get_cell_state(coord).should == expected.get_cell_state(coord)
54
+ rescue
55
+ puts "Wrong coord in x=#{x} y=#{y}"
56
+ puts "Got == #{got.as_string()}"
57
+ puts "Expected == #{expected.as_string()}"
58
+ raise
59
+ end
60
+ end
61
+ end
62
+
63
+ return
64
+ end
65
+
66
+ def get_6x6_easy_board_1()
67
+ input_str = <<'EOF'
68
+ |1 0 |
69
+ | 00 1|
70
+ | 00 1|
71
+ | |
72
+ |00 1 |
73
+ | 1 00|
74
+ EOF
75
+ return Binary_Puzzle_Solver.gen_board_from_string_v1(input_str)
76
+ end
77
+
78
+ def get_6x6_easy_board_1__intermediate_board()
79
+ str = <<'EOF'
80
+ |101010|
81
+ |010011|
82
+ |100101|
83
+ |011010|
84
+ |001101|
85
+ |110100|
86
+ EOF
87
+ return Binary_Puzzle_Solver.gen_board_from_string_v1(str)
88
+ end
89
+
90
+ def get_6x6_easy_board_2()
91
+ input_str = <<'EOF'
92
+ | 0 1|
93
+ |1 00 |
94
+ | 1 |
95
+ | 1 |
96
+ | 1 0|
97
+ |00 1 |
98
+ EOF
99
+ return Binary_Puzzle_Solver.gen_board_from_string_v1(input_str)
100
+ end
101
+
102
+ def get_6x6_easy_board_2__intermediate_board()
103
+ input_str = <<'EOF'
104
+ |100101|
105
+ |110010|
106
+ |011001|
107
+ |100110|
108
+ |011010|
109
+ |001101|
110
+ EOF
111
+ return Binary_Puzzle_Solver.gen_board_from_string_v1(input_str)
112
+ end
113
+
114
+ def get_6x6_medium_board_1()
115
+ input_str = <<'EOF'
116
+ | 00|
117
+ | |
118
+ | 1 |
119
+ |01 1 |
120
+ |0 0 |
121
+ | 1 |
122
+ EOF
123
+ return Binary_Puzzle_Solver.gen_board_from_string_v1(input_str)
124
+ end
125
+
126
+ def get_6x6_medium_board_1__after_easy_moves()
127
+ input_str = <<'EOF'
128
+ | 100|
129
+ | 01 |
130
+ |110 |
131
+ |0101 |
132
+ |001 0 |
133
+ |101 |
134
+ EOF
135
+ return Binary_Puzzle_Solver.gen_board_from_string_v1(input_str)
136
+ end
137
+
138
+ def get_6x6_medium_board_1__after_cells_of_one_value_in_row_were_all_found()
139
+ input_str = <<'EOF'
140
+ |110100|
141
+ |001011|
142
+ |1100 |
143
+ |0101 |
144
+ |001101|
145
+ |1010 |
146
+ EOF
147
+ return Binary_Puzzle_Solver.gen_board_from_string_v1(input_str)
148
+ end
149
+
150
+ def get_6x6_medium_board_1__final()
151
+ input_str = <<'EOF'
152
+ |110100|
153
+ |001011|
154
+ |110010|
155
+ |010101|
156
+ |001101|
157
+ |101010|
158
+ EOF
159
+ return Binary_Puzzle_Solver.gen_board_from_string_v1(input_str)
160
+ end
161
+
162
+ def get_8x8_easy_board_1__initial()
163
+ input_str = <<'EOF'
164
+ | 0|
165
+ | 00 1 |
166
+ | 0 1 0|
167
+ | 1 |
168
+ |00 1 1 |
169
+ | 1 |
170
+ |11 0 1|
171
+ | 1 1|
172
+ EOF
173
+ return Binary_Puzzle_Solver.gen_board_from_string_v1(input_str)
174
+ end
175
+
176
+ def get_8x8_easy_board_1__final()
177
+ input_str = <<'EOF'
178
+ |01101010|
179
+ |10010101|
180
+ |10010110|
181
+ |01101001|
182
+ |00110110|
183
+ |10011010|
184
+ |11001001|
185
+ |01100101|
186
+ EOF
187
+ return Binary_Puzzle_Solver.gen_board_from_string_v1(input_str)
188
+ end
189
+
190
+ def get_8x8_medium_board_1__initial()
191
+ input_str = <<'EOF'
192
+ | 0 0 |
193
+ |0 0 0 0 |
194
+ | |
195
+ | 1 1 |
196
+ |0 0 |
197
+ |0 00 |
198
+ | 1|
199
+ | 1 1 |
200
+ EOF
201
+ return Binary_Puzzle_Solver.gen_board_from_string_v1(input_str)
202
+ end
203
+
204
+ def get_8x8_medium_board_1__final()
205
+ input_str = <<'EOF'
206
+ |10100101|
207
+ |01010101|
208
+ |10101010|
209
+ |10011010|
210
+ |01100101|
211
+ |01100110|
212
+ |10011001|
213
+ |01011010|
214
+ EOF
215
+ return Binary_Puzzle_Solver.gen_board_from_string_v1(input_str)
216
+ end
217
+
218
+ describe "construct_board" do
219
+ it "6*6 Easy board No. 1 should" do
220
+
221
+ board = get_6x6_easy_board_1()
222
+
223
+ ONE = Binary_Puzzle_Solver::Cell::ONE
224
+ ZERO = Binary_Puzzle_Solver::Cell::ZERO
225
+ UNKNOWN = Binary_Puzzle_Solver::Cell::UNKNOWN
226
+
227
+ board.get_cell_state(
228
+ Binary_Puzzle_Solver::Coord.new(:x => 0, :y => 0)
229
+ ).should == ONE
230
+ board.get_cell_state(
231
+ Binary_Puzzle_Solver::Coord.new(:x => 3, :y => 0)
232
+ ).should == ZERO
233
+ board.get_cell_state(
234
+ Binary_Puzzle_Solver::Coord.new(:x => 1, :y => 0)
235
+ ).should == UNKNOWN
236
+ board.get_cell_state(
237
+ Binary_Puzzle_Solver::Coord.new(:x => 2, :y => 1)
238
+ ).should == ZERO
239
+ board.get_cell_state(
240
+ Binary_Puzzle_Solver::Coord.new(:x => 5, :y => 1)
241
+ ).should == ONE
242
+
243
+ # Check for dimensions of the board.
244
+ board.limit(:y).should == 6
245
+ board.limit(:x).should == 6
246
+ board.max_idx(:y).should == 5
247
+ board.max_idx(:x).should == 5
248
+
249
+ view = board.get_view(:rotate => false)
250
+
251
+ view.get_cell_state(
252
+ Binary_Puzzle_Solver::Coord.new(:x => 0, :y => 0)
253
+ ).should == ONE
254
+ view.get_cell_state(
255
+ Binary_Puzzle_Solver::Coord.new(:x => 3, :y => 0)
256
+ ).should == ZERO
257
+ view.get_cell_state(
258
+ Binary_Puzzle_Solver::Coord.new(:x => 1, :y => 0)
259
+ ).should == UNKNOWN
260
+ view.get_cell_state(
261
+ Binary_Puzzle_Solver::Coord.new(:x => 2, :y => 1)
262
+ ).should == ZERO
263
+ view.get_cell_state(
264
+ Binary_Puzzle_Solver::Coord.new(:x => 5, :y => 1)
265
+ ).should == ONE
266
+
267
+ view.get_row_summary(:dim => :x, :idx => 3
268
+ ).get_count(ONE).should == 1
269
+ view.get_row_summary(:dim => :x, :idx => 3
270
+ ).get_count(ZERO).should == 2
271
+ view.get_row_summary(:dim => :x, :idx => 0
272
+ ).get_count(ONE).should == 1
273
+ view.get_row_summary(:dim => :x, :idx => 0
274
+ ).get_count(ZERO).should == 1
275
+ view.get_row_summary(:dim => :y, :idx => 1
276
+ ).get_count(ZERO).should == 2
277
+ view.get_row_summary(:dim => :y, :idx => 1
278
+ ).get_count(ONE).should == 1
279
+
280
+ # Check for dimensions of the view.
281
+ view.limit(:y).should == 6
282
+ view.limit(:x).should == 6
283
+ view.max_idx(:y).should == 5
284
+ view.max_idx(:x).should == 5
285
+
286
+ rotated_view = board.get_view(:rotate => true)
287
+
288
+ rotated_view.get_cell_state(
289
+ Binary_Puzzle_Solver::Coord.new(:y => 0, :x => 0)
290
+ ).should == ONE
291
+ rotated_view.get_cell_state(
292
+ Binary_Puzzle_Solver::Coord.new(:y => 3, :x => 0)
293
+ ).should == ZERO
294
+ rotated_view.get_cell_state(
295
+ Binary_Puzzle_Solver::Coord.new(:y => 1, :x => 0)
296
+ ).should == UNKNOWN
297
+ rotated_view.get_cell_state(
298
+ Binary_Puzzle_Solver::Coord.new(:y => 2, :x => 1)
299
+ ).should == ZERO
300
+ rotated_view.get_cell_state(
301
+ Binary_Puzzle_Solver::Coord.new(:y => 5, :x => 1)
302
+ ).should == ONE
303
+
304
+ # Check for dimensions of the rotated_view.
305
+ rotated_view.limit(:y).should == 6
306
+ rotated_view.limit(:x).should == 6
307
+ rotated_view.max_idx(:y).should == 5
308
+ rotated_view.max_idx(:x).should == 5
309
+
310
+ end
311
+ end
312
+
313
+ describe "rudimentary_deduction" do
314
+ it "6*6 Easy board No. 1 should" do
315
+
316
+ board = get_6x6_easy_board_1()
317
+
318
+ # ONE = Binary_Puzzle_Solver::Cell::ONE
319
+ # ZERO = Binary_Puzzle_Solver::Cell::ZERO
320
+ # UNKNOWN = Binary_Puzzle_Solver::Cell::UNKNOWN
321
+
322
+ view = board.get_view(:rotate => false)
323
+ view.check_and_handle_sequences_in_row(:idx => 1)
324
+
325
+ board.get_cell_state(
326
+ Binary_Puzzle_Solver::Coord.new(:x => 1, :y => 1)
327
+ ).should == ONE
328
+ board.get_cell_state(
329
+ Binary_Puzzle_Solver::Coord.new(:x => 4, :y => 1)
330
+ ).should == ONE
331
+
332
+ board.num_moves_done.should == 2
333
+
334
+ end
335
+
336
+ it "6*6 Easy board No. 1 should" do
337
+
338
+ board = get_6x6_easy_board_1()
339
+
340
+ view = board.get_view(:rotate => true)
341
+ view.check_and_handle_sequences_in_row(:idx => 5)
342
+
343
+ board.get_cell_state(
344
+ Binary_Puzzle_Solver::Coord.new(:x => 5, :y => 0)
345
+ ).should == ZERO
346
+ board.get_cell_state(
347
+ Binary_Puzzle_Solver::Coord.new(:x => 5, :y => 3)
348
+ ).should == ZERO
349
+
350
+ board.num_moves_done.should == 2
351
+
352
+ end
353
+
354
+ it "6*6 Easy board No. 1 should flush moves properly" do
355
+
356
+ board = get_6x6_easy_board_1()
357
+
358
+ # ONE = Binary_Puzzle_Solver::Cell::ONE
359
+ # ZERO = Binary_Puzzle_Solver::Cell::ZERO
360
+ # UNKNOWN = Binary_Puzzle_Solver::Cell::UNKNOWN
361
+
362
+ view = board.get_view(:rotate => false)
363
+ view.check_and_handle_sequences_in_row(:idx => 1)
364
+
365
+ board.flush_moves()
366
+
367
+ view = board.get_view(:rotate => true)
368
+ view.check_and_handle_sequences_in_row(:idx => 5)
369
+
370
+ # Checking that the moves were flushed.
371
+ board.num_moves_done.should == 2
372
+
373
+ end
374
+
375
+ it "6*6 Easy board No. 1 should" do
376
+
377
+ board = get_6x6_easy_board_1()
378
+
379
+ # ONE = Binary_Puzzle_Solver::Cell::ONE
380
+ # ZERO = Binary_Puzzle_Solver::Cell::ZERO
381
+ # UNKNOWN = Binary_Puzzle_Solver::Cell::UNKNOWN
382
+
383
+ view = board.get_view(:rotate => false)
384
+ view.check_and_handle_sequences_in_row(:idx => 1)
385
+
386
+ board.get_cell_state(
387
+ Binary_Puzzle_Solver::Coord.new(:x => 1, :y => 1)
388
+ ).should == ONE
389
+ board.get_cell_state(
390
+ Binary_Puzzle_Solver::Coord.new(:x => 4, :y => 1)
391
+ ).should == ONE
392
+
393
+ board.num_moves_done.should == 2
394
+
395
+ m = board.get_new_move(0)
396
+
397
+ # Move has (x=1,y=1) coordinate.
398
+ m.coord.x.should == 1
399
+ m.coord.y.should == 1
400
+ m.dir.should == :x
401
+ m.val.should == ONE
402
+
403
+ m = board.get_new_move(1)
404
+
405
+ # Move has (x=1,y=1) coordinate.
406
+ m.coord.x.should == 4
407
+ m.coord.y.should == 1
408
+ m.dir.should == :x
409
+ m.val.should == ONE
410
+
411
+ end
412
+
413
+ it "6*6 Easy board No. 1 should" do
414
+
415
+ board = get_6x6_easy_board_1()
416
+
417
+ # ONE = Binary_Puzzle_Solver::Cell::ONE
418
+ # ZERO = Binary_Puzzle_Solver::Cell::ZERO
419
+ # UNKNOWN = Binary_Puzzle_Solver::Cell::UNKNOWN
420
+
421
+ view = board.get_view(:rotate => true)
422
+ view.check_and_handle_known_unknown_sameknown_in_row(:idx => 1)
423
+
424
+ board.get_cell_state(
425
+ Binary_Puzzle_Solver::Coord.new(:x => 1, :y => 3)
426
+ ).should == ONE
427
+
428
+ board.num_moves_done.should == 1
429
+
430
+ m = board.get_new_move(0)
431
+
432
+ # Move has (x=1,y=1) coordinate.
433
+ m.coord.x.should == 1
434
+ m.coord.y.should == 3
435
+ m.dir.should == :y
436
+ m.val.should == ONE
437
+
438
+ end
439
+
440
+ it "6*6 Easy process should" do
441
+
442
+ board = get_6x6_easy_board_1()
443
+
444
+ board.add_to_iters_quota(1_000_000_000);
445
+
446
+ board.try_to_solve_using(
447
+ :methods => [
448
+ :check_and_handle_sequences_in_row,
449
+ :check_and_handle_known_unknown_sameknown_in_row,
450
+ ]
451
+ );
452
+
453
+ good_num_iters = board.num_iters_done()
454
+
455
+ final_board = get_6x6_easy_board_1__intermediate_board()
456
+
457
+ compare_boards(board, final_board)
458
+
459
+ resume_board = get_6x6_easy_board_1()
460
+
461
+ resume_board.add_to_iters_quota(10);
462
+
463
+ resume_board.try_to_solve_using(
464
+ :methods => [
465
+ :check_and_handle_sequences_in_row,
466
+ :check_and_handle_known_unknown_sameknown_in_row,
467
+ ]
468
+ );
469
+
470
+ resume_board.add_to_iters_quota(1_000_000_000)
471
+
472
+ resume_board.try_to_solve_using(
473
+ :methods => [
474
+ :check_and_handle_sequences_in_row,
475
+ :check_and_handle_known_unknown_sameknown_in_row,
476
+ ]
477
+ );
478
+
479
+ resume_board.num_iters_done.should == good_num_iters
480
+ end
481
+
482
+ it "Solving 6*6 Easy board No. 2 should" do
483
+
484
+ board = get_6x6_easy_board_2()
485
+
486
+ board.add_to_iters_quota(1_000_000_000);
487
+
488
+ board.try_to_solve_using(
489
+ :methods => [
490
+ :check_and_handle_sequences_in_row,
491
+ :check_and_handle_known_unknown_sameknown_in_row,
492
+ ]
493
+ );
494
+
495
+ final_board = get_6x6_easy_board_2__intermediate_board()
496
+
497
+ compare_boards(board, final_board)
498
+ end
499
+
500
+ it "Solving 6*6 Medium board No. 1 should" do
501
+
502
+ board = get_6x6_medium_board_1()
503
+
504
+ board.validate().should == :non_final
505
+
506
+ board.add_to_iters_quota(1_000_000_000);
507
+
508
+ board.try_to_solve_using(
509
+ :methods => [
510
+ :check_and_handle_sequences_in_row,
511
+ :check_and_handle_known_unknown_sameknown_in_row,
512
+ ]
513
+ );
514
+
515
+ first_intermediate_board = get_6x6_medium_board_1__after_easy_moves()
516
+
517
+ compare_boards(board, first_intermediate_board)
518
+
519
+ board.try_to_solve_using(
520
+ :methods => [
521
+ :check_and_handle_cells_of_one_value_in_row_were_all_found,
522
+ ]
523
+ )
524
+
525
+ second_intermediate_board = get_6x6_medium_board_1__after_cells_of_one_value_in_row_were_all_found()
526
+
527
+ compare_boards(board, second_intermediate_board)
528
+
529
+ board.try_to_solve_using(
530
+ :methods => [
531
+ :check_and_handle_sequences_in_row,
532
+ :check_and_handle_known_unknown_sameknown_in_row,
533
+ :check_and_handle_cells_of_one_value_in_row_were_all_found,
534
+ ]
535
+ )
536
+
537
+ final_board = get_6x6_medium_board_1__final()
538
+
539
+ compare_boards(board, final_board)
540
+
541
+ board.validate().should == :final
542
+ end
543
+
544
+ it "Solving 8*8 Easy board No. 1 should" do
545
+
546
+ board = get_8x8_easy_board_1__initial()
547
+
548
+ board.add_to_iters_quota(1_000_000_000);
549
+
550
+ board.try_to_solve_using(
551
+ :methods => [
552
+ :check_and_handle_sequences_in_row,
553
+ :check_and_handle_known_unknown_sameknown_in_row,
554
+ :check_and_handle_cells_of_one_value_in_row_were_all_found,
555
+ ]
556
+ );
557
+
558
+ final_board = get_8x8_easy_board_1__final()
559
+
560
+ compare_boards(board, final_board)
561
+ end
562
+
563
+ it "Solving 8*8 Medium board No. 1 should" do
564
+
565
+ board = get_8x8_medium_board_1__initial()
566
+
567
+ board.add_to_iters_quota(1_000_000_000);
568
+
569
+ board.try_to_solve_using(
570
+ :methods => [
571
+ :check_and_handle_sequences_in_row,
572
+ :check_and_handle_known_unknown_sameknown_in_row,
573
+ :check_and_handle_cells_of_one_value_in_row_were_all_found,
574
+ ]
575
+ );
576
+
577
+ final_board = get_8x8_medium_board_1__final()
578
+
579
+ # binding.pry
580
+ compare_boards(board, final_board)
581
+ end
582
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: binary_puzzle_solver
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Shlomi Fish
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-06 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: launchy
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 2.5.0
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 2.5.0
46
+ description: ! "This is a solver for instances of the so-called Binary\n Puzzle
47
+ from http://www.binarypuzzle.com/ . It is incomplete, but\n can still solve
48
+ some games\n "
49
+ email:
50
+ - shlomif@cpan.org
51
+ executables: []
52
+ extensions: []
53
+ extra_rdoc_files: []
54
+ files:
55
+ - Gemfile
56
+ - LICENSE.txt
57
+ - Makefile
58
+ - README.md
59
+ - Rakefile
60
+ - binary_puzzle_solver.gemspec
61
+ - lib/binary_puzzle_solver.rb
62
+ - lib/binary_puzzle_solver/base.rb
63
+ - lib/binary_puzzle_solver/version.rb
64
+ - test/parse-board.rb
65
+ homepage: http://github.com/shlomif/binary-puzzle-garden
66
+ licenses: []
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubyforge_project:
85
+ rubygems_version: 1.8.24
86
+ signing_key:
87
+ specification_version: 3
88
+ summary: A solver for http://www.binarypuzzle.com/ instances
89
+ test_files:
90
+ - test/parse-board.rb