Advertisement
CaptainSpaceCat

SudokuGen Graphical

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