新手问题 如何解决 stack level too deep (SystemStackError) 的问题

proxhotdog · 2013年02月02日 · 最后由 proxhotdog 回复于 2013年02月03日 · 13053 次阅读

最近在用 recursive backtracking 写数独 (sudoku) solver,但调试的时候就出现stack level too deep (SystemStackError) 的问题,不知如何解决!

命令:ruby sudoku.rb < puzzle.txt

puzzle.txt 内容:

030090070
004800500
000001006
000000002
005406800
100000000
700200000
008003400
090070060

到 37 行是都会有这问题 以下是完整代码:

UNASSIGNED = 0
N = 9
problem = ''

while line = gets                               # read the txt file (puzzle)
  problem += line.chomp
end

problem = problem.split('').map(&:to_i).each_slice(9).to_a  # convert the puzzle into an 2-D integer array
grid = problem.dup

def FindUnassignedLocation(grid, row, col)
   0.upto(N-1) do |x|
    0.upto(N-1) do |y|
      if grid[x][y] == UNASSIGNED then return true end
    end
  end
  return false
end

def UsedInRow(grid, row, num)
  0.upto(N-1) do |col|
    if grid[row][col] == num then return true end
  end
  return false
end

def UsedInCol(grid, col, num)
  9.times do |row|
    if grid[row][col] == num then return true end
  end
  return false
end

def UsedInBox(grid, boxStartRow, boxStartCol, num)
  0.upto(2) do |row|
    0.upto(2) do |col|
      if grid[row+boxStartRow][col+boxStartCol] == num then
        return true
      end
    end
  end
  return false
end

def isSafe(grid, row, col, num)
  return !UsedInRow(grid, row, num) && !UsedInCol(grid, col, num) && !UsedInBox(grid, row - row%3, col - col%3, num)
end

def SolveSudoku(grid)
  row, col = 0, 0

  if !FindUnassignedLocation(grid, row, col) then
    return true
  end

  1.upto(9) { |num|                 # trying from 1 to 9
    if (isSafe(grid, row, col, num)) then
      grid[row][col] = num

      if SolveSudoku(grid) then             # stop when solved
        return true
      end

      grid[row][col] = UNASSIGNED       # undo and try again
    end
  }

    return false                    # this triggers backtracking
end

def printGrid(grid)
  grid.each {|s| p s}
end

if SolveSudoku(grid) == true then
  printGrid(grid)
else
  puts("No solution!")
end

改成迭代算法

死循环了。

Ruby uses the C stack so your options include using ulimit or compiling Ruby with some compiler/linker stack size flag. Tail recursion is yet to be implemented and Ruby's current support for recursion isn't so great. As cool and elegant recursion is, you might want to consider coping with the language's limitations and writing your code in a different way.

http://stackoverflow.com/questions/242617/how-to-increase-stack-size-for-a-ruby-app-recursive-app-getting-stack-level-to

row, col = 0, 0

一直都在 0, 0 跑不下去,死循环了

simple fix:

def FindUnassignedLocation(grid)
   0.upto(N-1) do |x|
    0.upto(N-1) do |y|
      if grid[x][y] == UNASSIGNED then return x,y end
    end
  end
  return false
end

...

def SolveSudoku(grid)
  row, col = FindUnassignedLocation(grid)
  return true unless row

...

感激不盡啊!!

需要 登录 后方可回复, 如果你还没有账号请 注册新账号