Thanks Konrad
A very elegant solution.
40 years of laziness, and I finally realize what a great feature the
lazy evaluation is ;)

Tzach


On Jan 9, 3:30 pm, Konrad Hinsen <konrad.hin...@laposte.net> wrote:
> On Jan 9, 2009, at 13:18, Tzach wrote:
>
>
>
> > The main functionsudokuis recursive:
> > 1. Getting asudokuboard as an input
> > 2. Choosing the next empty (zero) cell to test, loop on all valid
> > values, and callsudokuwith the new board
> > 3. When a solution (board with no zero values) is found: throw.
>
> > (defnsudoku[board]
> >   "solve asudokuproblem"
> >   (when (complete? board)
> >     (do
> >      (println "complete")
> >      (print-board board)
> >       (throw nil)))
> >   (let [cell (next-cell board)
> >        pos (first cell)
> >        valid-values (second cell)]
> >        (when cell
> >     (doseq [v valid-values]
> >            (sudoku(assoc-in board pos v)))
> >     )))
>
> > Although it does work, we can all agree its pretty ugly, so I would
> > appreciate your help on the following questions:
> > 1. How to can I return a solution via the recursive stack with out
> > throwing an exception? I understand there is no "return-from"
> > facility.
>
> The return value of a function is the last expression that was  
> evaluated. Yoursudokufunction could have a structure like this:
>
> (defnsudoku[board]
>    "solve asudokuproblem"
>    (if (complete? board)
>      board
>      (let [...]
>        ..))
>
> The problem is then in the let branch, as it can terminate without  
> returning a valid board.
>
> > 2. Can this function be implemented as tail recursive (using loop?
> > recur?)
>
> As it is, no, because you have multiple recursive calls. However, I  
> wonder what those are good for. If I understand your algorithm  
> correctly, it find all valid values for the next cell to be filled,  
> and then tries for each of them to complete the puzzle, using a  
> recursive call.
>
> I would rewrite the solver as a function that returns a lazy sequence  
> of valid solutions:
>
> (defn all-solutions [board]
>    (if (complete? board)
>      (list board)
>      (let [[pos valid-values] (next-cell board)]
>        (apply concat (for [v valid-values]
>                       (all-solutions (assoc-in board pos v)))))))
>
> Note that you don't have to do anything to make the sequences lazy;  
> apply and for take care of that automatically.
> The solver then just takes the first item of that sequence:
>
> (defnsudoku[board]
>    "solve asudokuproblem"
>    (first (all-solutions board)))
>
> Since the sequence is lazy, the remaining solutions (if any) are  
> never computed, so this version does not do more work than your  
> original one.
>
> Konrad.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to