doku 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,14 +2,78 @@
2
2
 
3
3
  Doku is a Ruby[http://www.rubylang.org/] gem for solving Sudoku-like puzzles using the {Dancing Links}[http://en.wikipedia.org/wiki/Dancing_Links] algorithm by Donald Knuth.
4
4
 
5
+ Currently it supports these puzzles:
6
+
7
+ * Sudoku
8
+ * Hexadoku
9
+ * Hexamurai
10
+
5
11
  == Installation
6
12
 
7
13
  At the command line, type
8
14
 
9
15
  gem install doku
10
16
 
11
- You might need to prefix that with <code>sudo</code> depending on where your gems are stored.
17
+ You might need to prefix the command with <code>sudo</code> depending on where your gems are stored.
12
18
 
13
19
  == Example code
14
20
 
15
- :include: example.rb
21
+ require 'rubygems'
22
+ require 'doku'
23
+
24
+ puzzle = Doku::Sudoku.new <<END
25
+ ...|..8|...
26
+ ..7|.35|..9
27
+ 5..|4.6|8..
28
+ ---+---+---
29
+ ...|..4|2..
30
+ 4..|...|.37
31
+ 8..|...|5..
32
+ ---+---+---
33
+ .9.|.67|...
34
+ ..3|...|1.5
35
+ ...|...|..3
36
+ END
37
+
38
+ puts puzzle.solve || "No solutions."
39
+
40
+ == Introduction
41
+
42
+ This gem is designed to solve Sudoku-like puzzles. For the purposes of this gem, a "Sudoku-like" puzzle is a defined to be a puzzle consisting of a set of glyphs (i.e. symbols), a set of squares, and a set of groups of squares. Additionally, the number of squares in each group must be equal to the number of glyphs. Given a partial assignment of glyphs to squares, the goal is to assign a glyph to every square such that no two squares in the same group are assigned the same glyph.
43
+
44
+ For example, in Sudoku, the glyphs are the numbers 0 through 9, the squares are the squares of a 9x9 grid, and the groups consist of nine rows, nine columns, and nine 3x3 squares.
45
+
46
+ Every Sudoku-like puzzle can be reduced to an {exact cover problem}[http://en.wikipedia.org/wiki/Exact_cover]. From there is can be efficiently solved with the {Dancing Links}[http://arxiv.org/abs/cs/0011047] algorithm discovered by Donald Knuth. That is the main purpose of this gem.
47
+
48
+ == Classes and Modules Overview
49
+
50
+ The Doku::Puzzle class is an abstract class for working with Sudoku-like puzzles. It implements the concepts of groups, glyphs and squares. Each instance of this class represents a particular assignment of glyphs to squares; at its core, an instance is just a hash where the keys are squares and values are glyphs. This class provides <code>[]</code> and <code>[]=</code> methods for reading and modifying instances of the puzzle. It provides equality comparison and solution checking.
51
+
52
+ The Puzzle class includes the Doku::SolvableWithDancingLinks module which provides methods for solving puzzles using the Dancing Links algorithm. The solutions returned are instances of Puzzle.
53
+
54
+ The Doku::SquareOnGrid module provides methods used for Sudoku-like puzzles that can be drawn on a 2D grid. It implements the string representations of the puzzle by providing an <code>initialize</code> method that creates puzzles from strings and a <code>to_s</code> method that creates strings from puzzles. It provides <code>get</code> and <code>set</code> methods for modifying suqares of the puzzle by their coordinates.
55
+
56
+ The classes Doku::Sudoku, Doku::Hexadoku, and Doku::Hexamurai all inherit from Doku::Puzzle and include Doku::SquareOnGrid. Because of the framework set up by that class and that module, the definitions of these classes are short and the methods provided by each of them are rich and consistent with eachother.
57
+
58
+ The Doku::DancingLinks module contains several class that comprise a general-purpose implementation of the Dancing Links algorithm. This module is included in the Doku gem for convenience, but it is not specifically for solving Sudoku-like puzzles; it can be applied to any exact cover problem.
59
+
60
+ == Detailed Documentation
61
+
62
+ For detailed documentation of every class, module, and method, see the "Class List" link above.
63
+
64
+ == Contributing
65
+
66
+ You are invited to fork the {Doku github repository}[https://github.com/DavidEGrayson/doku] and work on improving the gem.
67
+
68
+ There are many directions this gem could go in. The direction will be determined by user feedback and by whatever the developers feel like working on. Possible improvements could be:
69
+
70
+ * A command-line utility for solving puzzles. This requires us to define a file format for puzzles.
71
+ * A C extension or a column size cache to make the Dancing Links algorithm faster.
72
+ * Hooks for providing progress updates during the solving of hard puzzles.
73
+ * Outputting puzzles in SVG format. Could include SVG animations that show the process of solving the puzzle!
74
+ * More types of puzzles that are solvable (e.g. puzzles that have groups with fewer squares than the number of glyphs).
75
+ * Improve this page. Ideally the method names should be linkified on the {rubydoc.info page}[http://rubydoc.info/github/DavidEGrayson/doku/master], but I still want something presentable to be on the {github repository}[https://github.com/DavidEGrayson/doku]. Here's an example of a link that looks good on RubyDoc.info but not on github: {Doku::Sudoku Sudoku}. If either YARD or Github could be configured to use a different file on the front page, that would suffice!
76
+
77
+ == Philosophy
78
+
79
+ This gem is meant to showcase beautiful Ruby code. Test-driven development was used at all times during the development of this gem. I have spent many hours reviewing the code, looking for ways to make it simpler, and refactoring it. Every class and public method is documented. Every method is short. There are no ugly hacks. All method names were chosen carefully. At every level, the power of the Ruby language is exploited to its fullest potential. --David Grayson
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.0
1
+ 1.0.1
@@ -1,5 +1,4 @@
1
1
  require 'backports' unless defined?(Enumerator)
2
- require 'set'
3
2
 
4
3
  module Doku; end
5
4
 
@@ -7,8 +6,8 @@ module Doku; end
7
6
  # {http://arxiv.org/abs/cs/0011047 Dancing Links}
8
7
  # algorithm discovered by Donald Knuth for solving
9
8
  # {http://en.wikipedia.org/wiki/Exact_cover exact cover problems}.
10
- # This module is included in the Doku gem for convenience, but it really has
11
- # nothing to do with solving Sudoku-like puzzles; it can be applied to any
9
+ # This module is included in the Doku gem for convenience, but it is not
10
+ # specifically for solving Sudoku-like puzzles; it can be applied to any
12
11
  # exact cover problem.
13
12
  # The main class in this module is {LinkMatrix}. All the other classes and
14
13
  # modules are helpers for this class.
@@ -370,7 +369,8 @@ module Doku::DancingLinks
370
369
  # @param row_id (Object) The id of this row. This is used to express express exact covers and as the argument to {#remove_row}.
371
370
  def add_row(column_ids, row_id=column_ids.dup)
372
371
  first_node = nil
373
- Set.new(column_ids).each do |column_id|
372
+ column_ids = column_ids.uniq if column_ids.respond_to?(:uniq)
373
+ column_ids.each do |column_id|
374
374
  column = find_or_create_column(column_id)
375
375
  node = Node.new
376
376
 
@@ -409,19 +409,20 @@ module Doku::DancingLinks
409
409
  @rows[id]
410
410
  end
411
411
 
412
- # This is a recursive method that finds the first exact cover of a
413
- # LinkMatrix that represents an exact cover problem, using the
412
+ # This method is equivalent to {#each_exact_cover} but uses
414
413
  # the algorithm described on page 5 of Donald Knuth's paper "Dancing Links".
415
414
  # This method is just here for purists who want to be sure they are using
416
415
  # Donald Knuth's algorithm.
417
- # For most uses, it is recommended to use the more flexible, non-recursive
416
+ # For most users, it is recommended to use the more flexible, non-recursive
418
417
  # function {#each_exact_cover} and the methods based on it: {#exact_covers}
419
- # and {#find_exact_cover}.
418
+ # and {#find_exact_cover} because it can be difficult to debug programs with
419
+ # deep stacks.
420
420
  # @return (Array) Array of row_ids of the rows/sets that are in the cover,
421
421
  # or nil if no exact cover was found.
422
- def find_exact_cover_recursive(k=0, o=[])
422
+ def each_exact_cover_recursive(k=0, o=[], &block)
423
423
  if right == self
424
- return o[0...k].collect &:row_id # Success
424
+ yield o[0...k].collect &:row_id # Success
425
+ return
425
426
  end
426
427
 
427
428
  c = smallest_column
@@ -434,9 +435,7 @@ module Doku::DancingLinks
434
435
  j.column.cover
435
436
  end
436
437
 
437
- if answer = find_exact_cover_recursive(k+1, o)
438
- return answer # Success
439
- end
438
+ each_exact_cover_recursive(k+1, o, &block)
440
439
 
441
440
  r.nodes_except_self_leftward.each do |j|
442
441
  j.column.uncover
@@ -463,16 +462,12 @@ module Doku::DancingLinks
463
462
  # @return (Enumerable) Enumerable of exact covers. Each exact cover is
464
463
  # an array of row ids of the rows/sets that are in the cover.
465
464
  def exact_covers
466
- Enumerator.new do |y|
467
- each_exact_cover do |ec|
468
- y << ec
469
- end
470
- end
465
+ enum_for :each_exact_cover
471
466
  end
472
467
 
473
468
  # Searches for exact covers and yields them as it finds them.
474
469
  # NOTE: This method mutates the LinkMatrix while it is running, but
475
- # when it is finished the matrix will be back to its original state.
470
+ # when it is finished the matrix will be back to its original state.
476
471
  # @yield exact_cover
477
472
  # @yieldparam exact_cover (Array) Array of row_ids of the rows/sets that are
478
473
  # in the cover.
@@ -7,7 +7,30 @@ module Doku
7
7
  # This is a more complex version of Sudoku with a 16x16 grid, using
8
8
  # hex digits 0 through F.
9
9
  # Each instance of this class represents a particular arrangement of
10
- # numbers written in the boxes.
10
+ # numbers (glyphs) written in the boxes.
11
+ #
12
+ # The template for this puzzle is:
13
+ # puzzle = Doku::Hexadoku.new <<END
14
+ # ....|....|....|....
15
+ # ....|....|....|....
16
+ # ....|....|....|....
17
+ # ....|....|....|....
18
+ # ----+----+----+----
19
+ # ....|....|....|....
20
+ # ....|....|....|....
21
+ # ....|....|....|....
22
+ # ....|....|....|....
23
+ # ----+----+----+----
24
+ # ....|....|....|....
25
+ # ....|....|....|....
26
+ # ....|....|....|....
27
+ # ....|....|....|....
28
+ # ----+----+----+----
29
+ # ....|....|....|....
30
+ # ....|....|....|....
31
+ # ....|....|....|....
32
+ # ....|....|....|....
33
+ # END
11
34
  class Hexadoku < Puzzle
12
35
  include PuzzleOnGrid
13
36
  extend PuzzleOnGrid::ClassMethods # improves generated docs
@@ -7,7 +7,46 @@ module Doku
7
7
  # five {Hexadoku} puzzles superimposed on eachother.
8
8
  # The {http://www.elektor.com/magazines/2011/july-047-august/hexamurai.1852786.lynkx Hexamurai puzzle appeared in the July/August issue of Elektor magazine}.
9
9
  # Each instance of this class represents a particular arrangement of
10
- # numbers written in the boxes.
10
+ # numbers (glyphs) written in the boxes.
11
+ #
12
+ # The template for this puzzle is:
13
+ # puzzle = Doku::Hexamurai.new <<END
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
+ # END
11
50
  class Hexamurai < Puzzle
12
51
  include PuzzleOnGrid
13
52
  extend Doku::PuzzleOnGrid::ClassMethods # improves generated docs
@@ -9,18 +9,13 @@ module Doku
9
9
  # Returns the first solution found by the Dancing Links algorithm,
10
10
  # or nil if there is no solution.
11
11
  def solve
12
- each_solution { |s| return s }
13
- return nil
12
+ solutions.first
14
13
  end
15
14
 
16
15
  # An enumerator for all the solutions to the puzzle.
17
16
  # @return (Enumerable)
18
17
  def solutions
19
- Enumerator.new do |y|
20
- each_solution do |solution|
21
- y << solution
22
- end
23
- end
18
+ enum_for :each_solution
24
19
  end
25
20
 
26
21
  # This method lets you iterate over each solution.
@@ -5,7 +5,22 @@ require_relative 'grid'
5
5
  module Doku
6
6
  # This class represents {http://en.wikipedia.org/wiki/Sudoku Sudoku}.
7
7
  # Each instance of this class represents a particular arrangement of
8
- # numbers written in the boxes.
8
+ # numbers (glyphs) written in the boxes.
9
+ #
10
+ # The template for this puzzle is:
11
+ # puzzle = Doku::Sudoku.new <<END
12
+ # ...|...|...
13
+ # ...|...|...
14
+ # ...|...|...
15
+ # ---+---+---
16
+ # ...|...|...
17
+ # ...|...|...
18
+ # ...|...|...
19
+ # ---+---+---
20
+ # ...|...|...
21
+ # ...|...|...
22
+ # ...|...|...
23
+ # END
9
24
  class Sudoku < Puzzle
10
25
  include PuzzleOnGrid
11
26
  extend PuzzleOnGrid::ClassMethods # improves generated docs
@@ -75,9 +75,9 @@ describe Doku::DancingLinks::LinkMatrix do
75
75
  end
76
76
  end
77
77
 
78
- describe "find_exact_cover_recursive" do
78
+ describe "each_exact_cover_recursive" do
79
79
  it "find the trivial cover for the trivial matrix" do
80
- Doku::DancingLinks::LinkMatrix.new.find_exact_cover_recursive.should == []
80
+ Doku::DancingLinks::LinkMatrix.new.enum_for(:each_exact_cover_recursive).to_a.should == [[]]
81
81
  end
82
82
 
83
83
  it "works even if final(k) < max(k)" do
@@ -88,7 +88,19 @@ describe Doku::DancingLinks::LinkMatrix do
88
88
  [ 3,4, ],
89
89
  [ 4,5],
90
90
  [1,2,3,4,5] ]
91
- m.find_exact_cover_recursive.sort.should == [[1, 2, 3, 4, 5]]
91
+ m.enum_for(:each_exact_cover_recursive).to_a.should == [[[1, 2, 3, 4, 5]]]
92
+ end
93
+
94
+ it "can find multiple solutions" do
95
+ m = Doku::DancingLinks::LinkMatrix.from_sets({
96
+ :a => [1,2, ],
97
+ :b => [ 3,4,5],
98
+ :c => [1, 3, 5],
99
+ :d => [ 2, 4, ],
100
+ })
101
+ solutions = m.enum_for(:each_exact_cover_recursive).to_a.collect { |s| s.sort }
102
+ solutions.should include [:a, :b]
103
+ solutions.should include [:c, :d]
92
104
  end
93
105
  end
94
106
 
@@ -136,7 +148,7 @@ describe Doku::DancingLinks::LinkMatrix do
136
148
  [ 2,3, 6 ],
137
149
  [1, 4 ],
138
150
  [ 2, 7],
139
- Set.new([ 4,5, 7]),
151
+ [ 4,5, 7],
140
152
  ]
141
153
  @m = Doku::DancingLinks::LinkMatrix.from_sets @subsets, @universe
142
154
  end
@@ -41,12 +41,6 @@ END
41
41
  END
42
42
  end
43
43
 
44
- it "can also find the solution using Donald Knuth's recursive DLX" do
45
- sm = @puzzle.to_link_matrix
46
- exact_cover = sm.find_exact_cover_recursive
47
- solution = @puzzle.exact_cover_to_solution exact_cover
48
- solution.should == @solution
49
- end
50
44
  end
51
45
 
52
46
  context 'given a sudoku puzzle with two solutions' do
@@ -64,13 +58,8 @@ END
64
58
  ..3|...|1.5
65
59
  ...|...|..3
66
60
  END
67
- end
68
61
 
69
- it 'finds two solutions' do
70
- solutions = @puzzle.solutions.to_a
71
- solutions.size.should == 2
72
-
73
- solutions.should include Doku::Sudoku.new <<END
62
+ @solution1 = Doku::Sudoku.new <<END
74
63
  964|278|351
75
64
  287|135|649
76
65
  531|496|872
@@ -83,8 +72,7 @@ END
83
72
  723|849|165
84
73
  648|512|793
85
74
  END
86
-
87
- solutions.should include Doku::Sudoku.new <<END
75
+ @solution2 = Doku::Sudoku.new <<END
88
76
  964|278|351
89
77
  287|531|649
90
78
  531|496|872
@@ -97,6 +85,14 @@ END
97
85
  723|849|165
98
86
  648|152|793
99
87
  END
88
+ end
89
+
90
+ it 'finds two solutions' do
91
+ solutions = @puzzle.solutions.to_a
92
+ solutions.size.should == 2
93
+
94
+ solutions.should include @solution1
95
+ solutions.should include @solution2
100
96
 
101
97
  solutions[0].should be_a_solution_for @puzzle
102
98
  solutions[1].should be_a_solution_for @puzzle
@@ -130,11 +126,6 @@ END
130
126
  sc = sm.columns.min_by(&:size)
131
127
  sc.size.should > 0
132
128
  end
133
-
134
- it 'finds no solutions using the recursive algorithm' do
135
- sm = @puzzle.to_link_matrix
136
- sm.find_exact_cover_recursive.should == nil
137
- end
138
129
  end
139
130
 
140
131
  context 'given a hexadoku puzzle' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: doku
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-02-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: backports
16
- requirement: &21737000 !ruby/object:Gem::Requirement
16
+ requirement: &12242900 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *21737000
24
+ version_requirements: *12242900
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &21736400 !ruby/object:Gem::Requirement
27
+ requirement: &12241680 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *21736400
35
+ version_requirements: *12241680
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: bundler
38
- requirement: &21735640 !ruby/object:Gem::Requirement
38
+ requirement: &12240840 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *21735640
46
+ version_requirements: *12240840
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: jeweler
49
- requirement: &21734260 !ruby/object:Gem::Requirement
49
+ requirement: &12256480 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 1.6.2
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *21734260
57
+ version_requirements: *12256480
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rcov
60
- requirement: &21733260 !ruby/object:Gem::Requirement
60
+ requirement: &12255860 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *21733260
68
+ version_requirements: *12255860
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: yard
71
- requirement: &21751640 !ruby/object:Gem::Requirement
71
+ requirement: &12255300 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *21751640
79
+ version_requirements: *12255300
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: watchr
82
- requirement: &21750220 !ruby/object:Gem::Requirement
82
+ requirement: &12253280 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *21750220
90
+ version_requirements: *12253280
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: ruby-prof
93
- requirement: &21749120 !ruby/object:Gem::Requirement
93
+ requirement: &12251880 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ! '>='
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: '0'
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *21749120
101
+ version_requirements: *12251880
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: linecache19
104
- requirement: &21747360 !ruby/object:Gem::Requirement
104
+ requirement: &12250680 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ! '>='
@@ -109,10 +109,10 @@ dependencies:
109
109
  version: '0'
110
110
  type: :development
111
111
  prerelease: false
112
- version_requirements: *21747360
112
+ version_requirements: *12250680
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: ruby-debug-base19
115
- requirement: &21746120 !ruby/object:Gem::Requirement
115
+ requirement: &12249640 !ruby/object:Gem::Requirement
116
116
  none: false
117
117
  requirements:
118
118
  - - ! '>='
@@ -120,10 +120,10 @@ dependencies:
120
120
  version: 0.11.26
121
121
  type: :development
122
122
  prerelease: false
123
- version_requirements: *21746120
123
+ version_requirements: *12249640
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: ruby-debug19
126
- requirement: &21744820 !ruby/object:Gem::Requirement
126
+ requirement: &12264740 !ruby/object:Gem::Requirement
127
127
  none: false
128
128
  requirements:
129
129
  - - ! '>='
@@ -131,7 +131,7 @@ dependencies:
131
131
  version: '0'
132
132
  type: :development
133
133
  prerelease: false
134
- version_requirements: *21744820
134
+ version_requirements: *12264740
135
135
  description: ! 'This gem allows you to represent Sudoku-like puzzles
136
136
 
137
137
  (Sudoku, Hexadoku, and Hexamurai) as objects and find