From: John L. <jr...@us...> - 2006-05-31 21:26:37
|
Update of /cvsroot/wxlua/wxLua/samples In directory sc8-pr-cvs9.sourceforge.net:/tmp/cvs-serv27525/wxLua/samples Modified Files: wxluasudoku.wx.lua Log Message: more cleanup and added function to verify unique solution Index: wxluasudoku.wx.lua =================================================================== RCS file: /cvsroot/wxlua/wxLua/samples/wxluasudoku.wx.lua,v retrieving revision 1.50 retrieving revision 1.51 diff -C2 -d -r1.50 -r1.51 *** wxluasudoku.wx.lua 31 May 2006 06:06:21 -0000 1.50 --- wxluasudoku.wx.lua 31 May 2006 21:26:32 -0000 1.51 *************** *** 21,24 **** --- 21,25 ---- -- ============================================================================ -- A simple function to implement "cond ? A : B", eg "result = iff(cond, A, B)" + -- note all terms must be able to be evaluated function iff(cond, A, B) if cond then return A else return B end end *************** *** 171,176 **** -- given the upper left cell of block you can iterate through the block using ! -- for n = 1, 9 do cell = block_cell + sudoku.LinearBlockCells[n] ... end ! sudoku.LinearBlockCells = { 0, 0, 0, 6, 6, 6, 12, 12, 12 } -- ============================================================================ --- 172,204 ---- -- given the upper left cell of block you can iterate through the block using ! -- for n = 1, 9 do cell = n + block_cell + sudoku.LinearBlockCellTable[n] ... end ! sudoku.LinearBlockCellTable = { -1, -1, -1, 5, 5, 5, 11, 11, 11 } ! ! sudoku.CellToRowTable = {} ! sudoku.CellToColTable = {} ! sudoku.BlockToRowTable = {} ! sudoku.BlockToColTable = {} ! sudoku.CellToBlockTable = {} ! sudoku.BlockToCellTable = {} ! ! for cell = 1, 81 do ! local row = math.floor(cell/9.1)+1 ! local col = cell-(row-1)*9 ! sudoku.CellToRowTable[cell] = row ! sudoku.CellToColTable[cell] = col ! ! local block_row = math.floor(row/3.5)+1 ! local block_col = math.floor(col/3.5)+1 ! sudoku.CellToBlockTable[cell] = (block_row-1)*3 + block_col ! end ! ! for block = 1, 9 do ! local row = math.floor(block/3.5)*3+1 ! local col = math.fmod(block-1,3)*3+1 ! sudoku.BlockToRowTable[block] = row ! sudoku.BlockToColTable[block] = col ! ! sudoku.BlockToCellTable[block] = (row-1)*9 + col ! end -- ============================================================================ *************** *** 179,189 **** local sudokuTable = { ! values = {}, -- array (1-81) of values[cell#] = value (0 means unset) row_values = {}, -- array (1-9) of values[row#][value] = { cell1, cell2... } col_values = {}, -- array (1-9) of values[col#][value] = { cell1, cell2... } block_values = {}, -- array (1-9) of values[block#][value] = { cell1, cell2... } ! possible = {}, -- possible values per cell, possible[cell# 1-81] = { val1, val2... } ! invalid = {}, -- array (1-81) of known invalid[cell#] = true/nil ! flags = {} -- extra flags for puzzle, eg. ELIMINATE_NAKED_PAIRS } --- 207,217 ---- local sudokuTable = { ! values = {}, -- array (1-81) of values[cell#] = value (0 means unset) row_values = {}, -- array (1-9) of values[row#][value] = { cell1, cell2... } col_values = {}, -- array (1-9) of values[col#][value] = { cell1, cell2... } block_values = {}, -- array (1-9) of values[block#][value] = { cell1, cell2... } ! possible = {}, -- possible values per cell, possible[cell# 1-81] = { val1, val2... } ! invalid = {}, -- array (1-81) of known invalid[cell#] = true/nil ! flags = {} -- extra flags for puzzle, eg. ELIMINATE_NAKED_PAIRS } *************** *** 346,358 **** -- Convert a linear cell index (1-81) into a row, col cell index (1-9) function sudoku.CellToRowCol(cell) ! local row = math.floor(cell/9.1)+1 ! local col = cell-(row-1)*9 ! return row, col end function sudoku.CellToRow(cell) ! return math.floor(cell/9.1)+1 end function sudoku.CellToCol(cell) ! return cell-math.floor(cell/9.1)*9 end --- 374,384 ---- -- Convert a linear cell index (1-81) into a row, col cell index (1-9) function sudoku.CellToRowCol(cell) ! return sudoku.CellToRowTable[cell], sudoku.CellToColTable[cell] end function sudoku.CellToRow(cell) ! return sudoku.CellToRowTable[cell] end function sudoku.CellToCol(cell) ! return sudoku.CellToColTable[cell] end *************** *** 378,411 **** -- Convert a row, col cell index (1-9) into the linear block number (1-9) function sudoku.RowColToBlock(row, col) ! local block_row = math.floor(row/3.5)+1 ! local block_col = math.floor(col/3.5)+1 ! return (block_row-1)*3 + block_col end -- Get the block (1-9) that this cell (1-81) is in function sudoku.CellToBlock(cell) ! local row, col = sudoku.CellToRowCol(cell) ! return sudoku.RowColToBlock(row, col) end -- Get the upper left cell of this block function sudoku.BlockToCell(block) ! return sudoku.RowColToCell(math.floor(block/3.5)*3+1, math.fmod(block-1,3)*3+1) end -- Convert a linear block index (1-9) into upper left row, col cell index (1-9) function sudoku.BlockToRowCol(block) ! local row = math.floor(block/3.5)*3+1 ! local col = math.fmod(block-1,3)*3+1 ! return row, col end function sudoku.BlockToRow(block) ! return math.floor(block/3.5)*3+1 end function sudoku.BlockToCol(block) ! return math.fmod(block-1,3)*3+1 end -- Get the upper left row, col cell of the block given by row, col function sudoku.RowColToBlockRowCol(row, col) ! local block_row = math.floor(row/3.5)*3+1 ! local block_col = math.floor(col/3.5)*3+1 ! return block_row, block_col end --- 404,431 ---- -- Convert a row, col cell index (1-9) into the linear block number (1-9) function sudoku.RowColToBlock(row, col) ! return sudoku.CellToBlockTable[sudoku.RowColToCell(row, col)] end -- Get the block (1-9) that this cell (1-81) is in function sudoku.CellToBlock(cell) ! return sudoku.CellToBlockTable[cell] end -- Get the upper left cell of this block function sudoku.BlockToCell(block) ! return sudoku.BlockToCellTable[block] end -- Convert a linear block index (1-9) into upper left row, col cell index (1-9) function sudoku.BlockToRowCol(block) ! return sudoku.BlockToRowTable[block], sudoku.BlockToColTable[block] end function sudoku.BlockToRow(block) ! return sudoku.BlockToRowTable[block] end function sudoku.BlockToCol(block) ! return sudoku.BlockToColTable[block] end -- Get the upper left row, col cell of the block given by row, col function sudoku.RowColToBlockRowCol(row, col) ! local block = sudoku.RowColToBlock(row, col) ! return sudoku.BlockToRowTable[block], sudoku.BlockToColTable[block] end *************** *** 417,422 **** -- Set the cell value at a specific row, col function sudoku.SetValue(row, col, value, sudokuTable) ! local cell = sudoku.RowColToCell(row, col) ! local block = sudoku.RowColToBlock(row, col) local old_value = sudokuTable.values[cell] --- 437,442 ---- -- Set the cell value at a specific row, col function sudoku.SetValue(row, col, value, sudokuTable) ! local cell = sudoku.RowColToCell(row, col) ! local block = sudoku.CellToBlock(cell) local old_value = sudokuTable.values[cell] *************** *** 513,519 **** -- Can this value be put into this cell given the other existing values? function sudoku.IsValidValue(row, col, value, sudokuTable) ! if sudoku.GetRowValues(row, sudokuTable)[value] or ! sudoku.GetColValues(col, sudokuTable)[value] or ! sudoku.GetBlockValues(sudoku.RowColToBlock(row, col), sudokuTable)[value] then return false end --- 533,539 ---- -- Can this value be put into this cell given the other existing values? function sudoku.IsValidValue(row, col, value, sudokuTable) ! if sudokuTable.row_values[row][value] or ! sudokuTable.col_values[col][value] or ! sudokuTable.block_values[sudoku.RowColToBlock(row, col)][value] then return false end *************** *** 528,532 **** for n = 1, 9 do ! for i, cell_table in pairs(sudoku.GetRowValues(n, sudokuTable)) do if TableCount(cell_table) > 1 then for j, cell in pairs(cell_table) do --- 548,552 ---- for n = 1, 9 do ! for i, cell_table in pairs(sudokuTable.row_values[n]) do if TableCount(cell_table) > 1 then for j, cell in pairs(cell_table) do *************** *** 535,539 **** end end ! for i, cell_table in pairs(sudoku.GetColValues(n, sudokuTable)) do if TableCount(cell_table) > 1 then for j, cell in pairs(cell_table) do --- 555,559 ---- end end ! for i, cell_table in pairs(sudokuTable.col_values[n]) do if TableCount(cell_table) > 1 then for j, cell in pairs(cell_table) do *************** *** 542,546 **** end end ! for i, cell_table in pairs(sudoku.GetBlockValues(n, sudokuTable)) do if TableCount(cell_table) > 1 then for j, cell in pairs(cell_table) do --- 562,566 ---- end end ! for i, cell_table in pairs(sudokuTable.block_values[n]) do if TableCount(cell_table) > 1 then for j, cell in pairs(cell_table) do *************** *** 587,609 **** -- Remove a possible values from the row, col, block -- if exceptTable then don't remove it from exceptTable[cell#] = true ! function sudoku.RemovePossibleAll(row, col, value, sudokuTable, exceptTable) exceptTable = exceptTable or {} local cell local block_cell = sudoku.BlockToCell(sudoku.RowColToBlock(row, col)) for rcb = 1, 9 do cell = sudoku.RowColToCell(rcb, col) ! if not exceptTable[cell] then ! sudokuTable = sudoku.RemoveCellPossible(cell, value, sudokuTable) end cell = sudoku.RowColToCell(row, rcb) ! if not exceptTable[cell] then ! sudokuTable = sudoku.RemoveCellPossible(cell, value, sudokuTable) end ! cell = rcb - 1 + block_cell + sudoku.LinearBlockCells[rcb] ! if not exceptTable[cell] then ! sudokuTable = sudoku.RemoveCellPossible(cell, value, sudokuTable) end end --- 607,633 ---- -- Remove a possible values from the row, col, block -- if exceptTable then don't remove it from exceptTable[cell#] = true ! function sudoku.RemovePossibleAll(row, col, value, sudokuTable, exceptTable, break_empty) exceptTable = exceptTable or {} local cell local block_cell = sudoku.BlockToCell(sudoku.RowColToBlock(row, col)) + break_empty = break_empty or false for rcb = 1, 9 do cell = sudoku.RowColToCell(rcb, col) ! if (not exceptTable[cell]) and sudokuTable.possible[cell][value] then ! sudokuTable.possible[cell][value] = nil ! if break_empty and (not sudoku.HasCellValue(cell, sudokuTable)) and TableIsEmpty(sudokuTable.possible[cell]) then return nil end end cell = sudoku.RowColToCell(row, rcb) ! if (not exceptTable[cell]) and sudokuTable.possible[cell][value] then ! sudokuTable.possible[cell][value] = nil ! if break_empty and (not sudoku.HasCellValue(cell, sudokuTable)) and TableIsEmpty(sudokuTable.possible[cell]) then return nil end end ! cell = rcb + block_cell + sudoku.LinearBlockCellTable[rcb] ! if (not exceptTable[cell]) and sudokuTable.possible[cell][value] then ! sudokuTable.possible[cell][value] = nil ! if break_empty and (not sudoku.HasCellValue(cell, sudokuTable)) and TableIsEmpty(sudokuTable.possible[cell]) then return nil end end end *************** *** 655,681 **** end - -- For row, col, block check to see that there is at least one possible value - -- for any empty cells, returns true/false - function sudoku.HasPossibleForEmptyCellsAll(row, col, sudokuTable) - local cell - local block_cell = sudoku.BlockToCell(sudoku.RowColToBlock(row, col)) - - for rcb = 1, 9 do - cell = sudoku.RowColToCell(rcb, col) - if (not sudoku.HasCellValue(cell, sudokuTable)) and - TableIsEmpty(sudokuTable.possible[cell]) then return false end - - cell = sudoku.RowColToCell(row, rcb) - if (not sudoku.HasCellValue(cell, sudokuTable)) and - TableIsEmpty(sudokuTable.possible[cell]) then return false end - - cell = rcb - 1 + block_cell + sudoku.LinearBlockCells[rcb] - if (not sudoku.HasCellValue(cell, sudokuTable)) and - TableIsEmpty(sudokuTable.possible[cell]) then return false end - end - - return true - end - -- Get the count of all possible values for rows, cols, and blocks -- returns 3 tables row_possible[row#][value] = #times possible value occurs in row --- 679,682 ---- *************** *** 1248,1251 **** --- 1249,1253 ---- function sudoku.DoSolveBruteForce(sudokuTable, backwards, simpleTable, guesses, cell) local s = simpleTable + local g, empty_possible if sudoku.SolveBruteForceHook then *************** *** 1268,1289 **** s = sudoku.RemoveCellPossible(cell, k, s) ! -- start a new table and test out this guess w/ new table ! local s1 = sudoku.RemovePossibleAll(row, col, k, TableCopy(s)) ! local g ! -- don't use SetValue since we only care about possible s1.values[cell] = k --sudoku.SetValue(row, col, k, s1) guesses[cell] = guesses[cell] + 1 guesses.current = guesses.current + 1 - if sudoku.HasPossibleForEmptyCellsAll(row, col, s1) then - - s1, g = sudoku.DoSolveBruteForce(sudokuTable, backwards, s1, guesses, cell+1) - -- if s1 then success! we're all done if s1 then ! local s2 = TableCopy(sudokuTable) ! s2 = sudoku.SetValues(s1.values, s2) ! return s2, g ! end end end --- 1270,1292 ---- s = sudoku.RemoveCellPossible(cell, k, s) ! local s1 = TableCopy(s) -- don't use SetValue since we only care about possible s1.values[cell] = k --sudoku.SetValue(row, col, k, s1) + + -- start a new table and test out this guess w/ new table + s1 = sudoku.RemovePossibleAll(row, col, k, s1, nil, true) + guesses[cell] = guesses[cell] + 1 guesses.current = guesses.current + 1 if s1 then ! s1, g = sudoku.DoSolveBruteForce(sudokuTable, backwards, s1, guesses, cell+1) ! -- if s1 then success! we're all done ! if s1 then ! -- copy all original data back and just set the values ! local s2 = TableCopy(sudokuTable) ! s2 = sudoku.SetValues(s1.values, s2) ! return s2, g ! end end end *************** *** 1941,1944 **** --- 1944,1948 ---- ID_SHOW_HIDDENQUADS = NewID(), -- mark hidden quads + ID_VERIFY_PUZZLE = NewID(), ID_ELIMINATE_MENU = NewID(), ID_ELIMINATE_NAKED = NewID(), -- eliminate naked groups *************** *** 2170,2174 **** brush:Delete() ! local sudokuTable = sudokuGUI.GetCurrentGrid() local value_str, is_init = sudokuGUI.GetCellValueString(cell) --- 2174,2178 ---- brush:Delete() ! local sudokuTable = sudokuGUI.GetCurrentTable() local value_str, is_init = sudokuGUI.GetCellValueString(cell) *************** *** 2273,2277 **** local show_errors = sudokuGUI.IsCheckedMenuItem(sudokuGUI.ID_SHOW_ERRORS) if sudokuGUI.IsCheckedMenuItem(sudokuGUI.ID_CREATE) then show_errors = true end ! if show_errors then show_errors = sudokuGUI.GetCurrentGrid().invalid[cell] end local show_mistakes = sudokuGUI.sudokuSolnTable and sudokuGUI.IsCheckedMenuItem(sudokuGUI.ID_SHOW_MISTAKES) --- 2277,2281 ---- local show_errors = sudokuGUI.IsCheckedMenuItem(sudokuGUI.ID_SHOW_ERRORS) if sudokuGUI.IsCheckedMenuItem(sudokuGUI.ID_CREATE) then show_errors = true end ! if show_errors then show_errors = sudokuGUI.GetCurrentTable().invalid[cell] end local show_mistakes = sudokuGUI.sudokuSolnTable and sudokuGUI.IsCheckedMenuItem(sudokuGUI.ID_SHOW_MISTAKES) *************** *** 2465,2469 **** if printer:Print(sudokuGUI.frame, luaPrintout, true) == false then if printer:GetLastError() == wx.wxPRINTER_ERROR then ! wx.wxMessageBox("There was a problem printing.\nPerhaps your current printer is not set correctly?", "wxLuaSudoku Printout", wx.wxOK, sudokuGUI.frame) --- 2469,2474 ---- if printer:Print(sudokuGUI.frame, luaPrintout, true) == false then if printer:GetLastError() == wx.wxPRINTER_ERROR then ! wx.wxMessageBox("There was a problem printing.\n".. ! "Perhaps your current printer is not setup correctly?", "wxLuaSudoku Printout", wx.wxOK, sudokuGUI.frame) *************** *** 2485,2489 **** local result = preview:Ok() if result == false then ! wx.wxMessageBox("There was a problem previewing.\nPerhaps your current printer is not set correctly?", "wxLuaSudoku print preview error", wx.wxOK, sudokuGUI.frame) --- 2490,2495 ---- local result = preview:Ok() if result == false then ! wx.wxMessageBox("There was a problem previewing.\n".. ! "Perhaps your current printer is not setup correctly?", "wxLuaSudoku print preview error", wx.wxOK, sudokuGUI.frame) *************** *** 2791,2799 **** sudokuGUI.sudokuSolnTable = nil -- don't know anymore else ! local s = sudokuGUI.GetCurrentGrid() if (not is_init) and (sudoku.GetCellValue(cell, s) ~= value) then local s = TableCopy(s) s = sudoku.SetValue(row, col, value, s) ! sudokuGUI.AddGrid(s) end end --- 2797,2805 ---- sudokuGUI.sudokuSolnTable = nil -- don't know anymore else ! local s = sudokuGUI.GetCurrentTable() if (not is_init) and (sudoku.GetCellValue(cell, s) ~= value) then local s = TableCopy(s) s = sudoku.SetValue(row, col, value, s) ! sudokuGUI.AddTable(s) end end *************** *** 2802,2816 **** end ! -- Get the current grid to use ! function sudokuGUI.GetCurrentGrid() return sudokuGUI.sudokuTables[sudokuGUI.sudokuTables_pos] end ! -- Set the current grid to this grid ! function sudokuGUI.SetCurrentGrid(sudokuTable) sudokuGUI.sudokuTables[sudokuGUI.sudokuTables_pos] = sudokuTable end ! -- Add a grid to the list of grids, removing any past the current position, -- find possible, and refresh ! function sudokuGUI.AddGrid(sudokuTable) while TableCount(sudokuGUI.sudokuTables) > sudokuGUI.sudokuTables_pos do table.remove(sudokuGUI.sudokuTables) --- 2808,2835 ---- end ! -- Get the initial sudoku table ! function sudokuGUI.GetInitTable() ! return sudokuGUI.sudokuTables[1] ! end ! -- Set the initial sudoku table, clearing all others ! function sudokuGUI.SetInitTable(sudokuTable, solnTable) ! sudokuGUI.sudokuSolnTable = solnTable ! sudokuGUI.sudokuTables_pos = 1 ! sudokuGUI.sudokuTables = {} ! table.insert(sudokuGUI.sudokuTables, sudokuTable) ! sudokuGUI.UpdateTable() -- resets possible and refreshes too ! end ! ! -- Get the current sudoku table to use ! function sudokuGUI.GetCurrentTable() return sudokuGUI.sudokuTables[sudokuGUI.sudokuTables_pos] end ! -- Set the current sudoku table to this table ! function sudokuGUI.SetCurrentTable(sudokuTable) sudokuGUI.sudokuTables[sudokuGUI.sudokuTables_pos] = sudokuTable end ! -- Add a sudoku table to the list of tables, removing any past the current position, -- find possible, and refresh ! function sudokuGUI.AddTable(sudokuTable) while TableCount(sudokuGUI.sudokuTables) > sudokuGUI.sudokuTables_pos do table.remove(sudokuGUI.sudokuTables) *************** *** 2838,2843 **** if sudoku.HasCellValue(cell, sudokuGUI.sudokuTables[1]) then return tostring(sudoku.GetCellValue(cell, sudokuGUI.sudokuTables[1])), true ! elseif sudoku.HasCellValue(cell, sudokuGUI.GetCurrentGrid()) then ! value = tostring(sudoku.GetCellValue(cell, sudokuGUI.GetCurrentGrid())) end --- 2857,2862 ---- if sudoku.HasCellValue(cell, sudokuGUI.sudokuTables[1]) then return tostring(sudoku.GetCellValue(cell, sudokuGUI.sudokuTables[1])), true ! elseif sudoku.HasCellValue(cell, sudokuGUI.GetCurrentTable()) then ! value = tostring(sudoku.GetCellValue(cell, sudokuGUI.GetCurrentTable())) end *************** *** 2857,2861 **** -- Create a new empty puzzle function sudokuGUI.NewPuzzle() ! local ret = wx.wxMessageBox("Clear the current puzzle and start anew?\n".. "Use 'Create' to enter the initial values.", "wxLuaSudoku - New puzzle?", --- 2876,2880 ---- -- Create a new empty puzzle function sudokuGUI.NewPuzzle() ! local ret = wx.wxMessageBox("Clear all the values in the current puzzle and start anew?\n".. "Use 'Create' to enter the initial values.", "wxLuaSudoku - New puzzle?", *************** *** 2864,2873 **** if ret == wx.wxOK then ! sudokuGUI.sudokuSolnTable = nil -- don't know anymore ! local s = sudoku.CreateTable() ! sudokuGUI.sudokuTables_pos = 1 ! sudokuGUI.sudokuTables = {} ! table.insert(sudokuGUI.sudokuTables, s) ! sudokuGUI.UpdateTable() -- resets possible and refreshes too end end --- 2883,2887 ---- if ret == wx.wxOK then ! sudokuGUI.SetInitTable(sudoku.CreateTable(), nil) end end *************** *** 2914,2919 **** local ret = wx.wxMessageBox( "The initial puzzle you've created has invalid values.\n".. ! "Press Ok to correct them before continuing.\n".. ! "If you press cancel then don't blame me if things don't work out for you.", "wxLuaSudoku - Invalid initial puzzle!", wx.wxOK + wx.wxCANCEL + wx.wxICON_ERROR, --- 2928,2933 ---- local ret = wx.wxMessageBox( "The initial puzzle you've created has invalid values.\n".. ! "Press 'Ok' to correct them before continuing.\n".. ! "If you press 'Cancel' don't blame me if things don't work out for you.", "wxLuaSudoku - Invalid initial puzzle!", wx.wxOK + wx.wxCANCEL + wx.wxICON_ERROR, *************** *** 2925,2949 **** end elseif sudokuGUI.IsCheckedMenuItem(sudokuGUI.ID_SHOW_MISTAKES) then ! ! sudokuGUI.sudokuSolnTable = sudokuGUI.SolveBruteForce(sudokuGUI.sudokuTables[1]) ! ! if not sudokuGUI.sudokuSolnTable then ! -- try to make them correct the puzzle ! local ret = wx.wxMessageBox( ! "The initial puzzle you've created cannot be or was not solved ".. ! "and therefore mistakes cannot be marked.\n".. ! "Press Ok to continue 'Creating'.\n".. ! "If you press cancel then showing mistakes will be disabled.", ! "wxLuaSudoku - Invalid initial puzzle", ! wx.wxOK + wx.wxCANCEL + wx.wxICON_ERROR, ! sudokuGUI.frame ) ! ! if ret == wx.wxOK then ! sudokuGUI.CheckMenuItem(sudokuGUI.ID_CREATE, true) ! init = true ! else ! sudokuGUI.CheckMenuItem(sudokuGUI.ID_SHOW_MISTAKES, false) ! end ! end end end --- 2939,2943 ---- end elseif sudokuGUI.IsCheckedMenuItem(sudokuGUI.ID_SHOW_MISTAKES) then ! sudokuGUI.sudokuSolnTable = sudokuGUI.VerifyUniquePuzzle(sudokuGUI.GetInitTable()) end end *************** *** 3047,3061 **** if s1 then ! sudokuGUI.sudokuSolnTable = TableCopy(s) ! ! sudokuGUI.sudokuTables_pos = 1 ! sudokuGUI.sudokuTables = {} ! table.insert(sudokuGUI.sudokuTables, s1) ! sudokuGUI.UpdateTable() -- resets possible and refreshes too break else ret = wx.wxMessageBox( ! "The puzzle was not fully generated.".. ! "Press Ok to continue generating or Cancel to quit.", "wxLuaSudoku - Unfinished generation", wx.wxOK + wx.wxCANCEL + wx.wxICON_ERROR, --- 3041,3050 ---- if s1 then ! sudokuGUI.SetInitTable(s1, TableCopy(s)) break else ret = wx.wxMessageBox( ! "The puzzle was not fully generated. ".. ! "Press 'Ok' to continue generating or 'Cancel' to quit.", "wxLuaSudoku - Unfinished generation", wx.wxOK + wx.wxCANCEL + wx.wxICON_ERROR, *************** *** 3079,3088 **** if s then sudokuGUI.frame:SetTitle("wxLuaSudoku - "..sudokuGUI.fileName) - sudokuGUI.sudokuTables_pos = 1 - sudokuGUI.sudokuTables = {} - table.insert(sudokuGUI.sudokuTables, s) - sudokuGUI.UpdateTable() -- resets possible and refreshes too ! sudokuGUI.sudokuSolnTable = nil -- reset if not TableIsEmpty(sudokuGUI.sudokuTables[1].invalid) then --- 3068,3073 ---- if s then sudokuGUI.frame:SetTitle("wxLuaSudoku - "..sudokuGUI.fileName) ! sudokuGUI.SetInitTable(s, nil) if not TableIsEmpty(sudokuGUI.sudokuTables[1].invalid) then *************** *** 3090,3094 **** local ret = wx.wxMessageBox( "The puzzle you've opened has invalid values.\n".. ! "Press Ok to correct them using 'Create' before continuing.", "wxLuaSudoku - Invalid puzzle", wx.wxOK + wx.wxCANCEL + wx.wxICON_ERROR, --- 3075,3079 ---- local ret = wx.wxMessageBox( "The puzzle you've opened has invalid values.\n".. ! "Press 'Ok' to correct them using 'Create' before continuing.", "wxLuaSudoku - Invalid puzzle", wx.wxOK + wx.wxCANCEL + wx.wxICON_ERROR, *************** *** 3099,3124 **** end elseif sudokuGUI.IsCheckedMenuItem(sudokuGUI.ID_SHOW_MISTAKES) then ! local ret = wx.wxOK ! while ret == wx.wxOK do ! sudokuGUI.sudokuSolnTable = sudokuGUI.SolveBruteForce(sudokuGUI.sudokuTables[1]) ! ! if not sudokuGUI.sudokuSolnTable then ! -- try to make them correct the puzzle ! local ret = wx.wxMessageBox( ! "The initial puzzle you've opened cannot be or was not solved \n".. ! "and therefore mistakes cannot be marked.\n".. ! "If you press cancel then showing mistakes will be disabled.", ! "wxLuaSudoku - Invalid puzzle", ! wx.wxOK + wx.wxCANCEL + wx.wxICON_ERROR, ! sudokuGUI.frame ) ! ! if ret == wx.wxCANCEL then ! sudokuGUI.CheckMenuItem(sudokuGUI.ID_SHOW_MISTAKES, false) ! break ! end ! else ! break ! end ! end end else --- 3084,3088 ---- end elseif sudokuGUI.IsCheckedMenuItem(sudokuGUI.ID_SHOW_MISTAKES) then ! sudokuGUI.sudokuSolnTable = sudokuGUI.VerifyUniquePuzzle(sudokuGUI.GetInitTable()) end else *************** *** 3144,3148 **** sudokuGUI.fileName = fn:GetFullName() ! result = sudoku.Save(fileName, sudokuGUI.GetCurrentGrid()) if result then sudokuGUI.frame:SetTitle("wxLuaSudoku - "..sudokuGUI.fileName) --- 3108,3112 ---- sudokuGUI.fileName = fn:GetFullName() ! result = sudoku.Save(fileName, sudokuGUI.GetCurrentTable()) if result then sudokuGUI.frame:SetTitle("wxLuaSudoku - "..sudokuGUI.fileName) *************** *** 3228,3234 **** end -- Use the scanning method to solve it function sudokuGUI.SolveScanning() ! local s = TableCopy(sudokuGUI.GetCurrentGrid()) local invalid = not TableIsEmpty(s.invalid) --- 3192,3267 ---- end + function sudokuGUI.VerifyUniquePuzzle(sudokuTable) + local ret = wx.wxOK + + local msg_idx = 1 + local last_time = os.time() + local solve_progress = 0 + local start_time = os.time() + local solve_completed = true + + -- define handler function here so it'll work w/o gui + function sudoku.SolveBruteForceHook(guesses, cell) + if solve_completed == false then return false end -- canceled + solve_progress = solve_progress + 1 + if (solve_progress >= 1000) then solve_progress = 0 end + if (solve_progress-1)%10 ~= 0 then return true end + if (msg_idx < sudokuGUI.sayings_n) and (os.time() - last_time > 4) then + msg_idx = msg_idx + 1 + last_time = os.time() + end + local msg = string.format("%s\nIteration # %d, current cell %d ", sudokuGUI.sayings[msg_idx], guesses.current, cell) + solve_completed = progressDialog:Update(solve_progress/10, msg) + return solve_completed + end + + while ret == wx.wxOK do + msg_idx = 1 + last_time = os.time() + local diff_count = 0 + local diff_i = 0 + local diff_cell = 0 + + solve_progress = 0 + start_time = os.time() + solve_completed = true + + progressDialog = wx.wxProgressDialog("wxLuaSudoku - Ensuring Uniqueness...", + string.format("%s\nIteration # %d, current cell %d ", sudokuGUI.sayings[1], 0, 0), + 10000, + sudokuGUI.frame, + wx.wxPD_AUTO_HIDE+wx.wxPD_CAN_ABORT+wx.wxPD_ELAPSED_TIME) + + local s1, g = sudoku.IsUniquePuzzle(sudokuTable) + progressDialog:Destroy() + + if s1 then + return s1 + elseif solve_completed == false then + ret = wx.wxMessageBox( + "The puzzle was not fully verified. ".. + "Press 'Ok' to continue checking or 'Cancel' to quit.", + "wxLuaSudoku - Unfinished check", + wx.wxOK + wx.wxCANCEL + wx.wxICON_ERROR, + sudokuGUI.frame ) + else + wx.wxMessageBox( + "The puzzle does not have a unique solution.\n".. + "Use 'Create' to fix the problem, showing mistakes will be disabled.", + "wxLuaSudoku - Nonunique puzzle", + wx.wxOK + wx.wxICON_ERROR, + sudokuGUI.frame ) + + sudokuGUI.CheckMenuItem(sudokuGUI.ID_SHOW_MISTAKES, false) + return nil + end + end + + return nil + end + -- Use the scanning method to solve it function sudokuGUI.SolveScanning() ! local s = TableCopy(sudokuGUI.GetCurrentTable()) local invalid = not TableIsEmpty(s.invalid) *************** *** 3255,3260 **** local fixedS = sudokuGUI.FixInvalid(s, true) if fixedS then ! sudokuGUI.AddGrid(fixedS) ! s = TableCopy(sudokuGUI.GetCurrentGrid()) else return --- 3288,3293 ---- local fixedS = sudokuGUI.FixInvalid(s, true) if fixedS then ! sudokuGUI.AddTable(fixedS) ! s = TableCopy(sudokuGUI.GetCurrentTable()) else return *************** *** 3266,3270 **** local changed_count = 0 if changed_cells then ! sudokuGUI.AddGrid(s) changed_count = TableCount(changed_cells) end --- 3299,3303 ---- local changed_count = 0 if changed_cells then ! sudokuGUI.AddTable(s) changed_count = TableCount(changed_cells) end *************** *** 3281,3285 **** local solve_progress = 0 ! local s = TableCopy(sudokuTable or sudokuGUI.GetCurrentGrid()) local invalid = not TableIsEmpty(s.invalid) if invalid then --- 3314,3318 ---- local solve_progress = 0 ! local s = TableCopy(sudokuTable or sudokuGUI.GetCurrentTable()) local invalid = not TableIsEmpty(s.invalid) if invalid then *************** *** 3305,3310 **** local fixedS = sudokuGUI.FixInvalid(s, true) if fixedS then ! sudokuGUI.AddGrid(fixedS) ! s = TableCopy(sudokuGUI.GetCurrentGrid()) else return --- 3338,3343 ---- local fixedS = sudokuGUI.FixInvalid(s, true) if fixedS then ! sudokuGUI.AddTable(fixedS) ! s = TableCopy(sudokuGUI.GetCurrentTable()) else return *************** *** 3359,3363 **** elseif not sudokuTable then s.flags = flags -- restore flags ! sudokuGUI.AddGrid(s) -- we solved the current grid else s.flags = flags -- restore flags --- 3392,3396 ---- elseif not sudokuTable then s.flags = flags -- restore flags ! sudokuGUI.AddTable(s) -- we solved the current grid else s.flags = flags -- restore flags *************** *** 3389,3393 **** function sudokuGUI.UpdateTable(refresh) ! local sudokuTable = sudokuGUI.GetCurrentGrid() sudokuGUI.block_refresh = true --- 3422,3426 ---- function sudokuGUI.UpdateTable(refresh) ! local sudokuTable = sudokuGUI.GetCurrentTable() sudokuGUI.block_refresh = true *************** *** 3414,3418 **** end end ! sudokuGUI.SetCurrentGrid(sudokuTable) sudokuGUI.block_refresh = false --- 3447,3451 ---- end end ! sudokuGUI.SetCurrentTable(sudokuTable) sudokuGUI.block_refresh = false *************** *** 4226,4230 **** sudokuGUI.MenuId[sudokuGUI.ID_COPY_PUZZLE] = function (event) ! local str = sudoku.ToString(sudokuGUI.GetCurrentGrid()) if wx.wxClipboard_Get():Open() then wx.wxClipboard_Get():SetData(wx.wxTextDataObject(str)) --- 4259,4263 ---- sudokuGUI.MenuId[sudokuGUI.ID_COPY_PUZZLE] = function (event) ! local str = sudoku.ToString(sudokuGUI.GetCurrentTable()) if wx.wxClipboard_Get():Open() then wx.wxClipboard_Get():SetData(wx.wxTextDataObject(str)) *************** *** 4327,4331 **** sudokuGUI.frame ) if ret == wx.wxOK then ! local s = sudokuGUI.GetCurrentGrid() for cell = 1, 81 do sudokuGUI.pencilMarks[cell] = {} --- 4360,4364 ---- sudokuGUI.frame ) if ret == wx.wxOK then ! local s = sudokuGUI.GetCurrentTable() for cell = 1, 81 do sudokuGUI.pencilMarks[cell] = {} *************** *** 4360,4363 **** --- 4393,4404 ---- sudokuGUI.MenuId[sudokuGUI.ID_SHOW_HIDDENQUADS] = function(event) sudokuGUI.MenuCheckUpdate(event) end -- ---------------------------------------------------------------------------- + sudokuGUI.MenuId[sudokuGUI.ID_VERIFY_PUZZLE] = + function (event) + local s = sudokuGUI.VerifyUniquePuzzle(sudokuGUI.GetInitTable()) + if s then + sudokuGUI.sudokuSolnTable = s + end + end + sudokuGUI.MenuId[sudokuGUI.ID_ELIMINATE_NAKED] = function (event) *************** *** 4385,4405 **** sudokuGUI.MenuId[sudokuGUI.ID_SOLVE_SCANSINGLES] = function (event) ! local s, changed_cells = sudoku.SolveScanSingles(TableCopy(sudokuGUI.GetCurrentGrid())) ! if changed_cells then sudokuGUI.AddGrid(s) end end sudokuGUI.MenuId[sudokuGUI.ID_SOLVE_SCANROWS] = function (event) ! local s, changed_cells = sudoku.SolveScanRows(TableCopy(sudokuGUI.GetCurrentGrid())) ! if changed_cells then sudokuGUI.AddGrid(s) end end sudokuGUI.MenuId[sudokuGUI.ID_SOLVE_SCANCOLS] = function (event) ! local s, changed_cells = sudoku.SolveScanCols(TableCopy(sudokuGUI.GetCurrentGrid())) ! if changed_cells then sudokuGUI.AddGrid(s) end end sudokuGUI.MenuId[sudokuGUI.ID_SOLVE_SCANBLOCKS] = function (event) ! local s, changed_cells = sudoku.SolveScanBlocks(TableCopy(sudokuGUI.GetCurrentGrid())) ! if changed_cells then sudokuGUI.AddGrid(s) end end --- 4426,4446 ---- sudokuGUI.MenuId[sudokuGUI.ID_SOLVE_SCANSINGLES] = function (event) ! local s, changed_cells = sudoku.SolveScanSingles(TableCopy(sudokuGUI.GetCurrentTable())) ! if changed_cells then sudokuGUI.AddTable(s) end end sudokuGUI.MenuId[sudokuGUI.ID_SOLVE_SCANROWS] = function (event) ! local s, changed_cells = sudoku.SolveScanRows(TableCopy(sudokuGUI.GetCurrentTable())) ! if changed_cells then sudokuGUI.AddTable(s) end end sudokuGUI.MenuId[sudokuGUI.ID_SOLVE_SCANCOLS] = function (event) ! local s, changed_cells = sudoku.SolveScanCols(TableCopy(sudokuGUI.GetCurrentTable())) ! if changed_cells then sudokuGUI.AddTable(s) end end sudokuGUI.MenuId[sudokuGUI.ID_SOLVE_SCANBLOCKS] = function (event) ! local s, changed_cells = sudoku.SolveScanBlocks(TableCopy(sudokuGUI.GetCurrentTable())) ! if changed_cells then sudokuGUI.AddTable(s) end end *************** *** 4543,4546 **** --- 4584,4588 ---- local solveMenu = wx.wxMenu("", 0) + solveMenu:Append(sudokuGUI.ID_VERIFY_PUZZLE, "Verify unique solution...", "Verify that the puzzle has only one solution") local elimSolveMenu = wx.wxMenu("", 0) elimSolveMenu:AppendCheckItem(sudokuGUI.ID_ELIMINATE_NAKED, "Eliminate &naked groups", "Eliminate all naked groups from possible values") |