{"id":193,"date":"2004-05-28T03:38:34","date_gmt":"2004-05-28T01:38:34","guid":{"rendered":"http:\/\/blogs.bl0rg.net\/neingeist-neu\/2004\/05\/28\/the-knights-tour\/"},"modified":"2006-10-10T03:54:25","modified_gmt":"2006-10-10T01:54:25","slug":"the-knights-tour","status":"publish","type":"post","link":"https:\/\/blogs.bl0rg.net\/neingeist\/2004\/05\/28\/the-knights-tour\/","title":{"rendered":"The Knight&#8217;s Tour"},"content":{"rendered":"<p>One of my favorite problems when I try new programming languages is the Knight&#8217;s Tour. The goal is to move a knight on a chess board in a way that each square of the chess board is visited exactly once. The naive approach is to use simple backtracing, but a better way was found in the 19th century by H. C. Warnsdorff. This is an implementation of his algorithm. I hope the Lisp code is not too embarassing.<\/p>\n<pre>(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/mac_defun.html\">defun<\/a> start-tour (position)\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/speope_letcm_letst.html\">let<\/a> ((board (make-array '(8 8))))\r\n(move position board 1)))\r\n\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/mac_defun.html\">defun<\/a> move (position board n)\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/stagenfun_doc_umentationcp.html\">setf<\/a> (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/acc_aref.html\">aref<\/a> board (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/acc_carcm_cdr_darcm_cddddr.html\">car<\/a> position) (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/acc_carcm_cdr_darcm_cddddr.html\">cadr<\/a> position)) n)\r\n;;  (print-board board)\r\n;;  (print (evaluate-possible-moves position board))\r\n;;  (format t \"~%\")\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/mac_cond.html\">cond<\/a> ((<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_eqcm_sleq__lteqcm_gteq.html\">=<\/a> n 64) (print-board board))\r\n((<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/syscla_null.html\">null<\/a> (possible-moves position board)) 'failed-dead-end)\r\n((<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_eqcm_sleq__lteqcm_gteq.html\">&lt;<\/a> n 64) (move (best-move position board) board (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/var_plcm_plplcm_plplpl.html\">+<\/a> n 1)))))\r\n\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/mac_defun.html\">defun<\/a> best-move (position board)\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/acc_carcm_cdr_darcm_cddddr.html\">car<\/a> (evaluate-possible-moves position board)))\r\n\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/mac_defun.html\">defun<\/a> evaluate-possible-moves (position board)\r\n;;  (print position)\r\n;;  (format t \"~%\")\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_sortcm_stable-sort.html\">sort<\/a> (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_mapccm_ma_istcm_mapcon.html\">mapcar<\/a> #'(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/sym_lambda.html\">lambda<\/a> (x) (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_append.html\">append<\/a> x (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/syscla_list.html\">list<\/a> (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_length.html\">length<\/a> (possible-moves x board)))))\r\n(possible-moves position board))\r\n#'(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/sym_lambda.html\">lambda<\/a> (triple-a triple-b) (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_eqcm_sleq__lteqcm_gteq.html\">&lt;<\/a> (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/acc_carcm_cdr_darcm_cddddr.html\">caddr<\/a> triple-a) (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/acc_carcm_cdr_darcm_cddddr.html\">caddr<\/a> triple-b)))))\r\n\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/mac_defun.html\">defun<\/a> print-board (board)\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/mac_docm_dost.html\">do<\/a> ((x 0 (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/var_plcm_plplcm_plplpl.html\">+<\/a> x 1)))\r\n((<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_eqcm_sleq__lteqcm_gteq.html\">=<\/a> x 8))\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/mac_docm_dost.html\">do<\/a> ((y 0 (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/var_plcm_plplcm_plplpl.html\">+<\/a> y 1)))\r\n((<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_eqcm_sleq__lteqcm_gteq.html\">=<\/a> y 8))\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_format.html\">format<\/a> t \"~2D \" (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/acc_aref.html\">aref<\/a> board x y)))\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_format.html\">format<\/a> t \"~%\"))\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_format.html\">format<\/a> t \"~%\"))\r\n\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/mac_defun.html\">defun<\/a> on-board-p (position)\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/typspe_and.html\">and<\/a> (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_eqcm_sleq__lteqcm_gteq.html\">&gt;=<\/a> (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/acc_carcm_cdr_darcm_cddddr.html\">car<\/a> position) 0)\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_eqcm_sleq__lteqcm_gteq.html\">&lt;=<\/a> (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/acc_carcm_cdr_darcm_cddddr.html\">car<\/a> position) 7)\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_eqcm_sleq__lteqcm_gteq.html\">&gt;=<\/a> (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/acc_carcm_cdr_darcm_cddddr.html\">cadr<\/a> position) 0)\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_eqcm_sleq__lteqcm_gteq.html\">&lt;=<\/a> (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/acc_carcm_cdr_darcm_cddddr.html\">cadr<\/a> position) 7)))\r\n\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/mac_defun.html\">defun<\/a> visited-p (position board)\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_eqcm_sleq__lteqcm_gteq.html\">&gt;<\/a> (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/acc_aref.html\">aref<\/a> board (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/acc_carcm_cdr_darcm_cddddr.html\">car<\/a> position) (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/acc_carcm_cdr_darcm_cddddr.html\">cadr<\/a> position)) 0))\r\n\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/mac_defun.html\">defun<\/a> possible-moves (position board)\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_removecm__elete-if-not.html\">remove-if<\/a> #'(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/sym_lambda.html\">lambda<\/a> (x) (visited-p x board)) (moves position)))\r\n\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/mac_defun.html\">defun<\/a> moves (position)\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/speope_letcm_letst.html\">let<\/a> ((x (car position))\r\n(y (cadr position)))\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_removecm__elete-if-not.html\">remove-if-not<\/a> #'on-board-p\r\n`((,(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/var_plcm_plplcm_plplpl.html\">+<\/a> x 1) ,(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/var_plcm_plplcm_plplpl.html\">+<\/a> y 2))\r\n(,(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/var_plcm_plplcm_plplpl.html\">+<\/a> x 1) ,(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/var_-.html\">-<\/a> y 2))\r\n(,(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/var_-.html\">-<\/a> x 1) ,(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/var_plcm_plplcm_plplpl.html\">+<\/a> y 2))\r\n(,(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/var_-.html\">-<\/a> x 1) ,(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/var_-.html\">-<\/a> y 2))\r\n(,(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/var_plcm_plplcm_plplpl.html\">+<\/a> x 2) ,(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/var_plcm_plplcm_plplpl.html\">+<\/a> y 1))\r\n(,(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/var_plcm_plplcm_plplpl.html\">+<\/a> x 2) ,(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/var_-.html\">-<\/a> y 1))\r\n(,(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/var_-.html\">-<\/a> x 2) ,(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/var_plcm_plplcm_plplpl.html\">+<\/a> y 1))\r\n(,(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/var_-.html\">-<\/a> x 2) ,(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/var_-.html\">-<\/a> y 1))))))<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>One of my favorite problems when I try new programming languages is the Knight&#8217;s Tour. The goal is to move a knight on a chess board in a way that each square of the chess board is visited exactly once. The naive approach is to use simple backtracing, but a better way was found in [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[14],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.bl0rg.net\/neingeist\/wp-json\/wp\/v2\/posts\/193"}],"collection":[{"href":"https:\/\/blogs.bl0rg.net\/neingeist\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.bl0rg.net\/neingeist\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.bl0rg.net\/neingeist\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.bl0rg.net\/neingeist\/wp-json\/wp\/v2\/comments?post=193"}],"version-history":[{"count":0,"href":"https:\/\/blogs.bl0rg.net\/neingeist\/wp-json\/wp\/v2\/posts\/193\/revisions"}],"wp:attachment":[{"href":"https:\/\/blogs.bl0rg.net\/neingeist\/wp-json\/wp\/v2\/media?parent=193"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.bl0rg.net\/neingeist\/wp-json\/wp\/v2\/categories?post=193"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.bl0rg.net\/neingeist\/wp-json\/wp\/v2\/tags?post=193"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}