First pass at md to html conversion

This commit is contained in:
Drew Galbraith 2023-05-03 17:20:12 -07:00
parent be11a2ee83
commit 25a8a078bb
13 changed files with 256 additions and 3 deletions

View File

@ -1,9 +1,8 @@
---
title: Writing a Sudoku Solver
title: "Writing a Sudoku Solver: Displaying the Grid"
date: 2023-04-10
---
# Writing a Sudoku Solver: Displaying the Grid
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

17
blog/pandoc.html Normal file
View File

@ -0,0 +1,17 @@
<!DOCTYPE html>
$-- Run with the following command:
$-- pandoc -s --template=blog/pandoc.html -o public/blog/sudoku.html blog/2023-04-10-sudoku.md
<html>
<head>
<meta charset="utf-8" />
<title>$title$</title>
<link rel="stylesheet" href="/css/styles.css">
</head>
<body>
<div class="container">
<h1 class="page-title">$title$</h1>
<div class="date">Published $date$</div>
$body$
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -0,0 +1,237 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Writing a Sudoku Solver: Displaying the Grid</title>
<link rel="stylesheet" href="/css/styles.css">
</head>
<body>
<div class="container">
<h1>Writing a Sudoku Solver: Displaying the Grid</h1>
<div class="date">Published 2023-04-10</div>
<p>I previously dabbled with writing a <a
href="https://gitlab.com/dgalbraith33/sudoku-solver">sudoku
solver</a> 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.</p>
<p>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 Id also
like to take a crack at solving other types of sudokus (Chess
Sudoku, Killer Sudoku, etc).</p>
<p>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 Im planning on writing a
quick HTML/javascript board state display to be able to visualize
the board. For now I dont intend it to be interactive, however Ill
likely add that in the future.</p>
<h2 id="creating-a-sudoku-grid">Creating a sudoku grid</h2>
<p>Im 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.</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode html"><code class="sourceCode html"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">&lt;div</span> <span class="er">class</span><span class="ot">=</span><span class="st">&quot;container&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a> <span class="kw">&lt;h1&gt;</span>Sudoku<span class="kw">&lt;/h1&gt;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">&lt;div</span> <span class="er">class</span><span class="ot">=</span><span class="st">&quot;puzzle&quot;</span><span class="kw">&gt;</span>nothing<span class="kw">&lt;/div&gt;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">&lt;/div&gt;</span></span></code></pre></div>
<div class="sourceCode" id="cb2"><pre
class="sourceCode css"><code class="sourceCode css"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="fu">.container</span> {</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a> <span class="kw">max-width</span>: <span class="dv">800</span><span class="dt">px</span><span class="op">;</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">margin</span>: <span class="bu">auto</span><span class="op">;</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>}</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="fu">.puzzle</span> {</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a> <span class="kw">border</span>: <span class="dv">1</span><span class="dt">px</span> <span class="dv">solid</span> <span class="cn">black</span><span class="op">;</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
<figure>
<img src="images/sudoku-1.png" alt="border" />
<figcaption aria-hidden="true">border</figcaption>
</figure>
<p>Im not joking when I say Im going to have to do baby steps
here.</p>
<p>Next Ill try to actually make a square grid. The best way to do
this is probably with flexbox or something but Im just gonna hard
code some widths and heights.</p>
<p>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.</p>
<p>Lets focus on the 9 main boxes in the grid now before worrying
about the cells. Ill make each box 210 pixels tall and wide. And
slap a big ole border on there. Lets make it 2px because we will
want a narrower one for the cells.</p>
<pre><code>.puzzle {
width: 630px;
height: 630px;
}
.box {
border: 2px solid black;
width: 210px;
height: 210px;
}</code></pre>
<figure>
<img src="images/sudoku-2.png" alt="boxes" />
<figcaption aria-hidden="true">boxes</figcaption>
</figure>
<p>Reload that and… right divs auto linebreak after them.</p>
<p>I think we can “float: left” these bad boys and…</p>
<figure>
<img src="images/sudoku-3.png" alt="boxes2" />
<figcaption aria-hidden="true">boxes2</figcaption>
</figure>
<p>Right, now Im pretty sure the boxes are 210 + 4 pixels wide
because the border isnt included. While Im tempted to just math my
way out of this I recall that you can specify the border-box sizing
to avoid this.</p>
<p>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.</p>
<figure>
<img src="images/sudoku-4.png" alt="boxes3" />
<figcaption aria-hidden="true">boxes3</figcaption>
</figure>
<p>Ok now we can just recreate all of this with the cells and should
be good to go right?</p>
<p>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 wont fit in the
800px wide container. (Again just use flexbox).</p>
<p>Finally this works!</p>
<figure>
<img src="images/sudoku-5.png" alt="grid" />
<figcaption aria-hidden="true">grid</figcaption>
</figure>
<h2 id="displaying-a-puzzle">Displaying a puzzle</h2>
<p>Next up is to actually get some numbers in this bad boy. Now this
is where I relent and use flexboxes because <a
href="https://stackoverflow.com/questions/2939914/how-do-i-vertically-align-text-in-a-div/13515693">this</a>
StackOverflow answer convinced me.</p>
<pre><code>.cell {
...
font-size: 40px;
font-weight: bold;
display: flex;
align-items: center;
justify-content: center;
}</code></pre>
<figure>
<img src="images/sudoku-6.png" alt="cell number" />
<figcaption aria-hidden="true">cell number</figcaption>
</figure>
<h3 id="taking-the-puzzle-from-the-url">Taking the puzzle from the
URL</h3>
<p>Now to make it so I can get the page to display any puzzle I want
easily from the solver, Ill 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.</p>
<p>Ill 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.</p>
<pre><code>window.onload = (event) =&gt; {
var params = new URLSearchParams(window.location.search);
var puzzle = params.get(&quot;p&quot;);
if (puzzle === null) {
return;
}
if (puzzle.length != 81) {
console.log(&quot;Failure: puzzle url len is &quot; + puzzle.length);
return;
}
var cells = document.getElementsByClassName(&quot;cell&quot;);
if (cells.length != 81) {
console.log(&quot;Failure: wrong number of cells: &quot; + cells.length);
return;
}
for (i = 0; i &lt; 81; i++) {
if (puzzle[i] != &#39;.&#39;) {
cells[i].innerText = puzzle[i]
}
}
}</code></pre>
<p>And hooray it works super well!</p>
<figure>
<img src="images/sudoku-7.png" alt="bad puzzles" />
<figcaption aria-hidden="true">bad puzzles</figcaption>
</figure>
<p>Oh wait… I didnt think about the fact that the elements in the
HTMLCollection from the document.getElementsByClassName call
wouldnt be in the row order of the puzzle (all of the cells in box
1 come first).</p>
<p>You can see the effect of this as there are 2 9s in column 2 of
the puzzle. Oops.</p>
<p>Im going to just do the old fashioned brute force way and give
each cell an id from 1-81 and insert those manually. Im sure there
is a better way but hey this works.</p>
<p>Then with a quick update to the code.</p>
<pre><code>for (i = 0; i &lt; 81; i++) {
if (puzzle[i] != &#39;.&#39;) {
document.getElementById(i+1).innerText = puzzle[i]
}
}</code></pre>
<p>It works!</p>
<figure>
<img src="images/sudoku-8.png" alt="good puzzle" />
<figcaption aria-hidden="true">good puzzle</figcaption>
</figure>
<p>Still some goofiness like the border on the outside being thinner
than the interiors but Im pretty happy with this for now.</p>
<h2 id="showing-pencil-marks">Showing pencil marks</h2>
<p>Now to really visualize the solvers state, well 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.</p>
<pre><code>.cell &gt; span {
font-size: 10px;
font-weight: normal;
text-align: center;
letter-spacing: 6px;
word-wrap: anywhere;
}</code></pre>
<p>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.</p>
<p>This comes out quite nicely:</p>
<figure>
<img src="images/sudoku-9.png" alt="pencil marks" />
<figcaption aria-hidden="true">pencil marks</figcaption>
</figure>
<h3 id="reading-the-pencil-marks-from-the-url">Reading the pencil
marks from the url</h3>
<p>For this url trick we will add the pencil marks using a comma
separated array like so:</p>
<p>123,,,,456,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,</p>
<p>Using the string above we can use the following javascript code
to parse and insert them:</p>
<pre><code> var marks_param = params.get(&quot;m&quot;);
if (marks_param === null) {
return;
}
var marks = marks_param.split(&quot;,&quot;);
if (marks.length != 81) {
console.log(&quot;Failure: marks url len is &quot; + marks.length);
return;
}
for (i = 0; i &lt; 81; i++) {
if (marks[i].length &gt; 0) {
var cell = document.getElementById(i+1);
if (cell.innerHTML.trim().length &gt; 0) {
console.log(&quot;Pencil marks in cell with number: &quot; + (i+1));
} else {
cell.innerHTML = &quot;&lt;span&gt;&quot; + marks[i] + &quot;&lt;/span&gt;&quot;;
}
}
}</code></pre>
<p>Which also comes out nicely:</p>
<figure>
<img src="images/sudoku-10.png" alt="full puzzle" />
<figcaption aria-hidden="true">full puzzle</figcaption>
</figure>
</div>
</body>
</html>