3v4l.org

run code in 300+ PHP versions simultaneously
<?php class SudokuGenerator extends SudokuSolver { public $EleArray = NULL; const METRIC_EASY = 27; const METRIC_MEDIUM = 22; const METRIC_HARD = 17; public function __construct() { $this->EleArray(); parent::__construct(); } /* Creates an array of possible (row, col) combinations. So that uniquely a random elemnt can be selected */ public function EleArray() { $EleArray = array(); foreach(range(0, 8) as $i ) foreach(range(0, 8) as $j ) $EleArray[] = array($i, $j); $this->EleArray = $EleArray; } public function FillRandomValue() { if( $this->EleArray === NULL ) throw new Exception('$this->EleArray() must be called before FillRandomValue', 1); $ele = array_rand( $this->EleArray ); $randCol = $this->EleArray[$ele][0]; $randRow = $this->EleArray[$ele][1]; unset($this->EleArray[$ele]); for ( $i = 1; $i <= 9; $i++ ) { if( $this->checkValid($randRow, $randCol, $i) ) { $this->_oSudoku[$randRow][$randCol] = $i; break; } } } public function GenerateSudoku( $difficulty ) { $this->EleArray(); for( $i = 0; $i < $difficulty; $i++ ) $this->FillRandomValue(); do { $this->FillRandomValue(); $this->Solve(); } while( $this->HasUnique() === self::NOT_UNIQUE ); } } class SudokuSolver { protected $_iSudoku = array(); protected $_oSudoku = array(); protected $_stack; protected $_blocks; protected $_oSudoku90; protected $_compare; const NOT_SOLVABLE = 10; const NOT_UNIQUE = 11; public function __construct( $sudoku = NULL, $stack = NULL, $seedVal = 0 ) { $this->seedVal = $seedVal; if ( $stack === NULL ) $this->_stack = new Stack(); else $this->_stack = $stack; if ( $sudoku === NULL ) $sudoku = str_repeat( "0", 81 ); /** Creates an sudoku array from the supplied string or empty string */ if ( is_string( $sudoku ) ): $sudoku = str_split( $sudoku, 9 ); array_walk( $sudoku, function( &$arg ) { $arg = str_split( $arg ); } ); endif; $this->_iSudoku = $this->_oSudoku = $sudoku; $this->_compare = range(1, 9); $this->_constuctBlock(); } // Constructs block of 3 x 3 array, and row wise block that can later be used for direct // finding of possibles instead of looping protected function _constuctBlock() { for ( $x = 0; $x < 9; $x++ ) { $this->_oSudoku90[$x] = array(); for ( $y = 0; $y < 9; $y++ ) { $this->_oSudoku90[$x][$y] = &$this->_oSudoku[$y][$x]; } } // create '_blocks' for ( $blockX = 0; $blockX < 3; $blockX++ ) { $this->_blocks[$blockX] = array(); for ( $blockY = 0; $blockY < 3; $blockY++ ) { $this->_blocks[$blockX][$blockY] = array(); $gridX = $blockX * 3; for ( $cellX = 0; $cellX < 3; $cellX++ ) { $gridY = $blockY * 3; for ( $cellY = 0; $cellY <3; $cellY++ ) { $this->_blocks[$blockX][$blockY][] = &$this->_oSudoku[$gridX][$gridY++]; } $gridX++; } } } } /** The following functions find the possibles for column, row and 3 x 3 block */ public function missingColumn($m) { return array_diff($this->_compare, $this->_oSudoku[$m]); } public function missingRow($n) { return array_diff($this->_compare, $this->_oSudoku90[$n]); } public function missingBlock($m,$n) { return array_diff($this->_compare, $this->_blocks[$m][$n]); } /* An intersect of all the possibles finds the possibles obeying rules of sudoku */ public function possibles( $m, $n ) { return array_intersect( $this->missingBlock((int)$m / 3, (int)$n / 3), $this->missingColumn($m), $this->missingRow($n) ); } public function checkValid( $m, $n, $val ) { return in_array( $val, array_intersect( $this->missingBlock((int)$m / 3, (int)$n / 3), $this->missingColumn($m), $this->missingRow($n) )); } /** * Function checks if the sudoku has a unique solution */ public function HasUnique() { while ( !$this->_stack->isEmpty() ) { $stack = new Stack(); $oldSudoku = &$this->_oSudoku; list( $m, $n ) = $this->_stack->pop(); $val = $oldSudoku[$m][$n]; $oldSudoku[$m][$n] = 0; $sudoku = new SudokuSolver( $oldSudoku, $stack, $val ); if ( $sudoku->Solve() !== self::NOT_SOLVABLE ) return self::NOT_UNIQUE; } return TRUE; } public function Solve() { $m = $n = 0; fx: while ( $m !== 9 ): //Loop till 9 x 9 sudoku processed if ( ( (int)( $cell = &$this->_oSudoku[$m][$n] ) === 0 ) ) { foreach ( $this->possibles($m, $n) as $val) { $this->seedVal = 0; //If cell's value was less than value of $val means insertion //must be done otherwise it means it has returned from backtracking if( $cell < $val ) $cell = $val; else continue; $this->_stack->push( $m, $n ); //Record the insertion if ( $n === 8 ): $m += 1; $n = 0; else: $n += 1; endif; goto fx; ///if insertion was valid continue while } $this->_oSudoku[$m][$n] = 0; if ( $this->_stack->isEmpty() ) //If backtracked till begining return NOT SOLVABLE return self::NOT_SOLVABLE; else list( $m, $n ) = $this->_stack->pop(); //backtrack } else { if ( $n === 8 ): $m += 1; $n = 0; else: $n += 1; endif; } endwhile; } public function OutputArray() { return $this->_oSudoku; } public function OutputString() { array_walk( $this->_oSudoku, function( &$ele ) { $ele = implode( "", $ele ); } ); return implode( "", $this->_oSudoku ); } public function __toString() { return print_r( $this->_oSudoku, true ); } } class Stack { private $stk = array(); public function push($m, $n) { array_push( $this->stk, array($m, $n) ); } public function pop() { return array_pop($this->stk); } public function isEmpty() { return count($this->stk) === 0; } public function stackHeight() { return count( $this->stk ); } public function emptyStack() { while( !$this->isEmpty() ) $this->pop(); } } $sudoku = new SudokuGenerator(); $sudoku->GenerateSudoku( SudokuGenerator::METRIC_EASY ); $sudoku = new SudokuSolver($sudoku->OutputString()); $sudoku->Solve(); print $sudoku->OutputString();
Output for 7.4.1
351267849264385170000001023000010002000030000000002004140020000500143200632500001
Output for 7.4.0
457263891683451720200000043540302010000000004016000032034020100000000200120030000
Output for 7.3.13
453671829672839514891542673524167980306004150100200300200010430000453000000020000
Output for 7.3.12
253946178647150002100830000000600000501400000030205010010320504400561723000700000
Output for 7.3.11
637514289825679103400230500140300000302001000500420000004100020003000041200040000
Output for 7.3.10
678219030040500000510003042000002103020104050000000000031000500000401000700300421
Output for 7.3.9
364527189728169453519384672472698315853271946196435728235716894987040201601002000
Output for 7.3.8
371245689528176403460000210050000002000400031130062540000000304010000050040300120
Output for 7.3.7
426357891157264300000000200300001042000543000004002510002000000000100600010020403
Output for 7.3.6
456718290203000001010004003024005010130402000005300402000250100000043025002100000
Output for 7.3.5
546781392728653104300240000200304000004102000001506000002000003100005200003000410
Output for 7.3.4
657289401302401000000003200000014000040020300035000120003000040010040030400032010
Output for 7.3.3
235416789617538420000000130100000000002100000864357201301002000020003010050001340
Output for 7.3.2
415672893367518042200000051003200100000100000000043000000321004102000035000054200
Output for 7.3.1
637418290052000013400300005000240031000000000300105002040600000100520004023000106
Output for 7.3.0
325176894614389275789452316256793481478510020130000000000045100000621003040030002
Output for 7.2.26
346872159578416200120530000000320000001045602000601034005000000634100025002700010
Output for 7.2.25
346782951578146023020053000100020000200310040000400010030000105000030204014200300
Output for 7.2.24
137586429462793185589412637623857914741239568895641273354168792916325840200000301
Output for 7.2.23
256471389417326000000050120100000000300165742020030510034002001001000000000000034
Output for 7.2.22
467238519215467830030100200000321004300000072001004000100000450003000027000000361
Output for 7.2.21
243617895561843720000000060000000010020300640010000250000000030302104500100025074
Output for 7.2.20
243657819651849372789213456372165948194728530000304201060500023020030104010400000
Output for 7.2.19
126834907007000040004210503003000001000305420402001300005020000010500000000403012
Output for 7.2.18
456782190000453020320010400000004001001200030234000000102040050000136000000025003
Output for 7.2.17
123657849567824000000100302000500020000040003000302010002403160056210430301000250
Output for 7.2.16
316278459782435160054100203000001035001356042040002001000003000030000010025000000
Output for 7.2.15
367824915584631702000050043000140020000002004120300000010000250200000061400005030
Output for 7.2.14
423678591785241360001000000350020016064103020000000430100000000230000100500010240
Output for 7.2.13
172638495356217800040000001000000002000021603000000500401503020530002100020104000
Output for 7.2.12
174852693625731804000000200030046021502000000410003000200005000301604002040020100
Output for 7.2.11
457312689312678450006054012004200030003140000160500000001403205000000001025000300
Output for 7.2.10
617524839253167400004300261000001327102430056030200104001000000000000002000002000
Output for 7.1.12, 7.2.9
615327489278514300003000012000000000000130200406200001054001060020050130301400020
Output for 7.2.8
432576891567481302000000400200300100000000020005000000003205014004100200621700000
Output for 7.2.7
357489261641753890000026005010000004400317020200540013000200000000600130020001000
Output for 7.2.6
253784691178536402000100000431270000000040100000050000002010063310002005000060014
Output for 7.2.5
451789326236100405000000001000213000145000030020040000000402613000000000000031502
Output for 7.2.4
567481329849253671201000040400012000702046103130000000300005210000004005020100000
Output for 7.2.3
643578910015002304200100050030000100001030240400210000000003001020001400000004032
Output for 7.2.2
674289513385461279921357486753698142246175830100020000030002061002010004000000025
Output for 7.2.1
451783629678521300320046051000352010010400002002000000100000046040100003200000175
Output for 7.2.0
374158269568243701012000003100020000000400000200030010001000000025010034043600025
Output for 7.1.33
374625819689714325215389467451867900020531000030240000000003204140000500002400130
Output for 7.1.32
316578249275314680040200150000432001050061320000000000030100062020003000100020030
Output for 7.1.31
563417289472689501000253000030000400200164300014005062005002130300040000100000020
Output for 7.1.30
637218594124657830000300102300000400010530200000400600000000016240100000001002305
Output for 7.1.29
234567891718493526569128437473215689681749352952630174000000703000000210120050000
Output for 7.1.28
425167389361542700000000000000023010103000000000010402004030021000200500032051000
Output for 7.1.27
452761389678253014130000200000000030000102605315006420004310000000400100020605000
Output for 7.1.26
654137829783425601020000000240001350300000400015043200530200140400310000000504002
Output for 7.1.25
785369214946125378123748569518972400400010000230004100054601032307200001060030000
Output for 7.1.24
156378249247651803000002015030200000002413506010500000401025030000000104063100002
Output for 7.1.23
246317589513426700000000204001002000002004103005001406134000602000005340000230051
Output for 7.1.22
563714829214856370000320041000205013000001000100000200000000102001000035000100004
Output for 7.1.21
571463829283157406460020301100000003000000210030000000314000500020030100000000002
Output for 7.1.20
163758290000002003005430100030004050002000040041000730000501300000020014510043620
Output for 7.1.19
265317849417895236389246517574932681628154370030600420040508100050723000000461000
Output for 7.1.18
475183962689275314031004005000000000024000000000000201000010020003420100210030040
Output for 7.1.17
513246789762893145849175236657918324421637598380020010000002001030504002204001003
Output for 7.1.16
627841953183265470050000001240010030310420506005000140000003020000000060432050010
Output for 7.1.15
142673589678125003300000124403500210000231460000400005000310040021054000000002031
Output for 7.1.14
627451389541236700300000100003004020000005600200003501030012405010000000400300012
Output for 7.1.13
784263195152789436369145728475621803203000001010000200026010307540000012030500064
Output for 7.1.11
471683259658742301000105000003010020002034100010000000160350402000000030020060510
Output for 7.1.10
215436789678921403340050120063210050100000340000000002000300001020100030500002604
Output for 7.1.9
152647893673859021000000004000132050025004000431506000010300042300020010240010000
Output for 7.1.8
643572189275618304001004000050030020300050001420001003000000000000143502010020400
Output for 7.1.7
567823194489751362123649578274580013301406000000210040002100000000030200035002001
Output for 7.1.6
671328945238549761594716832357160420046200103010000000102605304003000010405000200
Output for 7.1.5
783452691162789534459361278645817302010030000000200010300520100500000000204100000
Output for 7.1.4
874936512123475869569182374786053201410200003000041000002010000001000400000020000
Output for 7.1.3
671482539382569147549137628263795481197843256458216370000301000000020010004650000
Output for 7.1.2
526738941471692358389514267295167430010000002043005610060000003152003004030000120
Output for 7.1.1
361748295247361800000502314000000001003204000002613000005100002004020103100000000
Output for 7.1.0
423657189576814032100000004000000010000000200200501003000100000054300021361482597

preferences:
105.03 ms | 401 KiB | 82 Q