Alice, Bob, and Mallory: Sudoku solver in CoffeeScriptmetasyntacticstag:alicebobandmallory.com,2005:TypoTypo2011-06-02T23:21:31+02:00Jonas Elfströmurn:uuid:12b7c916-c5eb-4510-ac0a-0efcfd2412252011-04-19T15:46:00+02:002011-06-02T23:21:31+02:00Sudoku solver in CoffeeScript<p><a href="http://jashkenas.github.com/coffee-script/">CoffeeScript</a> is inspired by Ruby and Python but what's most peculiar with it is that it compiles to JavaScript. The generated JavaScript isn't all that bad and it even passes <a href="http://www.javascriptlint.com/">JavaScript lint</a> without warnings.</p>
<p>"Underneath all of those embarrassing braces and semicolons, JavaScript has always had a gorgeous object model at its heart." - Jeremy Ashkenas</p>
<p>About a week ago I stumbled on the very clever <a href="http://norvig.com/sudoku.html">Sudoku solver by Peter Norvig</a>. I have nothing (or at least not much) against Python but I pretty soon checked out the Ruby translations of the solver. I then <a href="https://gist.github.com/914326">refactored one</a> of the solutions to get a chance to get to know the algorithm better.</p>
<p>Now that I finally <a href="http://jashkenas.github.com/coffee-script/#installation">installed CoffeeScript</a> the Sudoku solver came to mind. I dived in head first and got in trouble pretty soon. It turns out that Array Comprehensions in CoffeeScript differs some from the List Comprehensions in Python.</p>
<table class="CodeRay"><tr>
<td class="line-numbers" title="double click to toggle" ondblclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre><a href="#n1" name="n1">1</a>
<a href="#n2" name="n2">2</a>
<a href="#n3" name="n3">3</a>
</pre></td>
<td class="code"><pre><span style="color:#080;font-weight:bold">def</span> <span style="color:#06B;font-weight:bold">cross</span>(<span style="color:#036;font-weight:bold">A</span>, <span style="color:#036;font-weight:bold">B</span>):
<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">Cross product of elements in A and elements in B.</span><span style="color:#710">"</span></span>
<span style="color:#080;font-weight:bold">return</span> [a+b <span style="color:#080;font-weight:bold">for</span> a <span style="color:#080;font-weight:bold">in</span> <span style="color:#036;font-weight:bold">A</span> <span style="color:#080;font-weight:bold">for</span> b <span style="color:#080;font-weight:bold">in</span> <span style="color:#036;font-weight:bold">B</span>]</pre></td>
</tr></table>
<p>returns an one-dimensional array if you call it with two arrays (or strings).</p>
<p>But in CoffeeScript </p>
<table class="CodeRay"><tr>
<td class="line-numbers" title="double click to toggle" ondblclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>
</pre></td>
<td class="code"><pre>cross = (<span style="color:#036;font-weight:bold">A</span>, <span style="color:#036;font-weight:bold">B</span>) -> (a+b <span style="color:#080;font-weight:bold">for</span> a <span style="color:#080;font-weight:bold">in</span> <span style="color:#036;font-weight:bold">A</span> <span style="color:#080;font-weight:bold">for</span> b <span style="color:#080;font-weight:bold">in</span> <span style="color:#036;font-weight:bold">B</span>)</pre></td>
</tr></table>
<p>returns a two-dimensional array.</p>
<p><a href="https://github.com/jashkenas/coffee-script/issues/1191">The jury</a> is still out on <a href="http://stackoverflow.com/questions/5685449/nested-array-comprehensions-in-coffeescript">if this is intended</a> or not but either way the <a href="http://en.wikipedia.org/wiki/List_comprehension">array comprehensions</a> in CoffeeScript are still very useful.</p>
<div style="background-color: #F0F0F0">
<font color="red">EDIT 2011-06-02</font><br>
It's been decided that this is by design. The issue has been closed.
</div>
<p><br>
For the <code>cross</code>-function I ended up with</p>
<table class="CodeRay"><tr>
<td class="line-numbers" title="double click to toggle" ondblclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre><a href="#n1" name="n1">1</a>
<a href="#n2" name="n2">2</a>
<a href="#n3" name="n3">3</a>
<a href="#n4" name="n4">4</a>
<a href="#n5" name="n5">5</a>
<a href="#n6" name="n6">6</a>
</pre></td>
<td class="code"><pre>cross = (<span style="color:#036;font-weight:bold">A</span>, <span style="color:#036;font-weight:bold">B</span>) ->
results = []
<span style="color:#080;font-weight:bold">for</span> a <span style="color:#080;font-weight:bold">in</span> <span style="color:#036;font-weight:bold">A</span>
<span style="color:#080;font-weight:bold">for</span> b <span style="color:#080;font-weight:bold">in</span> <span style="color:#036;font-weight:bold">B</span>
results.push a + b
results</pre></td>
</tr></table>
<p><br/></p>
<div style="background-color: #F0F0F0">
<font color="red">EDIT 2011-06-02</font><br>
Using `map` I could have got much closer to the Ruby version.
<table class="CodeRay"><tr>
<td class="line-numbers" title="double click to toggle" ondblclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre><a href="#n1" name="n1">1</a>
<a href="#n2" name="n2">2</a>
</pre></td>
<td class="code"><pre>cross = (cols, rows) ->
[].concat (cols.map (x) -> rows.map (y) -> y+x)...</pre></td>
</tr></table>
I'm still more of a map/reduce guy than a list comprehension ninja.
</div>
<p><br><br>
You can find the <a href="https://gist.github.com/927782">CoffeScript Sudoku solver as a Gist</a>. <strike>Compile it with<br/>
<code>coffee -c sudoku.coffee</code><br/>
and then run it with<br/>
<code>node sudoku.js</code></strike></p>
<p>I don't know how I missed it but as Trevor pointed out below all you have to do is<br/>
<code>coffee sudoku.coffee</code></p>
<pre>
1 2 3 4 5 6 7 8 9
|------+-----+-----|
A | 4 8 3|9 2 1|6 5 7|
B | 9 6 7|3 4 5|8 2 1|
C | 2 5 1|8 7 6|4 9 3|
|------+-----+-----|
D | 5 4 8|1 3 2|9 7 6|
E | 7 2 9|5 6 4|1 3 8|
F | 1 3 6|7 9 8|2 4 5|
|------+-----+-----|
G | 3 7 2|6 8 9|5 1 4|
H | 8 1 4|2 5 3|7 6 9|
I | 6 9 5|4 1 7|3 8 2|
|------+-----+-----|
</pre>
<p><a href="http://alicebobandmallory.com/sudoku.js.html">Here's</a> the generated <a href="http://alicebobandmallory.com/sudoku.js.html">sudoku.js</a>.</p>
<p>This is the only CoffeeScript I've ever written but I already like it (more than JavaScript). Please correct me if I strayed from the CoffeeScript way. </p><p><a href="http://jashkenas.github.com/coffee-script/">CoffeeScript</a> is inspired by Ruby and Python but what's most peculiar with it is that it compiles to JavaScript. The generated JavaScript isn't all that bad and it even passes <a href="http://www.javascriptlint.com/">JavaScript lint</a> without warnings.</p>
<p>"Underneath all of those embarrassing braces and semicolons, JavaScript has always had a gorgeous object model at its heart." - Jeremy Ashkenas</p>
<p>About a week ago I stumbled on the very clever <a href="http://norvig.com/sudoku.html">Sudoku solver by Peter Norvig</a>. I have nothing (or at least not much) against Python but I pretty soon checked out the Ruby translations of the solver. I then <a href="https://gist.github.com/914326">refactored one</a> of the solutions to get a chance to get to know the algorithm better.</p>
<p>Now that I finally <a href="http://jashkenas.github.com/coffee-script/#installation">installed CoffeeScript</a> the Sudoku solver came to mind. I dived in head first and got in trouble pretty soon. It turns out that Array Comprehensions in CoffeeScript differs some from the List Comprehensions in Python.</p>
<table class="CodeRay"><tr>
<td class="line-numbers" title="double click to toggle" ondblclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre><a href="#n1" name="n1">1</a>
<a href="#n2" name="n2">2</a>
<a href="#n3" name="n3">3</a>
</pre></td>
<td class="code"><pre><span style="color:#080;font-weight:bold">def</span> <span style="color:#06B;font-weight:bold">cross</span>(<span style="color:#036;font-weight:bold">A</span>, <span style="color:#036;font-weight:bold">B</span>):
<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">Cross product of elements in A and elements in B.</span><span style="color:#710">"</span></span>
<span style="color:#080;font-weight:bold">return</span> [a+b <span style="color:#080;font-weight:bold">for</span> a <span style="color:#080;font-weight:bold">in</span> <span style="color:#036;font-weight:bold">A</span> <span style="color:#080;font-weight:bold">for</span> b <span style="color:#080;font-weight:bold">in</span> <span style="color:#036;font-weight:bold">B</span>]</pre></td>
</tr></table>
<p>returns an one-dimensional array if you call it with two arrays (or strings).</p>
<p>But in CoffeeScript </p>
<table class="CodeRay"><tr>
<td class="line-numbers" title="double click to toggle" ondblclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>
</pre></td>
<td class="code"><pre>cross = (<span style="color:#036;font-weight:bold">A</span>, <span style="color:#036;font-weight:bold">B</span>) -> (a+b <span style="color:#080;font-weight:bold">for</span> a <span style="color:#080;font-weight:bold">in</span> <span style="color:#036;font-weight:bold">A</span> <span style="color:#080;font-weight:bold">for</span> b <span style="color:#080;font-weight:bold">in</span> <span style="color:#036;font-weight:bold">B</span>)</pre></td>
</tr></table>
<p>returns a two-dimensional array.</p>
<p><a href="https://github.com/jashkenas/coffee-script/issues/1191">The jury</a> is still out on <a href="http://stackoverflow.com/questions/5685449/nested-array-comprehensions-in-coffeescript">if this is intended</a> or not but either way the <a href="http://en.wikipedia.org/wiki/List_comprehension">array comprehensions</a> in CoffeeScript are still very useful.</p>
<div style="background-color: #F0F0F0">
<font color="red">EDIT 2011-06-02</font><br>
It's been decided that this is by design. The issue has been closed.
</div>
<p><br>
For the <code>cross</code>-function I ended up with</p>
<table class="CodeRay"><tr>
<td class="line-numbers" title="double click to toggle" ondblclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre><a href="#n1" name="n1">1</a>
<a href="#n2" name="n2">2</a>
<a href="#n3" name="n3">3</a>
<a href="#n4" name="n4">4</a>
<a href="#n5" name="n5">5</a>
<a href="#n6" name="n6">6</a>
</pre></td>
<td class="code"><pre>cross = (<span style="color:#036;font-weight:bold">A</span>, <span style="color:#036;font-weight:bold">B</span>) ->
results = []
<span style="color:#080;font-weight:bold">for</span> a <span style="color:#080;font-weight:bold">in</span> <span style="color:#036;font-weight:bold">A</span>
<span style="color:#080;font-weight:bold">for</span> b <span style="color:#080;font-weight:bold">in</span> <span style="color:#036;font-weight:bold">B</span>
results.push a + b
results</pre></td>
</tr></table>
<p><br/></p>
<div style="background-color: #F0F0F0">
<font color="red">EDIT 2011-06-02</font><br>
Using `map` I could have got much closer to the Ruby version.
<table class="CodeRay"><tr>
<td class="line-numbers" title="double click to toggle" ondblclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre><a href="#n1" name="n1">1</a>
<a href="#n2" name="n2">2</a>
</pre></td>
<td class="code"><pre>cross = (cols, rows) ->
[].concat (cols.map (x) -> rows.map (y) -> y+x)...</pre></td>
</tr></table>
I'm still more of a map/reduce guy than a list comprehension ninja.
</div>
<p><br><br>
You can find the <a href="https://gist.github.com/927782">CoffeScript Sudoku solver as a Gist</a>. <strike>Compile it with<br/>
<code>coffee -c sudoku.coffee</code><br/>
and then run it with<br/>
<code>node sudoku.js</code></strike></p>
<p>I don't know how I missed it but as Trevor pointed out below all you have to do is<br/>
<code>coffee sudoku.coffee</code></p>
<pre>
1 2 3 4 5 6 7 8 9
|------+-----+-----|
A | 4 8 3|9 2 1|6 5 7|
B | 9 6 7|3 4 5|8 2 1|
C | 2 5 1|8 7 6|4 9 3|
|------+-----+-----|
D | 5 4 8|1 3 2|9 7 6|
E | 7 2 9|5 6 4|1 3 8|
F | 1 3 6|7 9 8|2 4 5|
|------+-----+-----|
G | 3 7 2|6 8 9|5 1 4|
H | 8 1 4|2 5 3|7 6 9|
I | 6 9 5|4 1 7|3 8 2|
|------+-----+-----|
</pre>
<p><a href="http://alicebobandmallory.com/sudoku.js.html">Here's</a> the generated <a href="http://alicebobandmallory.com/sudoku.js.html">sudoku.js</a>.</p>
<p>This is the only CoffeeScript I've ever written but I already like it (more than JavaScript). Please correct me if I strayed from the CoffeeScript way. </p>Jonas Elfströmurn:uuid:dad4a185-f89c-4d42-a29d-570c81acec1e2011-09-13T16:02:21+02:002011-09-13T23:13:39+02:00Comment on Sudoku solver in CoffeeScript by Jonas Elfström<p>The list comprehension issue has been reopened because of this post
<a href="http://brehaut.net/blog/2011/coffeescript_comprehensions">CoffeeScript Comprehensions Are Broken</a></p>
<p><a href="http://brehaut.net/blog/2011/coffeescript_comprehensions_reply">A reply from Trevor Burnham</a></p>
<p><a href="https://github.com/jashkenas/coffee-script/issues/1191#issuecomment-2081256">The issue</a></p>Jakob Erikssonurn:uuid:f7429c79-ed83-4059-81e9-db7d2ebf96952011-05-25T08:59:39+02:002011-05-25T21:15:33+02:00Comment on Sudoku solver in CoffeeScript by Jakob Eriksson<p>I also think your blog is so wonderful to keep sight of! :-P</p>
<p>Spambottarna smickrar, trevligt.</p>Jonas Elfströmurn:uuid:4116aa92-8196-401e-b418-eb5f950aea5f2011-05-19T20:49:27+02:002011-05-25T21:07:40+02:00Comment on Sudoku solver in CoffeeScript by Jonas Elfström<p>“CoffeeScript is well done and more convenient to use than JS, provided you buy into the Python-esque significant space and the costs of generating JS from another source language. But semantically it’s still JS.” - Brendan Eich <a href="http://brendaneich.com/2011/01/harmony-of-my-dreams/">http://brendaneich.com/2011/01/harmony-of-my-dreams/</a></p>Jonas Elfströmurn:uuid:c7bc0ec5-2055-4838-9465-6cab3ad3f5ca2011-05-04T21:32:59+02:002011-05-09T20:11:28+02:00Comment on Sudoku solver in CoffeeScript by Jonas Elfström<p>I didn’t write nearly enough about why I like CoffeeScript. Fortunately Trevor sums it up very good at <a href="http://www.pragprog.com/magazines/2011-05/a-coffeescript-intervention">http://www.pragprog.com/magazines/2011-05/a-coffeescript-intervention</a></p>Jonas Elfströmurn:uuid:e9c020f8-7db1-42e1-8ac5-a5e196fe6fbe2011-04-20T21:35:18+02:002011-04-20T21:39:35+02:00Comment on Sudoku solver in CoffeeScript by Jonas Elfström<p>Didn’t know that. Thanks!</p>Trevor Burnhamurn:uuid:cf5912f0-cc11-48f4-9067-815328fd3cef2011-04-20T21:01:01+02:002011-04-20T21:39:34+02:00Comment on Sudoku solver in CoffeeScript by Trevor Burnham<p>Nice post. By the way, you can just do <code>coffee sudoku.coffee</code> instead of <code>coffee -c sudoku.coffee; node sudoku.js</code>.</p>