如何从递归方法中删除剩余的堆栈

时间:2014-12-31 05:25:38

标签: ruby recursion stack

我使用递归方法编写了一个Sudoku解算器。它看起来像这样:

def solve(index = @board.key("-"), board_so_far = @board)
  if !board_so_far.has_value?("-")
    @solution = board_so_far
    return true
  elsif available_nums_to_place(index, board_so_far).any?
    available_nums_to_place(index, board_so_far).each do |num|
      board_so_far[index] = num
      solve(board_so_far.key("-"), Marshal.load(Marshal.dump(board_so_far)))
    end
  else
    return false
  end
end

一旦找到解决方案,它将在@solution中保存解决方案。当发生这种情况时,我想停止所有剩余的递归。现在,solve方法在通过解释其他堆栈已经找到解决方案之后需要的时间大约是它所需的两倍。我如何杀死其余的堆栈?我使用break代替我的return,解释器抛出

  

无效的break runner.rb:编译错误(SyntaxError)

错误。

更新1

以下是我希望足够清晰的完整代码,无需进一步解释。

class Sudoku

  def initialize(board_string)
    @board = to_hash(board_string)
    @solution = {}
  end

private

  def to_hash(board_string)
    output_hash = {}
    board_array = board_string.split("")
    board_array.each_with_index do |char,i|
      char == "-" ? output_hash[i] = "-" : output_hash[i] = char.to_i
    end
    output_hash
  end

  def row_number(index)
    row_number = index/9
  end

  def column_number(index)
    column_number = index % 9
  end

  def indices_of_row(index)
    starting_index = row_number(index) * 9
    row_indices = (starting_index...starting_index + 9).to_a
    row_indices.delete(index)
    row_indices
  end

  def indices_of_column(index)
    column_indices = 0.upto(8).map { |row| row * 9 + column_number(index) }
    column_indices.delete(index)
    column_indices
  end

  def grid_coords(index)
    [row_number(index) / 3, column_number(index) / 3]
  end

  def top_left_corner_index(coords)
    coords[1] * 3 + coords[0] * 27
  end

  def indices_of_grid(index)
    i = top_left_corner_index(grid_coords(index))
    position_adjustment = [0,1,2,9,10,11,18,19,20]
    indices_of_grid = position_adjustment.map { |num| num + i }
    indices_of_grid.delete(index)
    indices_of_grid
  end

  def available_nums(indices, board)
    value_array = indices.map { |index| board[index] }
    complete = (1..9).to_a
    unplaced_nums = complete - value_array
  end

  def available_nums_to_place(index, board)
    row_values = available_nums( indices_of_row(index), board )
    column_values = available_nums( indices_of_column(index), board )
    grid_values = available_nums( indices_of_grid(index), board )
  end

public

  def solve(index = @board.key("-"), board_so_far = @board)

    if !board_so_far.has_value?("-")
      @solution = board_so_far
      return true
    elsif available_nums_to_place(index, board_so_far).any?
      available_nums_to_place(index, board_so_far).each do |num|
        board_so_far[index] = num
        solve(board_so_far.key("-"), Marshal.load(Marshal.dump(board_so_far)))
      end
    else
      return false
    end
  end

  # Returns a string representing the current state of the board
  def to_s
    puts "+-----------------------+"
    puts "|        SUDOKU!        |"
    puts "+-----------------------+"
    three_rows = @solution.values.each_slice(27).map { |rows| rows }
    three_rows.each do |three_rows|
      three_rows.each_slice(9) do |row|
        printf("| %s %s %s | %s %s %s | %s %s %s |\n", row[0], row[1], row[2],  row[3], row[4], row[5], row[6], row[7], row[8] )
      end
      puts "|-----------------------|\n"
    end
  end
end

sudoku_strings = File.read('sudoku_puzzles.txt')
sudoku_arrays = sudoku_strings.split("\n")

sudokus_to_solve = sudoku_arrays.take(1)

sudokus = sudokus_to_solve.map do |unsolved_board|
  Sudoku.new(unsolved_board)
end

sudokus.each do |sudoku|
  sudoku.solve
  sudoku.to_s
end

1 个答案:

答案 0 :(得分:0)

更改行

solve(board_so_far.key("-"), Marshal.load(Marshal.dump(board_so_far)))

if solve(board_so_far.key("-"), Marshal.load(Marshal.dump(board_so_far)))
  return true
end