Class: SlidingPuzzle::Oracle
- Inherits:
-
Object
- Object
- SlidingPuzzle::Oracle
- Defined in:
- lib/sliding_puzzle/oracle.rb
Constant Summary collapse
- OPPOSITES =
{ left: :right, right: :left, up: :down, down: :up, }
Class Method Summary collapse
- .basename(puzzle) ⇒ Object
- .lookup(goal_state) ⇒ Object
- .precompute(goal_state, debug: false) ⇒ Object
- .precompute_all(max_tiles: 8, directory: "oracles", debug: false) ⇒ Object
- .read(path) ⇒ Object
Instance Method Summary collapse
-
#initialize(lookup_table) ⇒ Oracle
constructor
A new instance of Oracle.
- #solve(sliding_puzzle) ⇒ Object
- #write(path) ⇒ Object
Constructor Details
#initialize(lookup_table) ⇒ Oracle
Returns a new instance of Oracle.
72 73 74 |
# File 'lib/sliding_puzzle/oracle.rb', line 72 def initialize(lookup_table) self.lookup_table = lookup_table end |
Class Method Details
.basename(puzzle) ⇒ Object
68 69 70 |
# File 'lib/sliding_puzzle/oracle.rb', line 68 def self.basename(puzzle) puzzle.tiles.map { |row| row.join(",") }.join(":") end |
.lookup(goal_state) ⇒ Object
61 62 63 64 65 66 |
# File 'lib/sliding_puzzle/oracle.rb', line 61 def self.lookup(goal_state) filename = "#{basename(goal_state)}.dat" path = File.("#{__dir__}/../../oracles/#{filename}") read(path) if File.exist?(path) end |
.precompute(goal_state, debug: false) ⇒ Object
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/sliding_puzzle/oracle.rb', line 10 def self.precompute(goal_state, debug: false) goal_state = goal_state.clone queue = [goal_state] lookup_table = { goal_state => :goal } until queue.empty? puts "queue size: #{queue.size}" if debug puzzle = queue.shift puzzle.moves.each do |direction| next_puzzle = puzzle.(direction) unless lookup_table[next_puzzle] lookup_table[next_puzzle] = OPPOSITES[direction] queue.push(next_puzzle) end end end new(lookup_table) end |
.precompute_all(max_tiles: 8, directory: "oracles", debug: false) ⇒ Object
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 |
# File 'lib/sliding_puzzle/oracle.rb', line 33 def self.precompute_all(max_tiles: 8, directory: "oracles", debug: false) FileUtils.mkdir_p("oracles") 1.upto(5) do |rows| 1.upto(5) do |columns| number_of_tiles = rows * columns - 1 next if number_of_tiles > max_tiles numbers = 1.upto(number_of_tiles).to_a 0.upto(number_of_tiles) do |position| numbers_with_blank = numbers.dup.insert(position, 0) tiles = numbers_with_blank.each_slice(columns).to_a goal_state = SlidingPuzzle.new(tiles) path = "#{directory}/#{basename(goal_state)}.dat" print "Precomputing #{path}... " if debug oracle = precompute(goal_state) oracle.write(path) puts "Done." if debug end end end end |
.read(path) ⇒ Object
98 99 100 101 102 103 |
# File 'lib/sliding_puzzle/oracle.rb', line 98 def self.read(path) gzip = File.binread(path) data = Zlib::Inflate.inflate(gzip) Marshal.load(data) end |
Instance Method Details
#solve(sliding_puzzle) ⇒ Object
76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/sliding_puzzle/oracle.rb', line 76 def solve(sliding_puzzle) moves = [] next_puzzle = sliding_puzzle loop do direction = lookup_table[next_puzzle] return nil unless direction return moves if direction == :goal moves.push(direction) next_puzzle = next_puzzle.(direction) end end |
#write(path) ⇒ Object
91 92 93 94 95 96 |
# File 'lib/sliding_puzzle/oracle.rb', line 91 def write(path) data = Marshal.dump(self) gzip = Zlib::Deflate.deflate(data) File.open(path, "wb") { |f| f.write(gzip) } end |