# freeCodeCamp Challenge Guide: Sudoku

**URL:** <https://forum.freecodecamp.org/t/freecodecamp-challenge-guide-sudoku/302329>\
**Category:** freeCodeCamp Contributors\
**Tags:** guide\
**Created:** [August 3, 2019, 6:45pm UTC](https://forum.freecodecamp.org/t/freecodecamp-challenge-guide-sudoku/302329 "2019-08-03T18:45:14Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![camperbot](https://sea3.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/camperbot/32/18364_2.png) [@camperbot](https://forum.freecodecamp.org/u/camperbot)\
**Post date:** [August 3, 2019, 6:45pm UTC](https://forum.freecodecamp.org/t/freecodecamp-challenge-guide-sudoku/302329/1 "2019-08-03T18:45:14Z")

</div>

# [Sudoku](https://www.freecodecamp.org/learn/coding-interview-prep/rosetta-code/sudoku)

* * *

## Solutions

> **Solution 1 (Click to Show/Hide)**
>
> ```javascript
> function solveSudoku(puzzle) {
> var solution;
> 
> class DoX {
> constructor(V, H) {
> this.V = V;
> this.L = this;
> this.R = this;
> this.U = this;
> this.D = this;
> this.S = 1;
> this.H = H || this;
> H && (H.S += 1);
> }
> }
> 
> const addRight = (e, n) => {
> n.R = e.R;
> n.L = e;
> e.R.L = n;
> return e.R = n;
> };
> 
> const addBelow = (e, n) => {
> n.D = e.D;
> n.U = e;
> e.D.U = n;
> return e.D = n;
> };
> 
> const search = function(h, s) {
> if (h.R == h) {
> printSol(s);
> } else {
> let c = chooseColumn(h);
> cover(c);
> for (let r = c.D; r != c; r = r.D) {
> s.push(r);
> for (let j = r.R; r != j; j = j.R) {
> cover(j.H);
> }
> search(h, s);
> r = s.pop();
> for (let j = r.R; j != r; j = j.R) {
> uncover(j.H);
> }
> }
> uncover(c);
> }
> };
> 
> const chooseColumn = h => {
> let s = Number.POSITIVE_INFINITY;
> let c = h;
> for (let j = h.R; j != h; j = j.R) {
> if (j.S < s) {
> c = j;
> s = j.S;
> }
> }
> return c;
> };
> 
> const cover = c => {
> c.L.R = c.R;
> c.R.L = c.L;
> for (let i = c.D; i != c; i = i.D) {
> for (let j = i.R; j != i; j = j.R) {
> j.U.D = j.D;
> j.D.U = j.U;
> j.H.S = j.H.S - 1;
> }
> }
> };
> 
> const uncover = c => {
> for (let i = c.U; i != c; i = i.U) {
> for (let j = i.L; i != j; j = j.L) {
> j.H.S = j.H.S + 1;
> j.U.D = j;
> j.D.U = j;
> }
> }
> c.L.R = c;
> c.R.L = c;
> };
> 
> const printSol = a => {
> solution = a.reduce((p, c) => {
> let [i, v] = c.V.split(':');
> p[i * 1] = v;
> return p;
> }, new Array(a.length).fill('.'));
> };
> 
> const gridMeta = s => {
> const g = s.split('');
> const cellCount = g.length;
> const tokenCount = Math.sqrt(cellCount);
> const N = Math.sqrt(tokenCount);
> const g2D = g.map(e => isNaN(e * 1) ?
> new Array(tokenCount).fill(1).map((_, i) => i + 1) : [e * 1]);
> return [cellCount, N, tokenCount, g2D];
> };
> 
> const indexesN = n => i => {
> let c = Math.floor(i / (n * n));
> i %= n * n;
> return [c, i, Math.floor(c / n) * n + Math.floor(i / n)];
> };
> 
> const reduceGrid = puzString => {
> 
> const [
> numCells, // The total number of cells in a grid (81 for a 9x9 grid)
> N, // the 'n' value of the grid. (3 for a 9x9 grid)
> U, // The total number of unique tokens to be placed.
> g2D // A 2D array representation of the grid, with each element
> // being an array of candidates for a cell. Known cells are
> // single element arrays.
> ] = gridMeta(puzString);
> 
> const getIndex = indexesN(N);
> 
> const headRow = new Array(4 * numCells)
> .fill('')
> .map((_, i) => new DoX(`H${i}`));
> 
> let H = new DoX('ROOT');
> headRow.reduce((p, c) => addRight(p, c), H);
> 
> for (let i = 0; i < numCells; i++) {
> const [ri, ci, bi] = getIndex(i);
> g2D[i].forEach(num => {
> let id = `${i}:${num}`;
> let candIdx = num - 1;
> 
> // The 4 columns that we will populate.
> const A = headRow[i];
> const B = headRow[numCells + candIdx + (ri * U)];
> const C = headRow[(numCells * 2) + candIdx + (ci * U)];
> const D = headRow[(numCells * 3) + candIdx + (bi * U)];
> 
> // The Row-Column Constraint
> let rcc = addBelow(A.U, new DoX(id, A));
> 
> // The Row-Number Constraint
> let rnc = addBelow(B.U, addRight(rcc, new DoX(id, B)));
> 
> // The Column-Number Constraint
> let cnc = addBelow(C.U, addRight(rnc, new DoX(id, C)));
> 
> // The Block-Number Constraint
> addBelow(D.U, addRight(cnc, new DoX(id, D)));
> });
> }
> search(H, []);
> };
> 
> var stringPuzzle = "";
> 
> for (var i = 0; i < puzzle.length; i++) {
> puzzle[i].forEach(function(e) {
> if (e == -1)
> stringPuzzle += ".";
> else
> stringPuzzle += e;
> })
> }
> 
> reduceGrid(stringPuzzle)
> 
> var result = [];
> 
> for (var i = 0; i < 9; i++) {
> result.push(solution.slice(i * 9, (i + 1) * 9).map(e => parseInt(e)))
> }
> 
> return result;
> }
> 
> ```

---

<div class="post-metadata">

**Author:** ![ILM](https://sea3.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/ilm/32/363239_2.png) [@ILM](https://forum.freecodecamp.org/u/ILM)\
**Post date:** [January 8, 2025, 3:49pm UTC](https://forum.freecodecamp.org/t/freecodecamp-challenge-guide-sudoku/302329/2 "2025-01-08T15:49:05Z")

</div>


