Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ----------------------------------------------MISC FUNCS
- if fs.exists("console") then
- shell.run("delete console")
- end
- local w, h = term.getSize()
- local debug = false
- local diagnostics = false
- --local handle = fs.open("console","a")
- function log(t)
- end
- local chrono = 0
- function printBoard(board, num, str, override, lineTab, isoTab)
- if (debug and num) or override then
- for y = 1, 9 do
- term.setCursorPos(1, y + math.ceil(y/3))
- term.setBackgroundColor(colors.black)
- term.setTextColor(colors.white)
- write("|")
- for x = 1, 9 do
- if tonumber(board[y][x]) then
- term.setTextColor(colors.lightBlue)
- write(board[y][x])
- elseif board[y][x][num] == 1 then
- term.setTextColor(colors.lime)
- write(num)
- else
- term.setTextColor(colors.lightGray)
- write("0")
- end
- if x == 3 or x == 6 then
- term.setTextColor(colors.white)
- write("|")
- end
- end
- term.setTextColor(colors.white)
- write("|")
- end
- if lineTab then
- for i = 1, #lineTab do
- term.setCursorPos(lineTab[i][1] + math.ceil(lineTab[i][1]/3), lineTab[i][2] + math.ceil(lineTab[i][2]/3))
- if lineTab[i][3] then
- term.setBackgroundColor(colors.red)
- if lineTab[i][4] == 1 then
- term.setTextColor(colors.black)
- write(num)
- elseif lineTab[i][5] then
- term.setTextColor(colors.white)
- write(lineTab[i][5])
- else
- term.setTextColor(colors.gray)
- write("0")
- end
- else
- term.setBackgroundColor(colors.black)
- if lineTab[i][4] == 1 then
- term.setTextColor(colors.yellow)
- write(num)
- elseif lineTab[i][5] then
- term.setTextColor(colors.lightBlue)
- write(lineTab[i][5])
- else
- term.setTextColor(colors.lightGray)
- write("0")
- end
- end
- end
- end
- if isoTab then
- for i = 2, #isoTab do
- term.setBackgroundColor(colors.orange)
- term.setCursorPos(isoTab[i][1] + math.ceil(isoTab[i][1]/3), isoTab[i][2] + math.ceil(isoTab[i][2]/3))
- if isoTab[i][3] == 1 then
- term.setTextColor(colors.black)
- write(num)
- elseif isoTab[i][4] then
- term.setTextColor(colors.white)
- write(isoTab[i][4])
- else
- term.setTextColor(colors.gray)
- write("0")
- end
- end
- term.setBackgroundColor(colors.green)
- term.setTextColor(colors.lime)
- term.setCursorPos(isoTab[1][1] + math.ceil(isoTab[1][1]/3), isoTab[1][2] + math.ceil(isoTab[1][2]/3))
- write(num)
- end
- term.setBackgroundColor(colors.black)
- term.setTextColor(colors.white)
- term.setCursorPos(1, 1)
- write("-------------")
- term.setCursorPos(1, 5)
- write("|---+---+---|")
- term.setCursorPos(1, 9)
- write("|---+---+---|")
- term.setCursorPos(1, 13)
- write("-------------")
- term.setCursorPos(1, 14)
- elseif not num then
- for y = 1, 9 do
- term.setCursorPos(1, y + math.ceil(y/3))
- term.setTextColor(colors.white)
- write("|")
- for x = 1, 9 do
- term.setTextColor(colors.yellow)
- if tonumber(board[y][x]) then
- write(board[y][x])
- else write ("_") end
- if x == 3 or x == 6 then
- term.setTextColor(colors.white)
- write("|")
- end
- end
- term.setTextColor(colors.white)
- write("|")
- end
- term.setCursorPos(1, 1)
- write("-------------")
- term.setCursorPos(1, 5)
- write("|---+---+---|")
- term.setCursorPos(1, 9)
- write("|---+---+---|")
- term.setCursorPos(1, 13)
- write("-------------")
- term.setCursorPos(1, 14)
- end
- if debug then
- if str then
- term.clearLine()
- write(str)
- end
- os.pullEvent()
- end
- chrono = chrono + 1
- if chrono >= 100 then
- sleep(.005)
- chrono = 0
- end
- end
- ----------------------------------------------GENERATION
- function initializeBoard(board)
- for y = 1, 9 do
- board[y] = {}
- for x = 1, 9 do
- board[y][x] = {1, 1, 1, 1, 1, 1, 1, 1, 1}
- end
- end
- end
- function generatePuzzle(board)
- local scanRef = {}
- --log("-=-=-=-=-=-=-=-Starting Generation Algorithm-=-=-=-=-=-=-=-")
- for n = 1, 9 do
- --log("Filling in " .. n .. " --------------")
- scanRef = {{1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1}}
- for q = 1, 9 do
- --log("Quadrant " .. q .. "...")
- scanRef, changed = scanPatterns(board, q, n, scanRef)
- --if debug and changed then
- local logString = ""
- for i = 1, 2 do
- for n = 1, 9 do
- logString = logString .. scanRef[i][n] .. ", "
- end
- logString = logString:sub(1, -3)
- logString = logString .. "\n"
- end
- printBoard(board, n, "ScanRef:\n" .. logString)
- --end
- if scanRef[2][q] == 1 then
- local cells = getAvailableCells(board, q, n)
- local c = cells[math.random(1, #cells)]
- isolateNumber(board, c[1], c[2], n, " -=-random-=-")
- scanRef[2][q] = 0
- end
- --printBoard(board, n, "Reverting cycle...")
- --log("Quadrant " .. q .. " isolated>>")
- end
- end
- --finalizeBoard(board)
- end
- function isolateNumber(board, x, y, num, comment)
- comment = comment or ""
- local logTab = {}
- if debug then
- table.insert(logTab, {x, y, 1})
- for i = 1, 9 do
- if not tonumber(board[i][x]) then table.insert(logTab, {x, i, board[i][x][num]}) else table.insert(logTab, {x, i, 0, board[i][x]}) end
- if not tonumber(board[y][i]) then table.insert(logTab, {i, y, board[y][i][num]}) else table.insert(logTab, {i, y, 0, board[y][i]}) end
- if not tonumber(board[(math.ceil(y/3)-1)*3+math.ceil(i/3)][(math.ceil(x/3)-1)*3+(i-1)%3+1]) then
- table.insert(logTab, {(math.ceil(x/3)-1)*3+(i-1)%3+1, (math.ceil(y/3)-1)*3+math.ceil(i/3), board[(math.ceil(y/3)-1)*3+math.ceil(i/3)][(math.ceil(x/3)-1)*3+(i-1)%3+1][num]})
- else
- table.insert(logTab, {(math.ceil(x/3)-1)*3+(i-1)%3+1, (math.ceil(y/3)-1)*3+math.ceil(i/3), 0, board[(math.ceil(y/3)-1)*3+math.ceil(i/3)][(math.ceil(x/3)-1)*3+(i-1)%3+1]})
- end
- end
- end
- for i = 1, 9 do
- if not tonumber(board[i][x]) then board[i][x][num] = 0 end--whole row
- if not tonumber(board[y][i]) then board[y][i][num] = 0 end--whole column
- if not tonumber(board[(math.ceil(y/3)-1)*3+math.ceil(i/3)][(math.ceil(x/3)-1)*3+(i-1)%3+1]) then
- board[(math.ceil(y/3)-1)*3+math.ceil(i/3)][(math.ceil(x/3)-1)*3+(i-1)%3+1][num] = 0
- end
- --log("-->" .. (math.ceil(y/3)-1)*3+(i-1)%3+1 .. ":" .. (math.ceil(x/3)-1)*3+(i-1)%3+1)
- --whole box (holy crap! what a line of code!)
- end
- --for i = 1, 9 do
- -- board[y][x][i] = 0
- --end
- board[y][x] = num
- printBoard(board, num, "Isolated: " .. x .. ":" .. y .. comment, _, _, logTab)
- end
- function scanPatterns(board, qStart, num, refTab)
- local flag = true
- local altered = false
- while flag do
- flag = false
- for i = qStart, 9 do
- local cells = getAvailableCells(board, i, num)
- if #cells < 1 then
- --convertBoard(board)
- if not diagnostics then
- printBoard(board, num, _, true)
- end
- error("ERROR: No avilable places for number " .. num .. " in quadrant " .. i .. " ("..num..":"..i..")")
- elseif #cells == 1 and refTab[2][i] == 1 then
- isolateNumber(board, cells[1][1], cells[1][2], num)
- refTab[2][i] = 0
- flag = true
- altered = true
- break;
- elseif #cells > 1 and #cells <= 3 and refTab[1][i] == 1 then
- local detected, rays = detectLine(cells)
- if detected then
- refTab[1][i] = 0
- flag = true
- altered = true
- for _, v in ipairs(rays) do
- --log("Row?: " .. tostring(v[1]) .. " Slice:" .. v[2] .. " | Q" .. i)
- eliminateLine(board, v[1], v[2], i, num)
- end
- break;
- end
- end
- end
- end
- return refTab, altered
- end
- function detectLine(cells)
- local xList = {}
- local yList = {}
- for i, v in ipairs(cells) do
- table.insert(xList, v[1])
- table.insert(yList, v[2])
- end
- local rays = {}
- table.sort(xList)
- table.sort(yList)
- if xList[1] == xList[#xList] then
- table.insert(rays, {false, xList[1]})
- end
- if yList[1] == yList[#yList] then
- table.insert(rays, {true, yList[1]})
- end
- return #rays > 0, rays
- end
- function eliminateLine(board, row, slice, homeQuadrant, num) --num: the current number
- --int[][][]board: the board, boolean row: whether it is a row or a column
- --int slice: row/col being altered, homeQuadrant: unnaffected quadrant
- local logTab = {}
- if row then
- for i = 1, 9 do
- if not tonumber(board[slice][i]) then -- or board[slice][i]
- table.insert(logTab, {i, slice, math.ceil(i/3) ~= (homeQuadrant-1)%3 + 1, board[slice][i][num]})
- if math.ceil(i/3) ~= (homeQuadrant-1)%3 + 1 then
- board[slice][i][num] = 0
- end
- else
- table.insert(logTab, {i, slice, math.ceil(i/3) ~= (homeQuadrant-1)%3 + 1, 0, board[slice][i]})
- end
- end
- else
- for i = 1, 9 do
- if not tonumber(board[i][slice]) then
- table.insert(logTab, {slice, i, math.ceil(i/3) ~= math.ceil(homeQuadrant/3), board[i][slice][num]})
- if math.ceil(i/3) ~= math.ceil(homeQuadrant/3) then
- board[i][slice][num] = 0
- end
- else
- table.insert(logTab, {slice, i, math.ceil(i/3) ~= math.ceil(homeQuadrant/3), 0, board[i][slice]})
- end
- end
- end
- printBoard(board, num, "Line Eliminated: Q" .. homeQuadrant .. ", " .. tostring(row) .. ", " .. slice, _, logTab)
- end
- function getAvailableCells(board, quadrant, num)
- local result = {}
- for y = (math.ceil(quadrant/3)-1)*3 + 1, (math.ceil(quadrant/3)-1)*3 + 3 do
- for x = ((quadrant-1)%3)*3 + 1, ((quadrant-1)%3)*3 + 3 do
- if board[y][x] == num or (not tonumber(board[y][x]) and board[y][x][num] == 1) then
- table.insert(result, {x, y})
- end
- end
- end
- return result
- end
- ----------------------------------------------SOLUTION
- ----------------------------------------------ENGINE
- local tArgs = {...}
- term.setBackgroundColor(colors.black)
- term.setTextColor(colors.white)
- term.clear()
- local seed = math.random(1, 100000)
- math.randomseed(seed)
- log(seed)
- if #tArgs == 0 then
- term.setCursorPos(1, 1)
- print("Usage: ".. shell.getRunningProgram() .." gen <view>")
- print("adding <view> will show the process")
- print("algorithm works about 40% of the time\n")
- print("Usage: ".. shell.getRunningProgram() .." solve [puzzleFile] <view>")
- print("input the sudoku puzzle file into puzzleFile")
- print("adding <view> will show the process")
- print("coming soon...\n")
- print("Usage: ".. shell.getRunningProgram() .." test [g or s]")
- print("Analyzes the current algorithm and compiles results")
- print("g for generation, s for solution (WIP)")
- else
- if tArgs[1] == "generate" or tArgs[1] == "gen" or tArgs[1] == "g" then
- if tArgs[2] == "view" then debug = true end
- local board = {}
- diagnostics=true
- initializeBoard(board)
- if not debug then
- local ok, err = pcall(generatePuzzle, board)
- while not ok do
- initializeBoard(board)
- ok, err = pcall(generatePuzzle, board)
- printBoard(board)
- end
- else
- generatePuzzle(board)
- printBoard(board)
- end
- elseif tArgs[1] == "solve" or tArgs[1] == "s" then
- if tArgs[3] == "view" then debug = true end
- elseif tArgs[1] == "test" then
- diagnostics = true
- local board = {}
- if tArgs[2] == "g" then
- local s = 0
- local f = 0
- local errors = {}
- for i = 1, 9 do
- errors[i] = 0
- end
- while f < 100 do
- initializeBoard(board)
- ok, err = pcall(generatePuzzle, board)
- if not ok then
- errors[tonumber(err:sub(#err-3, -4))] = errors[tonumber(err:sub(#err-3, -4))] + 1
- f = f + 1
- term.setCursorPos(1, h-1)
- term.setBackgroundColor(colors.black)
- term.clearLine()
- write("Generating errors...")
- term.setCursorPos(w-#tostring(f), h-1)
- write(f .. "%")
- term.setBackgroundColor(colors.red)
- term.setCursorPos(1, h)
- write(string.rep(" ", math.floor((f/100)*w)))
- else
- s = s + 1
- end
- end
- --printBoard(board)
- term.setBackgroundColor(colors.black)
- term.clear()
- term.setCursorPos(1, 1)
- print("Results:")
- print("1 2 3 4 5 6 7 8 9")
- print("-------------------------")
- for i, v in ipairs(errors) do
- term.setCursorPos(3*(i-1) + 1, 4)
- write(v)
- end
- print("\n")
- print("Puzzles generated: " .. s+f)
- print("Success rate: " .. string.sub(tostring(s/(s+f)*100), 1, 5) .. "%")
- elseif tArgs[2] == "s" then
- end
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement