Sudoku solver in CoffeeScript
Posted by Jonas Elfström Tue, 19 Apr 2011 13:46:00 GMT
CoffeeScript 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 JavaScript lint without warnings.
"Underneath all of those embarrassing braces and semicolons, JavaScript has always had a gorgeous object model at its heart." - Jeremy Ashkenas
About a week ago I stumbled on the very clever Sudoku solver by Peter Norvig. I have nothing (or at least not much) against Python but I pretty soon checked out the Ruby translations of the solver. I then refactored one of the solutions to get a chance to get to know the algorithm better.
Now that I finally installed CoffeeScript 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.
1 2 3 |
def cross(A, B): "Cross product of elements in A and elements in B." return [a+b for a in A for b in B] |
returns an one-dimensional array if you call it with two arrays (or strings).
But in CoffeeScript
cross = (A, B) -> (a+b for a in A for b in B) |
returns a two-dimensional array.
The jury is still out on if this is intended or not but either way the array comprehensions in CoffeeScript are still very useful.
It's been decided that this is by design. The issue has been closed.
For the cross
-function I ended up with
1 2 3 4 5 6 |
cross = (A, B) -> results = [] for a in A for b in B results.push a + b results |
Using `map` I could have got much closer to the Ruby version.
1 2 |
cross = (cols, rows) -> [].concat (cols.map (x) -> rows.map (y) -> y+x)... |
You can find the CoffeScript Sudoku solver as a Gist. Compile it with
coffee -c sudoku.coffee
and then run it with
node sudoku.js
I don't know how I missed it but as Trevor pointed out below all you have to do is
coffee sudoku.coffee
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| |------+-----+-----|
Here's the generated sudoku.js.
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.
Nice post. By the way, you can just do
coffee sudoku.coffee
instead ofcoffee -c sudoku.coffee; node sudoku.js
.Didn’t know that. Thanks!
I didn’t write nearly enough about why I like CoffeeScript. Fortunately Trevor sums it up very good at http://www.pragprog.com/magazines/2011-05/a-coffeescript-intervention
“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 http://brendaneich.com/2011/01/harmony-of-my-dreams/
I also think your blog is so wonderful to keep sight of! :-P
Spambottarna smickrar, trevligt.
The list comprehension issue has been reopened because of this post CoffeeScript Comprehensions Are Broken
A reply from Trevor Burnham
The issue