I was required to implement the code to a spec file I was provided in Ruby. I was rejected with the message "The quality of your code isn't sufficient for this position". Can you please tell me what can be improved in order to achieve higher quality?
game_board_spec.rb
(file provided)
require './game'
require './game_board'
describe GameBoard do
it "should correctly solve the board" do
@game = Game.new
# Each '0' is a blank cell
@game.load_board 0, 0, 8, 3, 4, 2, 9, 0, 0,
0, 0, 9, 0, 0, 0, 7, 0, 0,
4, 0, 0, 0, 0, 0, 0, 0, 3,
0, 0, 6, 4, 7, 3, 2, 0, 0,
0, 3, 0, 0, 0, 0, 0, 1, 0,
0, 0, 2, 8, 5, 1, 6, 0, 0,
7, 0, 0, 0, 0, 0, 0, 0, 8,
0, 0, 4, 0, 0, 0, 1, 0, 0,
0, 0, 3, 6, 9, 7, 5, 0, 0
@solved_board = GameBoard.new 6, 7, 8, 3, 4, 2, 9, 5, 1,
3, 2, 9, 1, 8, 5, 7, 6, 4,
4, 5, 1, 7, 6, 9, 8, 2, 3,
5, 1, 6, 4, 7, 3, 2, 8, 9,
8, 3, 7, 9, 2, 6, 4, 1, 5,
9, 4, 2, 8, 5, 1, 6, 3, 7,
7, 6, 5, 2, 1, 4, 3, 9, 8,
2, 9, 4, 5, 3, 8, 1, 7, 6,
1, 8, 3, 6, 9, 7, 5, 4, 2
@game.solve.should == @solved_board
end
it "should correctly solve the board" do
@game = Game.new
# Each '0' is a blank cell
@game.load_board 0, 0, 4, 0, 0, 0, 5, 0, 0,
0, 7, 0, 2, 0, 0, 3, 6, 0,
8, 0, 0, 0, 0, 1, 0, 0, 0,
6, 2, 9, 0, 0, 0, 0, 3, 0,
0, 0, 0, 0, 6, 0, 0, 0, 0,
0, 4, 0, 0, 0, 0, 6, 1, 8,
0, 0, 0, 7, 0, 0, 0, 0, 6,
0, 1, 3, 0, 0, 4, 0, 2, 0,
0, 0, 2, 0, 0, 0, 4, 0, 0
@solved_board = GameBoard.new 2, 3, 4, 9, 7, 6, 5, 8, 1,
9, 7, 1, 2, 8, 5, 3, 6, 4,
8, 5, 6, 4, 3, 1, 2, 9, 7,
6, 2, 9, 1, 4, 8, 7, 3, 5,
1, 8, 5, 3, 6, 7, 9, 4, 2,
3, 4, 7, 5, 9, 2, 6, 1, 8,
4, 9, 8, 7, 2, 3, 1, 5, 6,
7, 1, 3, 6, 5, 4, 8, 2, 9,
5, 6, 2, 8, 1, 9, 4, 7, 3
@game.solve.should == @solved_board
end
end
My Solution:
game_board.rb
require 'matrix'
class GameBoard
attr_accessor :board
def initialize(*params)
@board = Matrix[ *params.each_slice(9).to_a ]
end
def ==(game_board)
return false unless game_board.respond_to? 'board'
self.board == game_board.board
end
end
game.rb
require './game_board'
class Game
attr_reader :game_board
attr_reader :number_set
def initialize
@number_set = [*(0..9)]
end
def load_board(*params)
@game_board = GameBoard.new(*params)
end
def solve
solve_game(game_board.board)
game_board
end
private
def solve_game(board)
if is_solved?(board)
game_board.board = board
return true
end
for i in 0..8 #traverse rows
available_row_choices = number_set - board.row(i).to_a
for j in 0..8 #traverse columns
if board[i,j] == 0
available_col_choices = number_set - board.column(j).to_a
available_pos_choices = available_row_choices &
available_col_choices &
available_block_choices(board, [i,j])
available_pos_choices.each do |choice|
updated_board = update_board(board, [i,j], choice)
return true if solve_game(updated_board)
end
return false
end #unless
end # for j
end # for i
end # solve_game
def update_board(board, position, value)
tmp_board = board.to_a
tmp_board[position.first][position.last] = value
Matrix[ *tmp_board ]
end
def available_block_choices(board, position)
block = get_block(board, position)
number_set - block.to_a.flatten.select{|e| e != 0}
end
def get_block(board, position)
index_i = (position.first / 3) * 3
index_j = (position.last / 3) * 3
board.minor(index_i..(index_i+2), index_j..(index_j+2))
end
def is_solved?(board)
board.find_index(0).nil?
end
end # class