class SlidingPuzzle

Attributes

max_column[RW]
max_row[RW]
tiles[W]

Public Class Methods

new(*tiles) click to toggle source
# File lib/sliding_puzzle/base.rb, line 14
def initialize(*tiles)
  self.tiles = flatten_tiles(tiles)
  self.max_row = @tiles.size - 1
  self.max_column = @tiles.first.size - 1

  must_be_rectangular!
  must_contain_one_blank!
end
oracle(goal_state) click to toggle source
# File lib/sliding_puzzle/base.rb, line 2
def self.oracle(goal_state)
  Oracle.lookup(goal_state)
end
precompute(goal_state, **options) click to toggle source
# File lib/sliding_puzzle/base.rb, line 6
def self.precompute(goal_state, **options)
  Oracle.precompute(goal_state, **options)
end
read(path) click to toggle source
# File lib/sliding_puzzle/base.rb, line 10
def self.read(path)
  Oracle.read(path)
end

Public Instance Methods

==(other) click to toggle source
# File lib/sliding_puzzle/base.rb, line 94
def ==(other)
  tiles == other.tiles
end
Also aliased as: eql?
clone() click to toggle source
# File lib/sliding_puzzle/base.rb, line 44
def clone
  self.class.new(*tiles)
end
eql?(other)
Alias for: ==
find(number) click to toggle source
# File lib/sliding_puzzle/base.rb, line 84
def find(number)
  tiles.each.with_index do |numbers, row|
    numbers.each.with_index do |n, column|
      return [row, column] if n == number
    end
  end

  nil
end
get(row, column) click to toggle source
# File lib/sliding_puzzle/base.rb, line 80
def get(row, column)
  @tiles[row][column]
end
hash() click to toggle source
# File lib/sliding_puzzle/base.rb, line 100
def hash
  tiles.hash
end
moves() click to toggle source
# File lib/sliding_puzzle/base.rb, line 52
def moves
  row, column = find(0)
  moves = []

  moves.push(:left) unless column == max_column
  moves.push(:right) unless column.zero?
  moves.push(:up) unless row == max_row
  moves.push(:down) unless row.zero?

  moves
end
print() click to toggle source
scramble(moves: 100) click to toggle source
# File lib/sliding_puzzle/base.rb, line 72
def scramble(moves: 100)
  clone.scramble!(moves: moves)
end
scramble!(moves: 100) click to toggle source
# File lib/sliding_puzzle/base.rb, line 64
def scramble!(moves: 100)
  moves.times do
    slide!(self.moves.sample)
  end

  self
end
slide(direction) click to toggle source
# File lib/sliding_puzzle/base.rb, line 40
def slide(direction)
  clone.slide!(direction)
end
slide!(direction) click to toggle source
# File lib/sliding_puzzle/base.rb, line 23
def slide!(direction)
  unless moves.include?(direction)
    raise InvalidMoveError, "unable to slide #{direction}"
  end

  x1, y1 = find(0)
  x2, y2 = x1, y1

  y2 += 1 if direction == :left
  y2 -= 1 if direction == :right
  x2 += 1 if direction == :up
  x2 -= 1 if direction == :down

  @tiles[x1][y1], @tiles[x2][y2] = @tiles[x2][y2], @tiles[x1][y1]
  self
end
tiles() click to toggle source
# File lib/sliding_puzzle/base.rb, line 76
def tiles
  JSON.parse(JSON.generate(@tiles))
end

Private Instance Methods

flatten_tiles(tiles) click to toggle source
# File lib/sliding_puzzle/base.rb, line 106
def flatten_tiles(tiles)
  if tiles[0].is_a?(Array) && tiles[0][0].is_a?(Array)
    tiles.flatten(1)
  else
    tiles
  end
end
must_be_rectangular!() click to toggle source
# File lib/sliding_puzzle/base.rb, line 114
def must_be_rectangular!
  sizes = tiles.map(&:size)

  if sizes.uniq.size > 1
    raise NotRectangularError, "puzzle must be rectangular"
  end
end
must_contain_one_blank!() click to toggle source
# File lib/sliding_puzzle/base.rb, line 122
def must_contain_one_blank!
  blanks = tiles.flatten.count(0)

  unless blanks == 1
    raise BlankError, "puzzle must contain a single blank"
  end
end