---
title: "Writing a Sudoku Solver: Displaying the Grid"
date: 2023-04-10
draft: true
---

I previously dabbled with writing a [sudoku solver](https://gitlab.com/dgalbraith33/sudoku-solver)
but got carried away early on by making crazy speed improvements rather than actually improving the
solving ability. What I did enjoy about the project is making logical deductions rather than the
guess and backcheck method commonly employed.

I want to take another crack at doing this except this time focus on the question "Given the current
state what are any of the next possible deductions" without focusing on speed. Eventually I'd also 
like to take a crack at solving other types of sudokus (Chess Sudoku, Killer Sudoku, etc).

One of the issues I had last time as I was debugging was displaying the current board state in
a clean way so I could see what had gone wrong. So this time around I'm planning on writing a quick
HTML/javascript board state display to be able to visualize the board. For now I don't intend it to
be interactive, however I'll likely add that in the future.

## Creating a sudoku grid

I'm no front end dev so this may take some time. I literally just want to create an outline for the 
puzzle with nothing in it.

```html
<div class="container">
  <h1>Sudoku</h1>
  <div class="puzzle">nothing</div>
</div>
```

```css
.container {
  max-width: 800px;
  margin: auto;
}

.puzzle {
  border: 1px solid black;
}
```

{{< figure src="images/sudoku-1.png" alt="A box with nothing in it."
class="center-img" >}}

I'm not joking when I say I'm going to have to do baby steps here.

Next I'll try to actually make a square grid. The best way to do this is probably with flexbox or
something but I'm just gonna hard code some widths and heights.

Ok lets make this thing a width divisible by 9 so we can divide it into equal portions. I chose 630 
quite honestly because it was the first number below 800px that popped into my head divisible by 9.

Let's focus on the 9 main boxes in the grid now before worrying about the cells. I'll make each box
210 pixels tall and wide. And slap a big ole border on there. Let's make it 2px because we will 
want a narrower one for the cells.

```css
.puzzle {
  width: 630px;
  height: 630px;
}

.box {
  border: 2px solid black;
  width: 210px;
  height: 210px;
}
```

{{< figure src="images/sudoku-2.png" alt="Boxes stacked vertically."
class="center-img" >}}

Reload that and... right div's auto linebreak after them.

I think we can "float: left" these bad boys and...

{{< figure src="images/sudoku-3.png" alt="Boxes stacked vertically in pairs."
class="center-img" >}}

Right, now I'm pretty sure the boxes are 210 + 4 pixels wide because the border
isn't included. While I'm tempted to just math my way out of this I recall that
you can specify the border-box sizing to avoid this.

Now this works! Now the astute of you may have noticed that there were 10 not 9 boxes in the 
screenshot with the 2 columns. That became even more obvious in the full grid.

{{< figure src="images/sudoku-4.png" alt="A 3x3 grid of boxes with one extra below it." 
class="center-img" >}} 

Ok now we can just recreate all of this with the cells and should be good to go right?

Nope! The internal size of the boxes are now only 206x206 because of the
border-box attribute. But I now realize I can just get rid of the puzzle sizing
all together and go back to regular sizing on the boxes. This happens to work
because 4 214px boxes won't fit in the 800px wide container. (Again just use
flexbox).

Finally this works!

{{< figure src="images/sudoku-5.png" alt="A 3x3 grid of boxes." class="center-img" >}} 

## Displaying a puzzle

Next up is to actually get some numbers in this bad boy. Now this is where I relent and use
flexboxes because
[this](https://stackoverflow.com/questions/2939914/how-do-i-vertically-align-text-in-a-div/13515693)
StackOverflow answer convinced me.

```css
.cell {
  ...

  font-size: 40px;
  font-weight: bold;
  display: flex;
  align-items: center;
  justify-content: center;
}
```

{{< figure src="images/sudoku-6.png" alt="A box with 9 cells in it." class="center-img" >}} 

### Taking the puzzle from the URL

Now to make it so I can get the page to display any puzzle I want easily from the solver, I'll allow
specifying it as a parameter in the URL. For now in a row-major string of 81 characters using a
period to denote blank spaces.

I'll can just get all of the cells by class name and iterate over them in the same order as the
puzzle string and it will display relatively easily.


```js
window.onload = (event) => {
  var params = new URLSearchParams(window.location.search);
  var puzzle = params.get("p");
  if (puzzle === null) {
    return;
  }
  if (puzzle.length != 81) {
    console.log("Failure: puzzle url len is " + puzzle.length);
    return;
  }
  var cells = document.getElementsByClassName("cell");
  if (cells.length != 81) {
    console.log("Failure: wrong number of cells: " + cells.length);
    return;
  }

  for (i = 0; i < 81; i++) {
    if (puzzle[i] != '.') {
      cells[i].innerText = puzzle[i]
    }
  }
}
```

And hooray it works super well!

{{< figure src="images/sudoku-7.png" alt="A full sudoku puzzle!" class="center-img" >}} 

Oh wait... I didn't think about the fact that the elements in the HTMLCollection from the 
document.getElementsByClassName call wouldn't be in the row order of the puzzle (all of the cells
in box 1 come first).

You can see the effect of this as there are 2 9s in column 2 of the puzzle. Oops.

I'm going to just do the old fashioned brute force way and give each cell an id from 1-81 and insert
those manually. I'm sure there is a better way but hey this works.

Then with a quick update to the code.

```js
for (i = 0; i < 81; i++) {
  if (puzzle[i] != '.') {
    document.getElementById(i+1).innerText = puzzle[i]
  }
}
```

It works!

{{< figure src="images/sudoku-8.png" alt="A full sudoku puzzle for real this time!" class="center-img" >}} 

Still some goofiness like the border on the outside being thinner than the interiors but I'm pretty
happy with this for now.

## Showing pencil marks

Now to really visualize the solver's state, we'll also need to see which pencil marks it has.
These could be styled nicely but for now I just went with a span inside the cell div with the
following style.

```css
.cell > span {
  font-size: 10px;
  font-weight: normal;
  text-align: center;
  letter-spacing: 6px;
  word-wrap: anywhere;
}
```

The letter-spacing and wordwrap attributes let us just jam all of the pencil marks in as a single
string and let the browser break them up into multiple lines for us. 

This comes out quite nicely:

{{< figure src="images/sudoku-9.png" alt="The top boxes of a sudoku puzzle with pencil marks"
class="center-img" >}} 

### Reading the pencil marks from the url

For this url trick we will add the pencil marks using a comma separated array like so:

123,,,,456,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

Using the string above we can use the following javascript code to parse and insert them:

```js
  var marks_param = params.get("m");
  if (marks_param === null) {
    return;
  }
  var marks = marks_param.split(",");

  if (marks.length != 81) {
    console.log("Failure: marks url len is " + marks.length);
    return;
  }

  for (i = 0; i < 81; i++) {
    if (marks[i].length > 0) {
      var cell = document.getElementById(i+1);
      if (cell.innerHTML.trim().length > 0) {
        console.log("Pencil marks in cell with number: " + (i+1));
      } else {
        cell.innerHTML = "<span>" + marks[i] + "</span>";
      }
    }
  }
```

Which also comes out nicely:

{{< figure src="images/sudoku-10.png" alt="The top boxes of a sudoku puzzle with pencil marks"
class="center-img" >}} 
