: n>> board>> length ; inline : all-pairs ( seq -- seqs ) [ ] [ length ] [ flip ] tri [ zip ] with map concat ; : knight-moves ( -- pairs ) -2 2 [a,b] all-pairs [ { 1 2 } [ norm ] bi@ = ] filter ; : show ( matrix -- ) [ [ "%5d" printf ] each nl ] each ; : nth/out ( n seq out -- elt ) [ [ bounds-check? ] [ [ nth ] 2curry ] 2bi ] [ [ ] curry ] bi* if ; : deep ( n-seq obj -- last-n seq ) over length 1 > [ [ unclip-slice ] [ nth ] bi* deep ] [ [ first ] [ ] bi* ] if ; : valid ( ktour -- ? ) [ pair>> first2 swap ] [ board>> ] bi { } nth/out f nth/out 0 = ; : valid-moves ( ktour -- seq ) [ knight-moves ] [ [ [ v+ ] >pair> ] curry ] bi* map [ valid ] filter ; : valid-moves-count ( ktour -- k ) valid-moves length ; : trace ( ktour -- ) [ k>> ] [ pair>> ] [ board>> ] tri deep set-nth ; : sorted-moves ( ktour -- moves ) [ valid-moves [ [ valid-moves-count ] compare ] sort ] keep ; : untrace ( ktour -- ) [ drop 0 ] [ pair>> ] [ board>> ] tri deep set-nth ; : (solve) ( ktour -- ktour/f ) dup trace [ ] [ k>> ] [ n>> sq ] tri < [ f swap sorted-moves [ [ [ 1+ ] >k> (solve) ] [ untrace ] bi* nip dup ] curry find 2drop ] [ dup board>> show ] if ; : solve ( n -- ) swap dup zero-matrix >>board 1 >>k { 0 0 } >>pair (solve) drop ;