#! /usr/bin/env ruby SudokuSize = 81 SudokuRow = 9 SudokuBox = 3 SudokuValidCharacters = [1, 2, 3, 4, 5, 6, 7, 8, 9] SudokuStr = "000008000200059000100000250008001460300000100904083000000500084000004900023000000" arr = SudokuStr .chars .map{|c| c.to_i} def buildRow (p) r = p % SudokuRow rp = p / SudokuRow row = [] 0.upto(SudokuRow - 1).each{ |e| if e != r then row.push(e + (rp * SudokuRow)) end } row end def buildCol (p) r = p % SudokuRow rp = p / SudokuRow col = [] 0.upto(SudokuRow - 1).each{ |e| if e != rp then col.push(r + (e * SudokuRow)) end } col end def buildBoxArr (p) if p == 0 then [1, 2] elsif p == 1 then [-1, 1] else [-2, -1] end end def buildBox (p) r = buildBoxArr((p / SudokuRow) % SudokuBox) c = buildBoxArr(p % SudokuBox) r.reduce([]){|ar, dr| c.reduce(ar){|ac, dc| ac.push(dc + p + (dr * SudokuRow))}} end def buildStartingValues(e, ar) SudokuValidCharacters .reduce([]){ |a, s| if (e.find{|ed| ar[ed] == s}) then a else a.push(s) end } end sudokuArr = arr .map .each_with_index{ |v, i| fixed = v == 0 ? false : true edges = fixed ? [] : (buildRow i) + (buildCol i) + (buildBox i) startingValues = fixed ? [] : buildStartingValues(edges, arr) [i, v, fixed, edges, startingValues] } def solveIt(sa, pos, ar) if pos < SudokuSize then elem = sa[pos] pe = elem[0] v = elem[1] f = elem[2] e = elem[3] sv = elem[4] if f then solveIt(sa, pos + 1, ar) else sv.each{ |s| if (e.find{|ed| ar[ed] == s}) then else ar[pos] = s solveIt(sa, pos + 1, ar) ar[pos] = 0 end } end else p ar end end solveIt(sudokuArr, 0, arr)