It was suggested in the comments that there was a better way to pass the history around, and the suggestion was correct. I tried Storable and was not able to make it do what I wanted, so I went with Clone.

The main loop is much cleaner, and it works. Yay me! Yay readers! Yay Clone! Yay Perl! Next steps are to integrate this into a Sudoku maker, connect that via Ajax to my puzzle, and to to find good ways to input the puzzles in the first place.

At this point, I will say that I don't quite get the story of John Henry. There's a job that's tough, that's back-breaking work. John Henry was good at it, the best there was. The company thinks that crippling men and sending them to an early grave doesn't pay and brings in a machine to do that job. John Henry challenges the machine, they go head-to-head, and John Henry, the best there was, beats the machine, but dies at the end. So the one man who can beat the machine is in a pine box, with his widow left to care for his orphan children, and this is somehow a win. With some modification, I could see this turned into a sort of Luddite anti-machine parable, but as it stands, it just doesn't work like that.

I do Sudoku to pass my time and exercise my mind. I know I can't beat the machine. "Varlo Grant is a number-crunchin' man, Lord, Lord. Varlo is a number-crunchin' man."

How do people solve Sudoku puzzles? I can tell you how I do it. There are two different ways of deciding if a number should be in a place. Either a number must be there, or a number cannot be anywhere else. I go for as many "must be there" numbers as I can, with each number limiting the number of possibilities for other numbers, giving me more "must be there" numbers. Eventually I come to the point where I start seeing "can't be elsewhere" places, where there's many open spots but the 8 can only be in one of 'em. And once I finish with all the things that have to be there, there's loops where two numbers are left and I have to choose one and see if it works out.

I use gnome-sudoku as I use a Gnome desktop, although sometimes I do puzzles on paper. Either way, there's note-taking. There is, to use a computer science term, state. If I put something down wrong, I have to erase everything about that. On paper, multiple erasures look bad and eventually tear away the paper. On the computer, it's easier, but still, there is a penalty for being wrong, if only in my head, which makes you careful about guessing. Basically, you guess when you can no longer prove. This works well for the human mind. I think this can be abstracted to other human activities. People improvise on guitars because the cost of blowing a note is only temporary embarrassment. People don't improvise so much in designing buildings because the cost of blowing architecture is several months of time, several million dollars and possibly several lives.

Computers, on the other hand, don't care. Depending on your algorithm, your state is ephemeral, tossed away as soon as as you know it's wrong.

Basically, take a position (in a specific and set order — tried a more chainy algorithm based upon my Boggle code [which I might post and discuss later], but it sucked), make a guess, check the state and go on. The key is to make the state passable. I'll get into details in a bit, but early on I tried copying an array. A Sudoku puzzle is a 9x9 square, which implies a 9x9 multidimensional array. But Perl, the implementation language I used, does not have multidimensional arrays. It has arrays of arrays. Assuming $array[0][1] = 2, @array is an array of pointers to anonymous arrays, and the second value in the first anonymous array (remember, computer people start counting at 0). The practical upside of this is that my @new_array = @array doesn't recreate the multidimensional array. It passes a set of pointers to anonymous arrays from one array to another. So, my choice was to make a scalar value holding the state that can easily be broken up into an array, rather than passing arrays around.

Modern::Perl for the win. Thanks, chromatic. Not that I probably couldn't get this working better, but we'll go with what we have. And I probably could cleans some unused variables from this section, but so be it. If I wanted to read in puzzles from standard in or something, I would've done something with Getopt::Long, but that wasn't the part that interested me.

One thing you might notice is that I start at position 0,0 when, in the data set, there's already a value in 0,0. The algorithm has to be able to handle the existing numbers.

There is dyked-out code for displaying each iteration. That was primarily for debugging and should really be put in an if ( $debug ) {} block. There's also a @no_go list created. I don't have the bugs worked out, and I've found this works acceptably fast without it, so I kept it out. So, I recreate and test the current state, decide on the next position, iterate through the possible values for that position (1 through 9) and jump to that. Recursion and iteration where each makes sense.

So, Dave, where do you know if you've solved it? In test_solution(), of course.

Adapted from my test code from the previous Sudoku problem, but instead of having to highlight all the positions where I fail, I just have to admit "I fail" and return 0. Makes for one fewer loop for each test, which is good. If I don't fail, I succeed, so I end with return 1 to announce that. And, after the possible fails and the return, I count the filled spaces. If there are ( 9 x 9 = ) 81 filled squares, then the puzzle is solved, so I display the solution and exit.

The real hero to the story of John Henry, I think, is the guy who invented and built the steel-driving machine, the man whose intellectual sweat made it so that nobody had to work themselves to an early grave. Of course, you now have to find something to do with all the people who are no longer killing themselves to death driving steel. But that seems a bit far afield and too philosophical for a coding blog.

//------------------------------------------------------------------------------// Kinda the "Main()" for this. Runs when the page is fully loaded.//------------------------------------------------------------------------------$(function() {

This code has only been tested in Firefox 3.0. If you have problems, please report them here. And nothing say "Hey, you won!" when the puzzle is solved yet. I figure that will come when I can generate new puzzles. Sorry.

The next bit, the tricky bit, would be to generate new puzzles. I don't have that yet. But if I can make 'em up, I can put 'em into the puzzle. Feel free to try it.