Advertisement
CaptainSpaceCat

SudokuGen SUCCESS :D

Jun 21st, 2016
189
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 11.88 KB | None | 0 0
  1. ----------------------------------------------MISC FUNCS
  2. if fs.exists("console") then
  3.     shell.run("delete console")
  4. end
  5.  
  6.  
  7. local debug = false
  8. local h = fs.open("console","a")
  9. function log(t)
  10.     if debug then
  11.   if type(t) == "table" then
  12.     for i,v in pairs(t) do
  13.       h.write("i = ")
  14.       h.write(i)
  15.       h.write(" v = ")
  16.       h.write(v)
  17.       h.write("\n")
  18.     end
  19.    
  20.   else
  21.     h.write(t)
  22.     h.write("\n")
  23.   end
  24.   h.flush()
  25.   end
  26. end
  27.  
  28. function logBoard(board, currentPos, futurePos)
  29.     if debug then
  30.         for y = 1, 9 do
  31.         term.setCursorPos(1, y + math.ceil(y/3) - 1)
  32.             for x = 1, 9 do
  33.                 if tonumber(board[y][x]) then
  34.                     term.setTextColor(colors.red)
  35.                     write(board[y][x])
  36.                 else
  37.                     term.setTextColor(colors.white)
  38.                     write("0")
  39.                 end
  40.                 if x == 3 or x == 6 then
  41.                     write(" ")
  42.                 end
  43.             end
  44.         end
  45.         if currentPos then
  46.             term.setTextColor(colors.orange)
  47.             term.setCursorPos(currentPos[1] + math.floor((currentPos[1]-1)/3), currentPos[2] + math.floor((currentPos[2]-1)/3))
  48.             term.write(board[currentPos[2]][currentPos[1]])
  49.         end
  50.         if futurePos then
  51.             term.setTextColor(colors.lime)
  52.             term.setCursorPos(futurePos[1] + math.floor((futurePos[1]-1)/3), currentPos[2] + math.floor((futurePos[2]-1)/3))
  53.             term.write("*")
  54.             os.pullEvent("mouse_click")
  55.         end
  56.         print("")
  57.         sleep(.1)
  58.     end
  59. end
  60.  
  61. local chrono = 0
  62. function printBoard(board, num, str, override, lineTab, isoTab)
  63.     if (debug and num) or override then
  64.         for y = 1, 9 do
  65.             term.setCursorPos(1, y + math.ceil(y/3))
  66.             term.setBackgroundColor(colors.black)
  67.             term.setTextColor(colors.white)
  68.             write("|")
  69.             for x = 1, 9 do
  70.                 if tonumber(board[y][x]) then
  71.                     term.setTextColor(colors.blue)
  72.                     write(board[y][x])
  73.                 elseif board[y][x][num] == 1 then
  74.                     term.setTextColor(colors.lime)
  75.                     write(num)
  76.                 else
  77.                     term.setTextColor(colors.lightGray)
  78.                     write("0")
  79.                 end
  80.                 if x == 3 or x == 6 then
  81.                     term.setTextColor(colors.white)
  82.                     write("|")
  83.                 end
  84.             end
  85.             term.setTextColor(colors.white)
  86.             write("|")
  87.         end
  88.         if lineTab then
  89.             for i = 1, #lineTab do
  90.                 term.setCursorPos(lineTab[i][1] + math.ceil(lineTab[i][1]/3), lineTab[i][2] + math.ceil(lineTab[i][2]/3))
  91.                 if lineTab[i][3] then
  92.                     term.setBackgroundColor(colors.red)
  93.                     if lineTab[i][4] == 1 then
  94.                         term.setTextColor(colors.black)
  95.                         write(num)
  96.                     else
  97.                         term.setTextColor(colors.gray)
  98.                         write("0")
  99.                     end
  100.                 else
  101.                     term.setBackgroundColor(colors.black)
  102.                     if lineTab[i][4] == 1 then
  103.                         term.setTextColor(colors.yellow)
  104.                         write(num)
  105.                     else
  106.                         term.setTextColor(colors.lightGray)
  107.                         write("0")
  108.                     end
  109.                 end
  110.             end
  111.         end
  112.         if isoTab then
  113.             for i = 2, #isoTab do
  114.                 term.setBackgroundColor(colors.orange)
  115.                 term.setCursorPos(isoTab[i][1] + math.ceil(isoTab[i][1]/3), isoTab[i][2] + math.ceil(isoTab[i][2]/3))
  116.                 if isoTab[i][3] == 1 then
  117.                     term.setTextColor(colors.black)
  118.                     write(num)
  119.                 else
  120.                     term.setTextColor(colors.gray)
  121.                     write("0")
  122.                 end
  123.             end
  124.             term.setBackgroundColor(colors.green)
  125.             term.setTextColor(colors.lime)
  126.             term.setCursorPos(isoTab[1][1] + math.ceil(isoTab[1][1]/3), isoTab[1][2] + math.ceil(isoTab[1][2]/3))
  127.             write(num)
  128.         end
  129.         term.setBackgroundColor(colors.black)
  130.         term.setTextColor(colors.white)
  131.         term.setCursorPos(1, 1)
  132.         write("-------------")
  133.         term.setCursorPos(1, 5)
  134.         write("|---+---+---|")
  135.         term.setCursorPos(1, 9)
  136.         write("|---+---+---|")
  137.         term.setCursorPos(1, 13)
  138.         write("-------------")
  139.         term.setCursorPos(1, 14)
  140.     elseif not num then
  141.         for y = 1, 9 do
  142.             term.setCursorPos(1, y + math.ceil(y/3))
  143.             term.setTextColor(colors.white)
  144.             write("|")
  145.             for x = 1, 9 do
  146.                 local c = 0
  147.                 for i = 1, 9 do
  148.                     if board[y][x][i] == 1 then
  149.                         if c ~= 0 then
  150.                             c = 0
  151.                             break;
  152.                         end
  153.                         c = i
  154.                     end
  155.                 end
  156.                 if c ~= 0 then
  157.                     term.setTextColor(colors.yellow)
  158.                     write(c)
  159.                 else
  160.                     term.setTextColor(colors.lightGray)
  161.                     write("0")
  162.                 end
  163.                 if x == 3 or x == 6 then
  164.                     term.setTextColor(colors.white)
  165.                     write("|")
  166.                 end
  167.             end
  168.             term.setTextColor(colors.white)
  169.             write("|")
  170.         end
  171.         term.setCursorPos(1, 1)
  172.         write("-------------")
  173.         term.setCursorPos(1, 5)
  174.         write("|---+---+---|")
  175.         term.setCursorPos(1, 9)
  176.         write("|---+---+---|")
  177.         term.setCursorPos(1, 13)
  178.         write("-------------")
  179.         term.setCursorPos(1, 14)
  180.     end
  181.     if debug then
  182.         if str then
  183.             term.clearLine()
  184.             write(str)
  185.         end
  186.         os.pullEvent()
  187.     end
  188.     chrono = chrono + 1
  189.     if chrono >= 100 then
  190.         sleep(.005)
  191.         chrono = 0
  192.     end
  193. end
  194.  
  195. ----------------------------------------------GENERATION
  196. function initializeBoard(board)
  197.     for y = 1, 9 do
  198.         board[y] = {}
  199.         for x = 1, 9 do
  200.             board[y][x] = {1, 1, 1, 1, 1, 1, 1, 1, 1}
  201.         end
  202.     end
  203. end
  204.  
  205. function generatePuzzle(board)
  206.     local scanRef = {}
  207.     --log("-=-=-=-=-=-=-=-Starting Generation Algorithm-=-=-=-=-=-=-=-")
  208.     for n = 1, 9 do
  209.         --log("Filling in " .. n .. " --------------")
  210.         scanRef = {{1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1}}
  211.         for q = 1, 9 do
  212.             --log("Quadrant " .. q .. "...")
  213.             scanRef, changed = scanPatterns(board, q, n, scanRef)
  214.             --if debug and changed then
  215.                 printBoard(board, n, "Scanned")
  216.             --end
  217.             if scanRef[2][q] == 1 then
  218.                 local cells = getAvailableCells(board, q, n)
  219.                 local c = cells[math.random(1, #cells)]
  220.                 isolateNumber(board, c[1], c[2], n, " -=-random-=-")
  221.                 scanRef[2][q] = 0
  222.             end
  223.             --printBoard(board, n, "Reverting cycle...")
  224.             --log("Quadrant " .. q .. " isolated>>")
  225.         end
  226.     end
  227.     --finalizeBoard(board)
  228. end
  229.  
  230. function isolateNumber(board, x, y, num, comment)
  231.     comment = comment or ""
  232.     local logTab = {}
  233.     if debug then
  234.         table.insert(logTab, {x, y, 1})
  235.         for i = 1, 9 do
  236.             if not tonumber(board[i][x]) then table.insert(logTab, {x, i, board[i][x][num]}) end
  237.             if not tonumber(board[y][i]) then table.insert(logTab, {i, y, board[y][i][num]}) end
  238.             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
  239.                 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]})
  240.             end
  241.         end
  242.     end
  243.     for i = 1, 9 do
  244.         if not tonumber(board[i][x]) then board[i][x][num] = 0 end--whole row
  245.         if not tonumber(board[y][i]) then board[y][i][num] = 0 end--whole column
  246.         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
  247.             board[(math.ceil(y/3)-1)*3+math.ceil(i/3)][(math.ceil(x/3)-1)*3+(i-1)%3+1][num] = 0
  248.         end
  249.         --log("-->" .. (math.ceil(y/3)-1)*3+(i-1)%3+1 .. ":" .. (math.ceil(x/3)-1)*3+(i-1)%3+1)
  250.                              --whole box (holy crap! what a line of code!)
  251.     end
  252.     --for i = 1, 9 do
  253.     --  board[y][x][i] = 0
  254.     --end
  255.     board[y][x] = num
  256.     printBoard(board, num, "Isolated: " .. x .. ":" .. y .. comment, _, _, logTab)
  257. end
  258.  
  259. function scanPatterns(board, qStart, num, refTab)
  260.     local flag = true
  261.     local altered = false
  262.     while flag do
  263.         flag = false
  264.         for i = qStart, 9 do
  265.             local cells = getAvailableCells(board, i, num)
  266.             if #cells < 1 then
  267.                 --convertBoard(board)
  268.                 printBoard(board, num, _, true)
  269.                 error("ERROR: No avilable places for number " .. num .. " in quadrant " .. i)
  270.             elseif #cells == 1 and refTab[2][i] == 1 then
  271.                 isolateNumber(board, cells[1][1], cells[1][2], num)
  272.                 refTab[2][i] = 0
  273.                 flag = true
  274.                 altered = true
  275.                 break;
  276.             elseif #cells > 1 and #cells <= 3 and refTab[1][i] == 1 then
  277.                
  278.                     local rays = detectLine(cells)
  279.                     for _, v in ipairs(rays) do
  280.                         --log("Row?: " .. tostring(v[1]) .. " Slice:" .. v[2] .. "  | Q" .. i)
  281.                         eliminateLine(board, v[1], v[2], i, num)
  282.                     end
  283.                 refTab[1][i] = 0
  284.                 flag = true
  285.                 altered = true
  286.                 break;
  287.             end
  288.         end
  289.     end
  290.     return refTab, altered
  291. end
  292.  
  293. function getAvailableNum(board, quadrant, num)
  294.     local cells = {}
  295.     for i = 1, 3 do
  296.         for j = 1, 3 do
  297.             if board[(math.ceil(quadrant/3)-1)*3 + i][(quadrant-1)%3 + j][num] == 1 then
  298.                 table.insert(cells, {(quadrant-1)%3 + j, (math.ceil(quadrant/3)-1)*3 + i})
  299.             end
  300.         end
  301.     end
  302.     return cells
  303. end
  304.  
  305. function detectLine(cells)
  306.     local xList = {}
  307.     local yList = {}
  308.     for i, v in ipairs(cells) do
  309.         table.insert(xList, v[1])
  310.         table.insert(yList, v[2])
  311.     end
  312.     local rays = {}
  313.     table.sort(xList)
  314.     table.sort(yList)
  315.     if xList[1] == xList[#xList] then
  316.         table.insert(rays, {false, xList[1]})
  317.     end
  318.     if yList[1] == yList[#yList] then
  319.         table.insert(rays, {true, yList[1]})
  320.     end
  321.     return rays
  322. end
  323.  
  324. function eliminateLine(board, row, slice, homeQuadrant, num) --num: the current number
  325.     --int[][][]board: the board, boolean row: whether it is a row or a column
  326.     --int slice: row/col being altered, homeQuadrant: unnaffected quadrant
  327.     local logTab = {}
  328.     if row then
  329.         for i = 1, 9 do
  330.             if not tonumber(board[slice][i]) then
  331.                 table.insert(logTab, {i, slice, math.ceil(i/3) ~= (homeQuadrant-1)%3 + 1, board[slice][i][num]})
  332.                 if math.ceil(i/3) ~= (homeQuadrant-1)%3 + 1 then
  333.                     board[slice][i][num] = 0
  334.                 end
  335.             end
  336.         end
  337.     else
  338.         for i = 1, 9 do
  339.             if not tonumber(board[i][slice]) then
  340.                 table.insert(logTab, {slice, i, math.ceil(i/3) ~= math.ceil(homeQuadrant/3), board[i][slice][num]})
  341.                 if math.ceil(i/3) ~= math.ceil(homeQuadrant/3) then
  342.                     board[i][slice][num] = 0
  343.                 end
  344.             end
  345.         end
  346.     end
  347.     printBoard(board, num, "Line Eliminated: Q" .. homeQuadrant .. ", " .. tostring(row) .. ", " .. slice, _, logTab)
  348. end
  349.  
  350. function convertBoard(board)
  351.     for y = 1, 9 do
  352.         for x = 1, 9 do
  353.             local num = 0
  354.             for i = 1, 9 do
  355.                 if board[y][x][i] == 1 then
  356.                     if num ~= 0 then
  357.                         --error("ERROR: Multiple answers at " .. x .. ":" .. y)
  358.                         board[y][x] = 0
  359.                         break;
  360.                     else
  361.                         num = i
  362.                     end
  363.                 end
  364.             end
  365.             if num == 0 then
  366.                 --error("ERROR: No answers at " .. x .. ":" .. y)
  367.                 board[y][x] = {}
  368.             else
  369.                 board[y][x] = num
  370.             end
  371.         end
  372.     end
  373. end
  374.  
  375. function finalizeBoard(board)
  376.     for y = 1, 9 do
  377.         for x = 1, 9 do
  378.             local num = 0
  379.             for i = 1, 9 do
  380.                 if board[y][x][i] == 1 then
  381.                     if num ~= 0 then
  382.                         error("ERROR: Multiple answers at " .. x .. ":" .. y)
  383.                     end
  384.                     num = i
  385.                 end
  386.             end
  387.             if num == 0 then
  388.                 error("ERROR: No answers at " .. x .. ":" .. y)
  389.             end
  390.             board[y][x] = num
  391.         end
  392.     end
  393. end
  394.  
  395. function getAvailableCells(board, quadrant, num)
  396.     local result = {}
  397.     for y = (math.ceil(quadrant/3)-1)*3 + 1, (math.ceil(quadrant/3)-1)*3 + 3 do
  398.         for x = ((quadrant-1)%3)*3 + 1, ((quadrant-1)%3)*3 + 3 do
  399.             if board[y][x] == num or (not tonumber(board[y][x]) and board[y][x][num] == 1) then
  400.                 table.insert(result, {x, y})
  401.             end
  402.         end
  403.     end
  404.     return result
  405. end
  406.  
  407. function iLocate(i, quadrantX, quadrantY, board)
  408.     for y =  1, 3 do
  409.         for x = 1, 3 do
  410.             if board[y + (quadrantY-1)*3][x + (quadrantX-1)*3] == i then
  411.                 return {x, y}, {x + (quadrantX-1)*3, y + (quadrantY-1)*3}
  412.             end
  413.         end
  414.     end
  415.     printBoard(board)
  416.     error("iLocate Failed")
  417. end
  418. ----------------------------------------------SOLUTION
  419.  
  420. ----------------------------------------------ENGINE
  421. local tArgs = {...}
  422. term.setBackgroundColor(colors.black)
  423. term.setTextColor(colors.white)
  424. term.clear()
  425.  
  426. if #tArgs == 0 then
  427.     term.setCursorPos(1, 1)
  428.     print("Usage: ".. shell.getRunningProgram() .." gen <view>")
  429.     print("adding <view> will show the process")
  430.     print("algorithm works about 40% of the time\n")
  431.     print("Usage: ".. shell.getRunningProgram() .." solve [puzzleFile] <view>")
  432.     print("input the sudoku puzzle file into puzzleFile")
  433.     print("adding <view> will show the process")
  434.     print("coming soon...")
  435. else
  436.     if tArgs[1] == "generate" or tArgs[1] == "gen" or tArgs[1] == "g" then
  437.         if tArgs[2] == "view" then debug = true end
  438.         local board = {}
  439.         initializeBoard(board)
  440.         generatePuzzle(board)
  441.         printBoard(board)
  442.     elseif tArgs[1] == "solve" or tArgs[1] == "s" then
  443.         if tArgs[3] == "view" then debug = true end
  444.     end
  445. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement