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 debug = false
- local h = fs.open("console","a")
- function log(t)
- if debug then
- if type(t) == "table" then
- for i,v in pairs(t) do
- h.write("i = ")
- h.write(i)
- h.write(" v = ")
- h.write(v)
- h.write("\n")
- end
- else
- h.write(t)
- h.write("\n")
- end
- h.flush()
- end
- end
- function logBoard(board, currentPos, futurePos)
- if debug then
- for y = 1, 9 do
- term.setCursorPos(1, y + math.ceil(y/3) - 1)
- for x = 1, 9 do
- if tonumber(board[y][x]) then
- term.setTextColor(colors.red)
- write(board[y][x])
- else
- term.setTextColor(colors.white)
- write("0")
- end
- if x == 3 or x == 6 then
- write(" ")
- end
- end
- end
- if currentPos then
- term.setTextColor(colors.orange)
- term.setCursorPos(currentPos[1] + math.floor((currentPos[1]-1)/3), currentPos[2] + math.floor((currentPos[2]-1)/3))
- term.write(board[currentPos[2]][currentPos[1]])
- end
- if futurePos then
- term.setTextColor(colors.lime)
- term.setCursorPos(futurePos[1] + math.floor((futurePos[1]-1)/3), currentPos[2] + math.floor((futurePos[2]-1)/3))
- term.write("*")
- os.pullEvent("mouse_click")
- end
- print("")
- sleep(.1)
- end
- 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.blue)
- 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)
- 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)
- 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)
- 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
- local c = 0
- for i = 1, 9 do
- if board[y][x][i] == 1 then
- if c ~= 0 then
- c = 0
- break;
- end
- c = i
- end
- end
- if c ~= 0 then
- term.setTextColor(colors.yellow)
- write(c)
- 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
- 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
- printBoard(board, n, "Scanned")
- --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]}) end
- if not tonumber(board[y][i]) then table.insert(logTab, {i, y, board[y][i][num]}) 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]})
- 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)
- printBoard(board, num, _, true)
- error("ERROR: No avilable places for number " .. num .. " in quadrant " .. 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 rays = detectLine(cells)
- 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
- refTab[1][i] = 0
- flag = true
- altered = true
- break;
- end
- end
- end
- return refTab, altered
- end
- function getAvailableNum(board, quadrant, num)
- local cells = {}
- for i = 1, 3 do
- for j = 1, 3 do
- if board[(math.ceil(quadrant/3)-1)*3 + i][(quadrant-1)%3 + j][num] == 1 then
- table.insert(cells, {(quadrant-1)%3 + j, (math.ceil(quadrant/3)-1)*3 + i})
- end
- end
- end
- return cells
- 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
- 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
- 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
- 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
- end
- end
- end
- printBoard(board, num, "Line Eliminated: Q" .. homeQuadrant .. ", " .. tostring(row) .. ", " .. slice, _, logTab)
- end
- function convertBoard(board)
- for y = 1, 9 do
- for x = 1, 9 do
- local num = 0
- for i = 1, 9 do
- if board[y][x][i] == 1 then
- if num ~= 0 then
- --error("ERROR: Multiple answers at " .. x .. ":" .. y)
- board[y][x] = 0
- break;
- else
- num = i
- end
- end
- end
- if num == 0 then
- --error("ERROR: No answers at " .. x .. ":" .. y)
- board[y][x] = {}
- else
- board[y][x] = num
- end
- end
- end
- end
- function finalizeBoard(board)
- for y = 1, 9 do
- for x = 1, 9 do
- local num = 0
- for i = 1, 9 do
- if board[y][x][i] == 1 then
- if num ~= 0 then
- error("ERROR: Multiple answers at " .. x .. ":" .. y)
- end
- num = i
- end
- end
- if num == 0 then
- error("ERROR: No answers at " .. x .. ":" .. y)
- end
- board[y][x] = num
- end
- end
- 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
- function iLocate(i, quadrantX, quadrantY, board)
- for y = 1, 3 do
- for x = 1, 3 do
- if board[y + (quadrantY-1)*3][x + (quadrantX-1)*3] == i then
- return {x, y}, {x + (quadrantX-1)*3, y + (quadrantY-1)*3}
- end
- end
- end
- printBoard(board)
- error("iLocate Failed")
- end
- ----------------------------------------------SOLUTION
- ----------------------------------------------ENGINE
- local tArgs = {...}
- term.setBackgroundColor(colors.black)
- term.setTextColor(colors.white)
- term.clear()
- 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...")
- else
- if tArgs[1] == "generate" or tArgs[1] == "gen" or tArgs[1] == "g" then
- if tArgs[2] == "view" then debug = true end
- local board = {}
- initializeBoard(board)
- generatePuzzle(board)
- printBoard(board)
- elseif tArgs[1] == "solve" or tArgs[1] == "s" then
- if tArgs[3] == "view" then debug = true end
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement