pentomino 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +51 -0
- data/Rakefile +2 -0
- data/bin/pentomino +193 -0
- data/lib/pentomino.rb +5 -0
- data/lib/pentomino/version.rb +3 -0
- data/pentomino.gemspec +23 -0
- metadata +83 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c16fecdac1939c848fd3db73e9c008803024a009
|
4
|
+
data.tar.gz: 1829effc275aa717c2d7f27c395ae33a16aeebd9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2d9e3a739720a952f3d38aa16d15b822b92a0e3bf1114de955f6d352340c0101040f0545a95dc753c45fa8e78c7786490c9c996688ac8f7be42f1d7a98179efb
|
7
|
+
data.tar.gz: fa478b7a5e3b085d62696f91246378ea850587154097bd00661e235a94a456150ab3509d49404d4d4f340e8770f36caf8df3599d0662445cd44f49e8454b7c3e
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 zariganitosh
|
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,51 @@
|
|
1
|
+
# Pentomino
|
2
|
+
|
3
|
+
Find answer of pentomino puzzle on the board(3x20, 4x15, 5x12, 6x10, 7x9-3, 8x8-4).
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'pentomino'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install pentomino
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
````
|
23
|
+
Usage: pentomino [options] [board size(3-8)]
|
24
|
+
-q Hide progress putting a piece on board.(quiet mode)
|
25
|
+
|
26
|
+
board size:
|
27
|
+
[3] x 20
|
28
|
+
[4] x 15
|
29
|
+
[5] x 12
|
30
|
+
[6] x 10 (Default)
|
31
|
+
[7] x 9 - 3
|
32
|
+
[8] x 8 - 4
|
33
|
+
|
34
|
+
example:
|
35
|
+
6 x 10 7 x 9 - 3 8 x 8 - 4
|
36
|
+
11 12 13 14 15 16 17 18 19 1A 11 12 13 14 15 16 17 18 19 11 12 13 14 15 16 17 18
|
37
|
+
21 22 23 24 25 26 27 28 29 2A 21 22 23 24 25 26 27 28 29 21 22 23 24 25 26 27 28
|
38
|
+
31 32 33 34 35 36 37 38 39 3A 31 32 33 34 35 36 37 38 39 31 32 33 34 35 36 37 38
|
39
|
+
41 42 43 44 45 46 47 48 49 4A 41 42 43 47 48 49 41 42 43 46 47 48
|
40
|
+
51 52 53 54 55 56 57 58 59 5A 51 52 53 54 55 56 57 58 59 51 52 53 56 57 58
|
41
|
+
61 62 63 64 65 66 67 68 69 6A 61 62 63 64 65 66 67 68 69 61 62 63 64 65 66 67 68
|
42
|
+
71 72 73 74 75 76 77 78 79 71 72 73 74 75 76 77 78
|
43
|
+
81 82 83 84 85 86 87 88
|
44
|
+
````
|
45
|
+
## Contributing
|
46
|
+
|
47
|
+
1. Fork it ( https://github.com/[my-github-username]/pentomino/fork )
|
48
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
49
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
50
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
51
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/bin/pentomino
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
# オプション解析
|
7
|
+
$options = {}
|
8
|
+
OptionParser.new do |opt|
|
9
|
+
opt.banner = 'Usage: pentomino [options] [board size(3-8)]'
|
10
|
+
opt.on('-q', 'Hide progress putting a piece on board.(quiet mode)') {|v| $options[:quiet] = v}
|
11
|
+
opt.separator('')
|
12
|
+
opt.on('board size:',
|
13
|
+
' [3] x 20',
|
14
|
+
' [4] x 15',
|
15
|
+
' [5] x 12',
|
16
|
+
' [6] x 10 (Default)',
|
17
|
+
' [7] x 9 - 3',
|
18
|
+
' [8] x 8 - 4',
|
19
|
+
)
|
20
|
+
opt.separator('')
|
21
|
+
opt.on('example:',
|
22
|
+
' 6 x 10 7 x 9 - 3 8 x 8 - 4',
|
23
|
+
'11 12 13 14 15 16 17 18 19 1A 11 12 13 14 15 16 17 18 19 11 12 13 14 15 16 17 18',
|
24
|
+
'21 22 23 24 25 26 27 28 29 2A 21 22 23 24 25 26 27 28 29 21 22 23 24 25 26 27 28',
|
25
|
+
'31 32 33 34 35 36 37 38 39 3A 31 32 33 34 35 36 37 38 39 31 32 33 34 35 36 37 38',
|
26
|
+
'41 42 43 44 45 46 47 48 49 4A 41 42 43 47 48 49 41 42 43 46 47 48',
|
27
|
+
'51 52 53 54 55 56 57 58 59 5A 51 52 53 54 55 56 57 58 59 51 52 53 56 57 58',
|
28
|
+
'61 62 63 64 65 66 67 68 69 6A 61 62 63 64 65 66 67 68 69 61 62 63 64 65 66 67 68',
|
29
|
+
' 71 72 73 74 75 76 77 78 79 71 72 73 74 75 76 77 78',
|
30
|
+
' 81 82 83 84 85 86 87 88',
|
31
|
+
)
|
32
|
+
begin
|
33
|
+
opt.parse!(ARGV)
|
34
|
+
BCOL = (ARGV[0] || 6).to_i
|
35
|
+
BROW = (60.0 / BCOL).round
|
36
|
+
raise "Invalid board size: #{BCOL}" if BCOL < 3 || 8 < BCOL
|
37
|
+
rescue => e
|
38
|
+
puts e
|
39
|
+
exit
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
# すべてのピース形状をPieceオブジェクトの配列に保存する
|
46
|
+
class Piece
|
47
|
+
attr_accessor :used, :form, :form_pos, :letter, :color
|
48
|
+
|
49
|
+
def initialize(a, m, n, l, c)
|
50
|
+
@used = false
|
51
|
+
@form = []
|
52
|
+
@form_pos = []
|
53
|
+
@letter = l
|
54
|
+
@color = c
|
55
|
+
for i in (1..m)
|
56
|
+
for j in (1..n)
|
57
|
+
@form << [a, a.flatten.index(1)]
|
58
|
+
a = a.transpose.reverse # rotate L
|
59
|
+
end
|
60
|
+
a = a.map(&:reverse) # flip LR
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
r = BCOL == 8 ? 1 : 2
|
66
|
+
@pieces = [Piece.new([[0,1,0], [1,1,1], [0,1,0]], 1, 1, :X, 141),
|
67
|
+
Piece.new([[1,1,1], [1,0,1]] , 1, 4, :U, 6),
|
68
|
+
Piece.new([[1,1,0], [0,1,1], [0,0,1]], 1, 4, :W, 104),
|
69
|
+
Piece.new([[1,1,0], [0,1,1], [0,1,0]], 1, r, :F, 172),
|
70
|
+
Piece.new([[1,1,0], [0,1,0], [0,1,1]], 2, 2, :Z, 211),
|
71
|
+
Piece.new([[1,1,1], [1,1,0]], 2, 4, :P, 70),
|
72
|
+
Piece.new([[1,1,1,0], [0,0,1,1]], 2, 4, :N, 121),
|
73
|
+
Piece.new([[1,1,1,1], [0,1,0,0]], 2, 4, :Y, 170),
|
74
|
+
Piece.new([[1,1,1], [0,1,0], [0,1,0]], 1, 4, :T, 42),
|
75
|
+
Piece.new([[1,1,1,1], [1,0,0,0]], 2, 4, :L, 3),
|
76
|
+
Piece.new([[1,1,1], [1,0,0], [1,0,0]], 1, 4, :V, 75),
|
77
|
+
Piece.new([[1,1,1,1,1]], 1, 2, :I, 217)]
|
78
|
+
|
79
|
+
@pieces.each_with_index do |piece, i|
|
80
|
+
piece.form.each do |form|
|
81
|
+
a = []
|
82
|
+
form[0].each_with_index do |row, r|
|
83
|
+
row.each_with_index do |col, c|
|
84
|
+
a << r * (BCOL + 1) + c - form[1] if col == 1
|
85
|
+
end
|
86
|
+
end
|
87
|
+
piece.form_pos << a
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
BLOCK_COLOR = [250] + @pieces.map{|i| i.color} + [0]
|
92
|
+
|
93
|
+
|
94
|
+
|
95
|
+
# エスケープシーケンス定義
|
96
|
+
module EscapeSequence
|
97
|
+
module_function
|
98
|
+
|
99
|
+
def home ; "\e[H" ; end # カーソル位置を画面左上へ移動(ホームポジション)
|
100
|
+
def clear(n=2) ; "\e[#{n}J" ; end # n=(0:画面先頭からカーソル位置まで消去, 1:カーソル位置から画面末尾まで消去, 2:画面全体を消去)
|
101
|
+
def moveup(n) ; "\e[#{n}A" ; end # カーソルを上方向へn行移動
|
102
|
+
def bgcolor(nnn); "\e[48;5;#{nnn}m" ; end # 色指定の開始(nnn=0..255)
|
103
|
+
def reset ; "\e[m" ; end # 色指定の終了
|
104
|
+
|
105
|
+
def create_block(color); bgcolor(BLOCK_COLOR[color]) + " " + reset; end
|
106
|
+
def back_to_head ; moveup(BCOL + 1) ; end
|
107
|
+
def reset_screen ; home + clear ; end
|
108
|
+
def next_screen ; "\n" * (BCOL + 2) ; end
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
|
113
|
+
# board定義
|
114
|
+
class Board
|
115
|
+
def initialize(row, col)
|
116
|
+
@row, @col = row, col
|
117
|
+
@cell = Array.new((row + 1) * (col + 1), 0)
|
118
|
+
@cell.each_with_index do |b, i|
|
119
|
+
@cell[i] = 100 if ((i + 1) % (col + 1)) == 0 || i >= ((col + 1) * row)
|
120
|
+
end
|
121
|
+
@cell[30], @cell[31], @cell[39], @cell[40] = 13, 13, 13, 13 if col == 8
|
122
|
+
@cell[27], @cell[35], @cell[43] = 13, 13, 13 if col == 7
|
123
|
+
end
|
124
|
+
|
125
|
+
def display(header='')
|
126
|
+
puts EscapeSequence.back_to_head + header
|
127
|
+
matrix = []
|
128
|
+
@cell.each_slice(@col + 1) do |line|
|
129
|
+
matrix << line.reject {|i| i == 100}.map {|i| EscapeSequence.create_block(i)}
|
130
|
+
end
|
131
|
+
matrix[0..-2].transpose.each {|line| puts line.join}
|
132
|
+
end
|
133
|
+
|
134
|
+
def blank_index
|
135
|
+
@cell.index(0)
|
136
|
+
end
|
137
|
+
|
138
|
+
def used?(pos, ox)
|
139
|
+
@cell[ox + pos[1]]>0 || @cell[ox + pos[2]]>0 || @cell[ox + pos[3]]>0 || @cell[ox + pos[4]]>0
|
140
|
+
end
|
141
|
+
|
142
|
+
def set_piece(piece_id, pos, ox)
|
143
|
+
pos.each {|p| @cell[ox + p] = piece_id}
|
144
|
+
end
|
145
|
+
|
146
|
+
def unset_piece(pos, ox)
|
147
|
+
pos.each {|p| @cell[ox + p] = 0}
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
|
152
|
+
|
153
|
+
# パズルの解を求める
|
154
|
+
def try_piece(lvl)
|
155
|
+
@try_counter += 1
|
156
|
+
origin_x = @board.blank_index
|
157
|
+
@pieces.each_with_index do |piece, i|
|
158
|
+
next if piece.used
|
159
|
+
piece.form_pos.each do |pos|
|
160
|
+
next if @board.used?(pos, origin_x)
|
161
|
+
# ピースを置く
|
162
|
+
@board.set_piece(i + 1, pos, origin_x)
|
163
|
+
piece.used = true
|
164
|
+
@board.display if !$options[:quiet]
|
165
|
+
# すべてのピースを置ききったら再帰呼び出し終了
|
166
|
+
if lvl == 11 then
|
167
|
+
@counter += 1
|
168
|
+
@board.display("No. #{@counter} (TRY: #{@try_counter})")
|
169
|
+
puts EscapeSequence.next_screen
|
170
|
+
# ピースを戻す
|
171
|
+
@board.unset_piece(pos, origin_x)
|
172
|
+
piece.used = false
|
173
|
+
return
|
174
|
+
end
|
175
|
+
# 次のピースを試す
|
176
|
+
try_piece(lvl + 1)
|
177
|
+
# ピースを戻す
|
178
|
+
@board.unset_piece(pos, origin_x)
|
179
|
+
piece.used = false
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
@counter = 0
|
185
|
+
@try_counter = 0
|
186
|
+
@board = Board.new(BROW, BCOL)
|
187
|
+
puts EscapeSequence.reset_screen
|
188
|
+
puts "Pentomino #{BCOL}x#{BROW}"
|
189
|
+
puts EscapeSequence.next_screen
|
190
|
+
try_piece(0)
|
191
|
+
puts "Pentomino #{BCOL}x#{BROW}"
|
192
|
+
puts "解合計: #{@counter}"
|
193
|
+
puts "操作数: #{@try_counter}"
|
data/lib/pentomino.rb
ADDED
data/pentomino.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'pentomino/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "pentomino"
|
8
|
+
spec.version = Pentomino::VERSION
|
9
|
+
spec.authors = ["zariganitosh"]
|
10
|
+
spec.email = ["XXXX@example.com"]
|
11
|
+
spec.summary = %q{Find answer of pentomino puzzle.}
|
12
|
+
spec.description = %q{Find answer of pentomino puzzle on the board(3x20, 4x15, 5x12, 6x10, 7x9-3, 8x8-4).}
|
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_development_dependency "bundler", "~> 1.7"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pentomino
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- zariganitosh
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-01-23 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.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
description: Find answer of pentomino puzzle on the board(3x20, 4x15, 5x12, 6x10,
|
42
|
+
7x9-3, 8x8-4).
|
43
|
+
email:
|
44
|
+
- XXXX@example.com
|
45
|
+
executables:
|
46
|
+
- pentomino
|
47
|
+
extensions: []
|
48
|
+
extra_rdoc_files: []
|
49
|
+
files:
|
50
|
+
- .gitignore
|
51
|
+
- Gemfile
|
52
|
+
- LICENSE.txt
|
53
|
+
- README.md
|
54
|
+
- Rakefile
|
55
|
+
- bin/pentomino
|
56
|
+
- lib/pentomino.rb
|
57
|
+
- lib/pentomino/version.rb
|
58
|
+
- pentomino.gemspec
|
59
|
+
homepage: ''
|
60
|
+
licenses:
|
61
|
+
- MIT
|
62
|
+
metadata: {}
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options: []
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - '>='
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
requirements: []
|
78
|
+
rubyforge_project:
|
79
|
+
rubygems_version: 2.4.2
|
80
|
+
signing_key:
|
81
|
+
specification_version: 4
|
82
|
+
summary: Find answer of pentomino puzzle.
|
83
|
+
test_files: []
|