Ruby2.0でlazyな n-Queen

759 views
632 views

Published on

0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
759
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
2
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Ruby2.0でlazyな n-Queen

  1. 1. Ruby2.0でlazyなN-Queen e-Zuka Tech Night 山崎重一郎
  2. 2. N-Queen 1 2 3 4 解 [2,4,1,3][1~N] の順列の生成、テスト
  3. 3. Rubyで順列の生成> [1,2,3,4].permutation=> #<Enumerator: [1, 2, 3, 4]:permutation> > [1,2,3,4].permutation.to_a => [[1, 2, 3, 4], [1, 2, 4, 3], [1, 3, 2, 4], [1, 3, 4, 2], [1, 4, 2, 3], [1, 4, 3, 2], [2, 1, 3, 4], [2, 1, 4, 3], [2, 3, 1, 4], [2, 3, 4, 1], [2, 4, 1, 3], [2, 4, 3, 1], [3, 1, 2, 4], [3, 1, 4, 2], [3, 2, 1, 4], [ 3, 2, 4, 1], [3, 4, 1, 2], [3, 4, 2, 1], [4, 1, 2, 3], [4, 1, 3, 2], [4, 2, 1, 3], [4, 2, 3, 1], [4, 3, 1, 2], [4, 3, 2, 1]]
  4. 4. 順列の生成方法> [1,2,3,4].permutation=> #<Enumerator: [1, 2, 3, 4]:permutation> > [*1..10].permutation.to_a なかなか返ってこない〜
  5. 5. 順列生成をFiberにするf=->n{Fiber.new{[*1..n].permutation.each{|x|Fiber.yield x}}}g=f[10]=> #<Fiber:0x00000126282090>g.resume=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]g.resume=> [1, 2, 3, 4, 5, 6, 7, 8, 10, 9]g=f[100]g.resume
  6. 6. Ruby 2.0のlazy 順列をlazyに生成Ruby 1.9の場合はgemでenumerable-lazyを入れてrequire enumerable/lazy[*1..4].permutation.lazy[*1..4].permutation.lazy.to_a=>[[1, 2, 3, 4], [1, 2, 4, 3], [1, 3, 2, 4], [1, 3, 4, 2], [1, 4, 2, 3], [1, 4, 3, 2], [2, 1, 3, 4], [2, 1, 4, 3], [2, 3, 1, 4], [2, 3, 4, 1], [2, 4, 1, 3], [2, 4, 3, 1], [3, 1, 2, 4], [3, 1, 4, 2], [3, 2, 1, 4], [3, 2, 4, 1], [3, 4, 1, 2], [3, 4, 2, 1], [4, 1, 2, 3], [4, 1, 3, 2], [4, 2, 1, 3], [4, 2, 3, 1], [4, 3, 1, 2], [4, 3, 2, 1]][*1..4].permutation.lazy.take(3).to_a=> [[1, 2, 3, 4], [1, 2, 4, 3], [1, 3, 2, 4]]
  7. 7. Ruby 2.0 順列生成をlazyにやるf=->n{[*1..n].permutation.lazy}g=f[20]g.take(3).to_a=>[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], [1, 2,3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 19], [1, 2, 3, 4, 5,6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 18, 20]]g.take(4).to_a=>[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], [1, 2,3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 19], [1, 2, 3, 4, 5,6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 18, 20], [1, 2, 3, 4, 5, 6, 7, 8,
  8. 8. Fiber版N-Queen#斜めチェックd=->b{->a{a.map.with_index{|x,i|x==b-i-1 or x==b+i+1}}}diag=->a{a==[]? true : (not(d[a[0]][a[1..-1]].any?) and diag[a[1..-1]])}#ファイバー生成関数f=->n{Fiber.new{[*1..n].permutation.each{|x|Fiber.yield x}}}g=f[10]queen=->{p;begin p=g.resume end until diag[p];p}queen[]=> [1, 3, 6, 8, 10, 5, 9, 2, 4, 7]queen[]=> [1, 3, 6, 9, 7, 10, 4, 2, 5, 8]> queen[]=> [1, 3, 6, 9, 7, 10, 4, 2, 8, 5]
  9. 9. lazy版N-Queend=->b{->a{a.map.with_index{|x,i|x==b-i-1 or x==b+i+1}}}diag=->a{a==[]? true : (not(d[a[0]][a[1..-1]].any?) and diag[a[1..-1]])}f=->n{[*1..n].permutation.lazy}queen=->n{->m{f[n].select{|p|diag[p]}.take(m).to_a}}# takeは、取り出す解の個数queen[10][1]=> [[1, 3, 6, 8, 10, 5, 9, 2, 4, 7]]queen[10][2]=> [[1, 3, 6, 8, 10, 5, 9, 2, 4, 7], [1, 3, 6, 9, 7, 10, 4, 2, 5, 8]]queen[10][3]=>[[1, 3, 6, 8, 10, 5, 9, 2, 4, 7], [1, 3, 6, 9, 7, 10, 4, 2, 5, 8], [1, 3, 6, 9, 7, 10, 4, 2, 8, 5]]
  10. 10. lazy版N-Queend=->b{->a{a.map.with_index{|x,i|x==b-i-1 or x==b+i+1}}}diag=->a{a==[]? true : (not(d[a[0]][a[1..-1]].any?) and diag[a[1..-1]])}f=->n{[*1..n].permutation.lazy}queen=->n{->m{f[n].take(m).select{|p|diag[p]}.to_a}}#takeの位置を変更して、候補の順列の生成回数にしてみるqueen[10][50000]=> []queen[10][60000]=>[[1, 3, 6, 8, 10, 5, 9, 2, 4, 7], [1, 3, 6, 9, 7, 10, 4, 2, 5, 8], [1, 3, 6, 9, 7, 10, 4, 2, 8, 5]]

×