% \iffalse meta-comment % % sudokubundle.dtx % % Author: Peter Wilson (Herries Press) herries dot press at earthlink dot net % Copyright 2006 Peter R. Wilson % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either % version 1.3 of this license or (at your option) any % later version. % The latest version of the license is in % http://www.latex-project.org/lppl.txt % and version 1.3 or later is part of all distributions of % LaTeX version 2003/06/01 or later. % % This work has the LPPL maintenance status "author-maintained". % % This work consists of the files listed in the README file. % %<*driver> \documentclass[twoside]{ltxdoc} \usepackage{printsudoku} \usepackage{url} \usepackage[draft=false, plainpages=false, pdfpagelabels, bookmarksnumbered, hyperindex=false ]{hyperref} \makeatletter \@mparswitchfalse \makeatother \EnableCrossrefs \CodelineIndex %%% \RecordChanges %%%%%%%%%%%%% uncomment the next line to show all the code details %%\OnlyDescription %%% Don't use the default Short Verb. \AtBeginDocument{\DeleteShortVerb{\|}} %%% page headings to aid navigation, but I don't like Uppercased titles. \renewcommand{\MakeUppercase}[1]{#1} \pagestyle{headings} \setcounter{StandardModuleDepth}{1} \begin{document} \DocInput{sudokubundle.dtx} \end{document} % % % \fi % % \CheckSum{5494} % % \DoNotIndex{\',\.,\@M,\@@input,\@addtoreset,\@arabic,\@badmath} % \DoNotIndex{\@centercr,\@cite} % \DoNotIndex{\@dotsep,\@empty,\@gobble,\@gobbletwo,\@ignoretrue} % \DoNotIndex{\@input,\@ixpt,\@m} % \DoNotIndex{\@minus,\@ne,\@nil,\@nomath,\@plus,\@set@topoint} % \DoNotIndex{\@tempboxa,\@tempcnta,\@tempdima,\@tempdimb} % \DoNotIndex{\@tempswafalse,\@tempswatrue,\@viipt,\@viiipt,\@vipt} % \DoNotIndex{\@vpt,\@warning,\@xiipt,\@xipt,\@xivpt,\@xpt,\@xviipt} % \DoNotIndex{\@xxpt,\@xxvpt,\\,\ ,\addpenalty,\addtolength,\addvspace} % \DoNotIndex{\advance,\Alph,\alph} % \DoNotIndex{\arabic,\ast,\begin,\begingroup,\bfseries,\bgroup,\box} % \DoNotIndex{\bullet} % \DoNotIndex{\cdot,\cite,\CodelineIndex,\cr,\day,\DeclareOption} % \DoNotIndex{\def,\DisableCrossrefs,\divide,\DocInput,\documentclass} % \DoNotIndex{\DoNotIndex,\egroup,\ifdim,\else,\fi,\em,\endtrivlist} % \DoNotIndex{\EnableCrossrefs,\end,\endgroup} % \DoNotIndex{\endlist,\everycr,\everypar,\ExecuteOptions,\expandafter} % \DoNotIndex{\fbox} % \DoNotIndex{\filedate,\filename,\fileversion,\fontsize,\framebox,\gdef} % \DoNotIndex{\global,\halign,\hbox,\hfil,\hfill,\hrule} % \DoNotIndex{\hsize,\hskip,\hspace,\hss,\if@tempswa,\ifcase,\or,\fi,\fi} % \DoNotIndex{\ifhmode,\ifvmode,\ifnum,\iftrue,\ifx,\fi,\fi,\fi,\fi,\fi} % \DoNotIndex{\input} % \DoNotIndex{\jobname,\kern,\leavevmode,\let} % \DoNotIndex{\list,\llap,\long,\m@ne,\m@th} % \DoNotIndex{\month,\newcommand,\newcounter,\newenvironment} % \DoNotIndex{\NeedsTeXFormat,\newdimen} % \DoNotIndex{\newlength,\newpage,\nobreak,\noindent,\null,\number} % \DoNotIndex{\numberline,\OldMakeindex,\OnlyDescription,\p@} % \DoNotIndex{\par,\paragraph,\paragraphmark,\parfillskip} % \DoNotIndex{\penalty,\PrintChanges,\PrintIndex,\ProcessOptions} % \DoNotIndex{\protect,\ProvidesClass} % \DoNotIndex{\refstepcounter,\relax,\renewcommand,\reset@font} % \DoNotIndex{\rightskip,\rlap,\rmfamily,\roman} % \DoNotIndex{\roman,\secdef,\selectfont,\setbox,\setcounter,\setlength} % \DoNotIndex{\settowidth,\sfcode,\skip,\sloppy,\slshape,\space} % \DoNotIndex{\symbol,\the,\trivlist,\typeout,\tw@,\undefined,\uppercase} % \DoNotIndex{\usecounter,\usefont,\usepackage,\vfil,\vfill,\viiipt} % \DoNotIndex{\viipt,\vipt,\vskip,\vspace} % \DoNotIndex{\wd,\xiipt,\year,\z@} % \DoNotIndex{\@namedef,\@nameuse,\csname,\endcsname} % % \def\dtxfile{sudokubundle.dtx} % \def\fileversion{1.0a} \def\filedate{2006/02/19} % % \newcommand*{\fref}[1]{Figure~\ref{#1}} % \newcommand*{\tref}[1]{Table~\ref{#1}} % \newcommand*{\Lopt}[1]{\textsf {#1}} ^^A typeset an option % \newcommand*{\file}[1]{\texttt {#1}} ^^A typeset a file % \newcommand*{\Lcount}[1]{\textsl {\small#1}} ^^A typeset a counter % \newcommand*{\pstyle}[1]{\textsl {#1}} ^^A typeset a pagestyle % \newcommand*{\Lenv}[1]{\texttt {#1}} ^^A typeset an environment % \newcommand*{\Lpack}[1]{\textsf {#1}} ^^A typeset a package % \newcommand*{\ctt}{\textsc{ctt}} % \newcommand{\Lclass}[1]{\textsf{#1}} % \newcommand{\PWcomment}[1]{} % \newenvironment{PW}{\itshape}{} % \renewenvironment{PW}{\sffamily}{} % \newcommand{\texbook}{\textit{TeXbook}} % \newcommand{\thetexbook}{\textit{The TeXbook}} % \newcommand{\egstart}{} % \newcommand{\egmid}{} % \newcommand{\egend}{} % \renewcommand{\egstart}{ % \par % \begingroup % \centering % \begin{minipage}{0.45\textwidth}} % \renewcommand{\egmid}{ % \end{minipage}\hfill\begin{minipage}{0.45\textwidth}} % \renewcommand{\egend}{ % \end{minipage}\par\endgroup} % % \title{The sudoku bundle for displaying, solving and generating Sudoku % puzzles\thanks{This file (\dtxfile) % has version number \fileversion, last revised on \filedate.}} % \author{Peter % Wilson\thanks{\texttt{herries dot press at earthlink dot net}}\\ % The Herries Press} % \date{\filedate} % \maketitle % % \begin{abstract} % The \Lpack{sudoku bundle} provides a coordinated set of packages for % displaying, solving, and generating Sudoku puzzles. A set of over 50 puzzles % is also supplied. % \end{abstract} % % \tableofcontents % \listoffigures % % \section{Introduction} % % In December 2005 the \emph{PracTeX Journal}~\cite{PRACTEX} set a competition % about Sudoku puzzles. % Depending on their experience with \TeX\ contestants were asked to % (a) typeset a particular puzzle, (b) typeset % a puzzle described in a `sudoku' file, (c) create a solver for % sudoku puzzles. I entered the competition with a printer and solver. % Following from this it was no great effort to develop a matching % Soduko puzzle generator. % % The packages described here have been developed completely independently % from Paul Abraham's \Lpack{sudoku} package~\cite{SUDOKU}, which I did % not see until after I had finished work on them. % % A Sudoku puzzle consists a 9 by 9 grid of cells with % some of the cells containing a number between 1 and 9, such as is % shown in \fref{fig:puz1}. The problem % is to place a number between 1 and 9 in each cell such that no number appears % more than once in each row and in each column and in each minor 3 by 3 grid. % The solution to the example puzzle is shown in \fref{fig:ans1}. The % puzzle and answer have been typeset using the \Lpack{printsudoku} package. % % \changes{v1.0a}{2006/02/19}{Deleted clue from example puzzle, % courtesy William Hammond} % \renewcommand*{\puzzlefile}{examout.sud} % \writepuzzle% % {..483..72}% % {.12....8.}% % {..52.13..}% % {....62.91}% % {7..5.9..3}% % {94.78....}% % {..39.74..}% % {.5....61.}% % {.8..469..}% % [Example puzzle \sudpuzznewline % (anything can come after the nine puzzle lines)] % \begin{figure} % \centering % \sudoku{examout.sud} % \caption{Example Sudoku puzzle}\label{fig:puz1} % \end{figure} % % Among many other sources the \emph{Sudoku Solver by logic} % website~\cite{SSBL} % provides much information on Sudoku puzzles and their solutions, % as does the \emph{Sudoku Online}~\cite{SOL} website. % % A Sudoku puzzle may be represented as a simple text file consisting % of nine rows of numbers and dots, nine numbers and dots in each row. % The numbers are the clues to the puzzle and the dots represent blanks % in the grid. A sudoko file for the example puzzle is given in % \fref{fig:file1}. % % % \begin{figure} % \centering % \begin{verbatim} % ..483..72 % .12....8. % ..52.13.. % ....62.91 % 7..5.9..3 % 94.78.... % ..39.74.. % .5....61. % .8..469.. % % Example puzzle % (anything can come after the nine puzzle lines) % \end{verbatim} % \caption{A sudoku file for the example puzzle}\label{fig:file1} % \end{figure} % % % \renewcommand*{\puzzlefile}{examout.ans} % \writepuzzle% % {694835172}% % {312674589}% % {875291364}% % {538462791}% % {726519843}% % {941783256}% % {163957428}% % {459328617}% % {287146935}% % [Solution to example puzzle] % % \begin{figure} % \centering % \cluefont{\normalsize}\cellsize{1.5\baselineskip} % \sudoku{examout.ans} % \caption{Solution to example puzzle}\label{fig:ans1} % \end{figure} % % % This manual is typeset according to the conventions of the \LaTeX{} % \textsc{docstrip} utility which enables the automatic extraction % of the \LaTeX{} macro source files~\cite{COMPANION}. % % \section{Usage} % % The bundle provides three packages; one for typesetting a puzzle, one % for solving a puzzle, and the third for generating a puzzle. Each package % requires the previous one(s). % % A file is also provided that contains over 50 puzzles and their answers --- % all you have to do is run LaTeX on it, print it, and get to work on the puzzles % (or give them to someone else). % % \subsection{Typesetting} % % The \Lpack{printsudoku} package enables you to typeset a Sudoku % puzzle given in a sudoku file. % % \DescribeMacro{\sudoku} % The command \cs{sudoku}\marg{file} typesets the sudoku puzzle from the % sudoku file named \meta{file}. % For example: \\ % \verb? \begin{center} \sudoku{puzzle1.sud} \end{center}? \\ % The command reads only the first nine lines in the file, which must % contain the puzzle's description. Anything after these lines is ignored, % so comments, such as a title or other explanatory text, % can be put at the end of the file. % % \DescribeMacro{\cluefont} % Following \cs{cluefont}\marg{font} the clues are typeset using the % \meta{font} font specification. The default is: \\ % \verb?\cluefont{\Huge}? % % \DescribeMacro{\cellsize} % The puzzle is typeset as a \LaTeX\ \Lenv{picture} and % \cs{cellsize}\marg{length} specifies the size of the cells in the grid. % To match the \cs{cluefont} the default is: \\ % \verb?\cellsize{2.5\baselineskip}? % % Figure~\ref{fig:puz1} was set using the default \cs{cluefont} and % \cs{cellsize}. On the other hand, \fref{fig:ans1} was set via: % \begin{verbatim} % \begin{figure} % \centering % \cluefont{\normalsize}\cellsize{1.5\baselineskip} % \sudoku{examout.ans} % \caption{Solution to example puzzle}\label{fig:ans1} % \end{figure} % \end{verbatim} % % \DescribeMacro{\writepuzzle} % \DescribeMacro{\puzzlefile} % \DescribeMacro{\sudpuzznewline} % The command \cs{writepuzzle}, which takes nine required arguments each of % which is a line in the puzzle, writes the puzzle to the file \cs{puzzlefile}, where the default % is: \\ % \verb?\newcommand*{\puzzlefile}{puzz.sud}? % % The nine required arguments to \cs{writepuzzle} are the lines describing % a puzzle as they would appear in a sudoku file. There is an optional tenth % argument after the nine required arguments which you may use to write % a comment at the end of the file. % For instance, earlier I used the following % to write out the example puzzle to the file \file{examout.sud}: % \begin{verbatim} % \renewcommand*{\puzzlefile}{examout.sud} % \writepuzzle% % {..483..72}% % {.12....8.}% % {..52.13..}% % {....62.91}% % {7..5.9..3}% % {94.78....}% % {..39.74..}% % {.5....61.}% % {.8..469..}% % [Example puzzle \sudpuzznewline % (anything can come after the nine puzzle lines)] % \end{verbatim} % And similarly for writing out the file with the solution. % % If you want a multiline comment, use the \cs{sudpuzznewline} macro to % start a new line (\verb?\\? or \cs{newline} will not work). % % % \subsection{Solving} % % The \Lpack{solvesudoku} package lets you use \LaTeX\ to try and solve % a Sudoku puzzle. % % \DescribeMacro{\sudokusolve} % The macro \cs{sudokusolve}\marg{file} attempts to find a solution to % the puzzle in the sudoku file \meta{file}. It uses the \Lpack{printsudoku} % package for typesetting the puzzle. % % It first prints the puzzle as given and then attempts to solve it. % The solution, or as much as was obtainable, is typeset in a smaller % font below the original. Here is the definition: % \begin{verbatim} % \newcommand*{\sudokusolve}[1]{% % \begin{center} % \sudoku{#1} % \end{center} % \getproblem{#1} % \reduceallcells \keepreducing % \writegame % \noindent\begin{minipage}{\linewidth} % THE ANSWER % \begin{center} % \cluefont{\normalsize} % \cellsize{1.5\baselineskip} % \sudoku{sud.out} % \end{center} % \end{minipage}} % \end{verbatim} % You may use the macros in \cs{sudokusolve} separately if you wish. % % \DescribeMacro{\getproblem} % \cs{getproblem}\marg{file} reads in the puzzle from the sudoku file % \meta{file} and initialises the solution. % % \DescribeMacro{\reduceallcells} % \cs{reduceallcells} takes a simple-minded approach to develop a solution % to the puzzle. % % \DescribeMacro{\keepreducing} % If \cs{reduceallcells} does not completely solve the puzzle then % \cs{keepreducing} applies increasingly sophisticated solution methods, % which may or may not lead to a complete solution. % % \DescribeMacro{\writegame} % \DescribeMacro{\sudsolnfile} % \cs{writegame} writes out a (partially) solved puzzle to the sudoku file % \cs{sudsolnfile} (default \file{sud.out}). Later this is read in again % by \cs{sudoku} to % typeset the solution. % % Here's a small example of how you might use the package. This will keep % asking on the terminal for sudoku files to solve. % \begin{verbatim} %%%% solvethem.tex Solve Sudoku files %%%% Peter Wilson % \documentclass{article} % \usepackage{solvesudoku} % \newcommand*{\solvefile}[1]{\begingroup % \sudokusolve{#1}% % \par % \vspace{\baselineskip} % Number of clues = \the\numcluesctr\ and difficulty = \the\difficultyctr. % \endgroup} % \def\yesans{y} % \begin{document} % \loop % \typein[\getans]{New file? y/n} % \ifx\yesans\getans % \typein[\sudfile]{Enter the file name} % \clearpage % \begin{center} \Huge \sudfile \end{center} % \solvefile{\sudfile} % \repeat % \end{document} % \end{verbatim} % % \DescribeMacro{\numcluesctr} % \DescribeMacro{\difficultyctr} % These are two \TeX\ \cs{count}s. \cs{numcluesctr} is the number of clues % in the initial puzzle, and \cs{difficultyctr} is a numerical indication % of how hard the solver had to work, but it doesn't really mean much % as the solver has had successes with some puzzles with a high % \cs{difficultyctr} rating % but failed to solve some with medium values of \cs{difficultyctr}. % % \subsection{Generation} % % With the \Lpack{createsudoku} package you can get \LaTeX\ to automatically % generate a Sudoku puzzle. This package does require the use of Donald % Arseneau's \Lpack{random} code~\cite{RANDOM} for generating random numbers. % % \DescribeMacro{\generategrid} % \cs{generategrid}\oarg{file} will generate a Sudoku puzzle starting with % the solution given in the sudoku file \meta{file}. If the file is % not given then it will start from a solution provided by the package. % % The puzzle is generated by taking the solution and randomly exchanging % rows and columns for some (random) number of times. Then clues are % eliminated until % it is no longer soluble by \cs{sudokusolve}. The last clue that was deleted % is put back and then the resulting grid is presented as the puzzle. % % An initial set of clues are deleted before the solver is called. It can % happen that the puzzle even then is too difficult for the solver, so % you have to check the solution as presented is a complete one for the puzzle. % % \DescribeMacro{\genfile} % \DescribeMacro{\prevfile} % \DescribeMacro{\currfile} % The generated puzzle, and its solution, is typeset and the puzzle is % also output in the sudoku file \cs{genfile}. The default is: \\ % \verb?\newcommand*{\genfile}{gensud.sud}? \\ % Two temporary sudoku files, \cs{prevfile} and \cs{currfile}, are % used during the generation. The defaults are: \\ % \verb?\newcommand*{\prevfile}{genprev.sdx}? \\ % \verb?\newcommand*{\currfile}{gencurr.sdx}? \\ % A pre-existing version of any of these three files will be overwritten. % % \DescribeMacro{\setsudrandom} % The random number generater is initialised via a seed based on % a number (the internal value of \cs{randomi}) % in the range $-1 \leq$ \cs{randomi} $\leq 2147483646$. % If its value is -1 (set via \verb?\setsudrandom{-1}?) then the actual % seed will be calculated based on the time and date. For any given % seed the sequence of the generated random numbers is the same. % The value of the % seed is output via a \cs{typeout} if you need to repeat a generation. % % You should not attempt to set \cs{randomi} directly but use % \cs{setsudrandom}\marg{num}. % % The default setting is: \\ % \verb?\setsudrandom{-1}? \\ % and as that means that the seed depends on the time and date, % a new puzzle will be % generated each time (unless the time interval is very short). The % maximum number of puzzles that can be generated from one initial solution % is 2,147,483,646 which is the range of the random number generator. % % \DescribeMacro{\initialelimination} % The macro \cs{initialelimination} eliminates an initial set of solutions % from the randomized starting grid. Various predefined sets are provided % and you can either provide your own definition for \cs{initialelimination} % or \cs{let} it to one of the predefined sets, e.g., \\ % \verb?\let\initialelimination\elimcrossandnines? % % \DescribeMacro{\elimseventeen} % \DescribeMacro{\elimnum} % \DescribeMacro{\elimcross} % \DescribeMacro{\elimex} % \DescribeMacro{\elimcrossandnines} % \DescribeMacro{\elimcrossandex} % \DescribeMacro{\elimcrossandexandnines} % \cs{elimseventeen} randomly eliminates 17 solutions from the grid --- % apparently the solution to a puzzle can be ambiguous if two numbers % are completely absent. % \cs{elimnum}\marg{num} eliminates every solution \meta{num} % (e.g. \verb?\elimnum{7}? will eliminate every 7 from the grid). % \cs{elimcross} eliminates all numbers from column 5 and from row 5, while % \cs{elimex} eliminates all numbers on the diagonals. % % \cs{elimcrossandnines} % is a combination of \cs{elimcross} and \verb?\elimnum{9}?. Similarly the % macros \cs{elimcrossandex} and \cs{elimcrossandexandnines} are combinations % of some of the earlier macros. % % % % \StopEventually{ % \bibliographystyle{alpha} % \begingroup % \raggedright % \begin{thebibliography}{GMSN94A} % % \bibitem[Abr05]{SUDOKU} % Paul Abraham. % \newblock \emph{The sudoku package}. % \newblock June 2005. % \newblock (Available from CTAN in % \texttt{macros/latex/contrib/sudoku}) % % \bibitem[Ars95]{RANDOM} % Donald Arseneau. % \newblock \emph{Generating random numbers in \TeX}. % \newblock 1995. % \newblock (Available from CTAN in % \texttt{macros/generic/random.tex}) % % % \bibitem[MG04]{COMPANION} % Frank Mittelbach and Michel Goossens. % \newblock \emph{The LaTeX Companion}. % \newblock Second edition. % \newblock Addison-Wesley Publishing Company, 2004. % \newblock \textsc{isbn} 0-201-36299-6. % % \bibitem[PJ05]{PRACTEX} % \TeX\ Users Group. % \newblock Distractions: Sudoku. % \newblock \emph{The PracTeX Journal}. % \newblock 2005-4. % \newblock \url{http://tug.org/pracjourn2005-4/distract} % % \bibitem[SOL]{SOL} % \emph{Sudoku Online: Home of the Sudokulist}. % \newblock \url{http://www.sudoku.org.uk} % % \bibitem[SSBL]{SSBL} % \emph{Sudoku Solver ... by logic}. % \newblock \url{http://www.sudokusolver.co.uk} % % % ^^A \bibitem[Wil04]{MEMOIR} % ^^A Peter Wilson. % ^^A \newblock \emph{The LaTeX \Lpack{memoir} class for configurable % ^^A typesetting: Source code}. % ^^A \newblock January 2004. % ^^A \newblock (Available from CTAN in % ^^A \texttt{macros/latex/contrib/memoir}) % % % \end{thebibliography} % \endgroup % % \PrintIndex % } % % \section{Code} % % \subsection{The \Lpack{printsudoku} package} % % \begin{macrocode} %<*print> \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{printsudoku}[2006/02/16 v1.0 typeset sudoku puzzles] % \end{macrocode} % % \begin{macro}{\s@dread} % \begin{macro}{\s@dwrite} % We are going to be reading and writing some files. % \begin{macrocode} \newread\s@dread \newwrite\s@dwrite % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\reads@dgame} % \cs{reads@dgame}\marg{file} opens a sudoku file \meta{file} for reading. % \begin{macrocode} %%%% open game file \newcommand*{\reads@dgame}[1]{% \closein\s@dread \openin\s@dread=#1} % \end{macrocode} % \end{macro} % % \begin{macro}{\halfs@dcell} % \begin{macro}{\cellsize} % \begin{macro}{\cluefont} % We're going to use a \Lenv{picture} environment for drawing the grid, % and to keep numbers neatly we'll use the length \cs{halfs@dcell} as % the \cs{unitlength}. \cs{cellsize}\marg{length} is the use command for % setting the size of a cell. The clues are typeset using the \cs{cluefont} % font. % \begin{macrocode} %%% set size of a game cell \newlength\halfs@dcell \newcommand*{\cellsize}[1]{% \halfs@dcell=#1\relax \halfs@dcell=0.5\halfs@dcell} \cellsize{2.5\baselineskip} %% set font for the numbers \newcommand*{\cluefont}[1]{\def\s@dfont{#1}} \cluefont{\Huge} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\s@dncol} % \begin{macro}{\s@dnrow} % \begin{macro}{\s@dcolpos} % \begin{macro}{\s@drowpos} % Counts for looping and cell positions % \begin{macrocode} %% counts for looping and cell positions \newcount\s@dncol \newcount\s@dnrow \newcount\s@dcolpos \newcount\s@drowpos % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\adds@dclues} % \cs{adds@dclues} inserts the clues into the game grid. It reads the % sudoku file line by line insert the clues into the grid for one line % before going on to the next line. % \begin{macrocode} %% insert the clues into the game array \newcommand*{\adds@dclues}{% \firsts@dcluetrue \s@dnrow\@ne \loop \ifnum\s@dnrow<10\relax \read\s@dread to \s@dline \firsts@dcluetrue \s@drowpos=\s@dnrow \multiply\s@drowpos\tw@ \advance\s@drowpos\m@ne \s@dncol\@ne \dos@dcols \advance\s@dnrow\@ne \repeat \closein\s@dread} % \end{macrocode} % \end{macro} % % \begin{macro}{\dos@dcols} % \cs{dos@dcols} inserts one row of clues into the game grid. % \begin{macrocode} %% insert a row of clues \newcommand*{\dos@dcols}{% \bgroup \loop \ifnum\s@dncol<10\relax \s@dcolpos=\s@dncol \multiply\s@dcolpos\tw@ \advance\s@dcolpos\m@ne \put(\s@dcolpos,-\s@drowpos){\makebox(0,0){\s@dfont\gets@dclue}}% \advance\s@dncol\@ne \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\gettwo} % \begin{macro}{\nowt} % \begin{macro}{\istchar} % \begin{macro}{\restchars} % \begin{macro}{\splitoff} % \cs{splitoff}\marg{string} gets the next character in a string. The next % character is made available as \cs{istchar} and the remainder of the % string as \cs{restchars}. This is explained in a forthcoming % \emph{Glisterings} column in \emph{TUGboat}. % \begin{macrocode} %% get the next character in a string \def\gettwo#1#2\nowt{% \gdef\istchar{#1}\gdef\restchars{#2}} \def\splitoff#1{\gettwo#1\nowt} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\s@dfstop} % We use this for checking if a character extracted from a string is a `.'. % \begin{macrocode} %% a full stop (period) \gdef\s@dfstop{.} % \end{macrocode} % \end{macro} % % \begin{macro}{\iffirsts@dclue} % \begin{macro}{\firsts@dcluetrue} % \begin{macro}{\firsts@dcluefalse} % \begin{macro}{\gets@dclue} % \cs{gets@dclue} gets the next clue (character) from a line of clues. % We do slightly different things if we are dealing with the first clue % or the others. % \begin{macrocode} %% get the next clue in the line \newif\iffirsts@dclue \firsts@dcluetrue \newcommand*{\gets@dclue}{% \iffirsts@dclue \expandafter\splitoff\expandafter{\s@dline}% \global\firsts@dcluefalse \else \expandafter\splitoff\expandafter{\restchars}% \fi \ifx\s@dfstop\istchar \else \istchar \fi} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\s@dgame} % \cs{s@dgame} typesets the grid, then adds in the clues. % \begin{macrocode} %% typeset the grid, then add the clues \newcommand*{\s@dgame}{% \setlength\unitlength\halfs@dcell \begin{picture}(18,18)(0,-18) \thinlines \multiput(0,0)(2,0){10}{\line(0,-1){18}} \multiput(0,0)(0,-2){10}{\line(1,0){18}} \thicklines \linethickness{1pt} \multiput(0,0)(6,0){4}{\line(0,-1){18}} \multiput(0,0)(0,-6){4}{\line(1,0){18}} \adds@dclues \end{picture}} % \end{macrocode} % \end{macro} % % \begin{macro}{\sudoku} % \cs{sudoku}\marg{file} reads a game from \meta{file} and then typesets it. % \begin{macrocode} %% the whole shebang, where #1 is the name of the game file \newcommand*{\sudoku}[1]{% \reads@dgame{#1}% \s@dgame} % \end{macrocode} % \end{macro} % % \begin{macro}{\puzzlefile} % \begin{macro}{\writepuzzle} % \begin{macro}{\writes@dpuzzend} % \begin{macro}{\sudpuzznewline} % \cs{writepuzzle} takes nine arguments --- the nine lines specifying a puzzle % --- and writes them to the \cs{puzzlefile} file. % % \cs{writes@dpuzzend}\oarg{comment} writes \meta{comment} at the end of the % \cs{puzzlefile} file. % % \cs{sudpuzznewline} provides a \cs{newline} macro for use in a comment being % written to a puzzle file. % \begin{macrocode} \newcommand*{\puzzlefile}{puzz.sud} \newcommand*{\writepuzzle}[9]{% \immediate\closeout\s@dwrite \immediate\openout\s@dwrite=\puzzlefile \immediate\write\s@dwrite{#1}% \immediate\write\s@dwrite{#2}% \immediate\write\s@dwrite{#3}% \immediate\write\s@dwrite{#4}% \immediate\write\s@dwrite{#5}% \immediate\write\s@dwrite{#6}% \immediate\write\s@dwrite{#7}% \immediate\write\s@dwrite{#8}% \immediate\write\s@dwrite{#9}% \writes@dpuzzend} \newcommand*{\writes@dpuzzend}[1][\@empty]{ \ifx\@empty #1\else \immediate\write\s@dwrite{ }% \immediate\write\s@dwrite{#1}% \fi \immediate\closeout\s@dwrite} \newcommand*{\sudpuzznewline}{^^J} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % The end of the package. % \begin{macrocode} % % \end{macrocode} % % \subsection{The \Lpack{solvesudoku} package} % % The package requires the \Lpack{printsudoku} package to do some puzzle % typesetting. % % \begin{macrocode} %<*solve> \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{solvesudoku}[2006/02/16 v1.0 solve sudoku puzzles] \RequirePackage{printsudoku} % \end{macrocode} % % \subsubsection{Setup} % % \begin{macro}{\commentary} % It can be useful to control the amount of output to the log file. % \begin{macrocode} \newcommand{\commentary}[1]{\typeout{#1}} % \end{macrocode} % \end{macro} % % The following counts are defined in the \Lpack{printsudoku} package: \\ % \verb?\s@dncol, \s@dnrow, \s@dcolpos, \s@drowpos? % % \begin{macro}{\s@lcnta} % \begin{macro}{\solcnt} % \begin{macro}{\tenscnt} % \begin{macro}{\tempcntz} % \begin{macro}{\tempcnty} % \begin{macro}{\tmpsetctr} % \begin{macro}{\tmpsetansctr} % \begin{macro}{\boxctr} % \begin{macro}{\sumctr} % \begin{macro}{\toprangectr} % A bunch of \cs{count}s. They could probably be reduced in number % but they help me to keep the code less mysterious. % \begin{macrocode} %%% too many counts, maybe they should be reduced \newcount\s@lcnta % a cell number \newcount\solcnt % number of solved cells \newcount\settonumcnt \newcount\tenscnt \newcount\tempcntz \newcount\tempcnty \newcount\tmpsetctr \newcount\tmpsetansctr \newcount\boxctr \newcount\sumctr \newcount\toprangectr % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\lonecellctr} % \begin{macro}{\reducedctr} % \begin{macro}{\numlistctr} % \begin{macro}{\difficultyctr} % \begin{macro}{\s@dtempcnta} % \begin{macro}{\s@dtempcntb} % \begin{macro}{\s@dtemploopcnta} % \begin{macro}{\maxrangectr} % \begin{macro}{\asetctr} % \begin{macro}{\secondctr} % \begin{macrocode} \newcount\lonecellctr \newcount\reducedctr \newcount\numlistctr \newcount\difficultyctr \newcount\s@dtempcnta \newcount\s@dtempcntb \newcount\s@dtemploopcnta \newcount\maxrangectr \newcount\asetctr \newcount\secondctr % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\digitictr} % \begin{macro}{\digitiictr} % \begin{macro}{\numdigitsctr} % \begin{macro}{\numcluesctr} % \begin{macrocode} \newcount\digitictr \newcount\digitiictr \newcount\numdigitsctr \newcount\numcluesctr % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\iffirsts@dclue} % \begin{macro}{\iffirstchar} % \begin{macro}{\ifnotgotthechar} % \begin{macro}{\ifsetchanged} % \begin{macro}{\ifchanged} % \begin{macro}{\ifanychanged} % \begin{macro}{\iflonerchanged} % \begin{macro}{\ifstilldigits} % \begin{macro}{\ifkeepon} % \begin{macro}{\ifpairchanged} % \begin{macrocode} %%% \iffirsts@dclue% defined in printsudoku package \newif\iffirstchar \newif\ifnotgotthechar \newif\ifsetchanged \newif\ifchanged \newif\ifanychange \newif\iflonerchanged \newif\ifstilldigits \newif\ifkeepon \newif\ifpairchanged % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\newknt} % \begin{macro}{\useknt} % \begin{macro}{\createsudsets} % \cs{newknt}\marg{name} creates a new count \cs{name}, which can include % analphabetic characters. \cs{useknt}\marg{name} calls the \cs{name} count. % These are like the \LaTeX\ kernel \cs{@namedef} and \cs{@nameuse}. % In particular we will use 81 `numbered' counts, one for each cell % in the sudoku grid, using \cs{createsudsets} to generate them. % \begin{macrocode} %% create and use a numbered count %% we'll use 81 of these, one for each cell in the grid \newcommand*{\newknt}[1]{\expandafter\newcount\csname #1\endcsname} \newcommand*{\useknt}[1]{\csname #1\endcsname} %% create potential answer sets \newcommand*{\createsudsets}{% \global\s@lcnta\@ne \global\solcnt\z@ \loop \ifnum\s@lcnta<82\relax \newknt{s@lans\the\s@lcnta}% \advance\s@lcnta\@ne \repeat} \createsudsets % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \subsubsection{Binary solution sets} % % The major concern was deciding on the datastructure for the problem % (the value of \verb?\useknt{\s@lans\the\s@lcnta}}? for the \cs{s@lcnta} cell). % In the end I used a 9 digit `binary solution set' for the potential % solutions for % each cell. ($[111111111] \leftrightarrow 123456789$ and % $[101010101] \leftrightarrow 13579$). A cell % solution, say N, is represented as the `set' -N (e.g., a % potential solution 3 is represented as $[001000000]$ and the actual solution % 3 is represented by $[-3]$). % % % \begin{macro}{\initialisesuddata} % This sets each of the 81 cells to 111111111. % \begin{macrocode} %% initialise potential answer sets \newcommand*{\initialisesuddata}{\bgroup \global\s@lcnta\@ne \global\solcnt\z@ \global\difficultyctr\z@ \global\numcluesctr\z@ \loop \ifnum\s@lcnta<82\relax \global\useknt{s@lans\the\s@lcnta}=111111111\relax \advance\s@lcnta\@ne \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macrocode} %%%%%%%%%%%%%%%%%%%%%%%% utility macros for `binary solution sets' %%%%%%%%%%%%%%%% % \end{macrocode} % % \begin{macro}{\settonum} % \cs{settonum}\marg{set}\marg{cnt} converts a potential solution % binary set \meta{set} to the corresponding set of digits; that is % \verb?[11....1] -> 12...9?. The result of the conversion is assigned % to the \cs{count} \meta{cnt} which must be supplied by the calling macro. % If the set is negative then the result is that number % (e.g.\verb?[-3] -> -3?). If the set contains only a single non-zero % entry, that is converted to the negative of the corresponding digit % (e.g. \verb?[100] -> -7?). % % \begin{macrocode} %%\settonum{110011...}{cnt} %% converts a potential solution set to a number ([11....1] -> 12...9) %% returns the input if it is negative ([-3] -> -3) %% returns a negative number if the set represents a single digit ([10] -> -8) \newcommand*{\settonum}[2]{% \settonumcnt=#1\relax \tempcnty=\z@ \tenscnt=\@ne \ifnum\settonumcnt<\z@ % just return the number \tempcnty=\settonumcnt #2=\tempcnty \else \ifodd\settonumcnt % 9 flagged \tempcntz=9\relax \multiply\tempcntz \tenscnt \advance \tempcnty by \tempcntz \multiply\tenscnt 10\relax \fi \divide\settonumcnt by 10\relax \ifodd\settonumcnt % 8 flagged \tempcntz=8\relax \multiply\tempcntz \tenscnt \advance \tempcnty \tempcntz \multiply\tenscnt 10\relax \fi \divide\settonumcnt by 10\relax \ifodd\settonumcnt % 7 flagged \tempcntz=7\relax \multiply\tempcntz \tenscnt \advance \tempcnty \tempcntz \multiply\tenscnt 10\relax \fi \divide\settonumcnt by 10\relax \ifodd\settonumcnt % 6 flagged \tempcntz=6\relax \multiply\tempcntz \tenscnt \advance \tempcnty \tempcntz \multiply\tenscnt 10\relax \fi \divide\settonumcnt by 10\relax \ifodd\settonumcnt % 5 flagged \tempcntz=5\relax \multiply\tempcntz \tenscnt \advance \tempcnty \tempcntz \multiply\tenscnt 10\relax \fi \divide\settonumcnt by 10\relax \ifodd\settonumcnt % 4 flagged \tempcntz=4\relax \multiply\tempcntz \tenscnt \advance \tempcnty \tempcntz \multiply\tenscnt 10\relax \fi \divide\settonumcnt by 10\relax \ifodd\settonumcnt % 3 flagged \tempcntz=3\relax \multiply\tempcntz \tenscnt \advance \tempcnty \tempcntz \multiply\tenscnt 10\relax \fi \divide\settonumcnt by 10\relax \ifodd\settonumcnt % 2 flagged \tempcntz=2\relax \multiply\tempcntz \tenscnt \advance \tempcnty \tempcntz \multiply\tenscnt 10\relax \fi \divide\settonumcnt by 10\relax \ifodd\settonumcnt % 1 flagged \tempcntz=1\relax \multiply\tempcntz \tenscnt \advance \tempcnty \tempcntz %% \multiply\tenscnt 10\relax \fi \ifnum \tempcnty<10 \ifnum\tempcnty>\z@ \tempcnty = -\tempcnty \fi \fi #2=\tempcnty \fi} % \end{macrocode} % \end{macro} % % \begin{macro}{\numofnuminset} % \cs{numofnuminset}\marg{digit}\marg{set}\marg{cnt} set the \cs{count} % \meta{cnt}to the number of times the digit \meta{digit} is represented % in the binary set \meta{set}. For example, the number of digits in the set % \verb?[200000013]? are \verb?1 -> 2?, \verb?2 -> 0?, \verb?...?, % \verb?8 -> 1? and \verb?9 -> 3?. % \begin{macrocode} %%\numofnuminset{digit}{set}{returnctr} %% returns the number of times digit is represented in the set %% e.g. if the set is [200000013] then 1 -> 2, 2 -> 0,... 8 -> 1, 9 -> 3 \newcommand*{\numofnuminset}[3]{% \tmpsetctr=#2\relax \tmpsetansctr=\tmpsetctr \ifnum\tmpsetctr<\z@% solution, not a set \tmpsetansctr=\z@ \else \ifcase #1\relax \or % 1 \divide\tmpsetansctr by 100000000\relax \or % 2 \divide\tmpsetansctr by 10000000\relax \tmpsetctr=\tmpsetansctr \divide\tmpsetctr 10\relax \multiply\tmpsetctr 10\relax \advance\tmpsetansctr -\tmpsetctr \or % 3 \divide\tmpsetansctr by 1000000\relax \tmpsetctr=\tmpsetansctr \divide\tmpsetctr 10\relax \multiply\tmpsetctr 10\relax \advance\tmpsetansctr -\tmpsetctr \or % 4 \divide\tmpsetansctr by 100000\relax \tmpsetctr=\tmpsetansctr \divide\tmpsetctr 10\relax \multiply\tmpsetctr 10\relax \advance\tmpsetansctr -\tmpsetctr \or % 5 \divide\tmpsetansctr by 10000\relax \tmpsetctr=\tmpsetansctr \divide\tmpsetctr 10\relax \multiply\tmpsetctr 10\relax \advance\tmpsetansctr -\tmpsetctr \or % 6 \divide\tmpsetansctr by 1000\relax \tmpsetctr=\tmpsetansctr \divide\tmpsetctr 10\relax \multiply\tmpsetctr 10\relax \advance\tmpsetansctr -\tmpsetctr \or % 7 \divide\tmpsetansctr by 100\relax \tmpsetctr=\tmpsetansctr \divide\tmpsetctr 10\relax \multiply\tmpsetctr 10\relax \advance\tmpsetansctr -\tmpsetctr \or % 8 \divide\tmpsetansctr by 10\relax \tmpsetctr=\tmpsetansctr \divide\tmpsetctr 10\relax \multiply\tmpsetctr 10\relax \advance\tmpsetansctr -\tmpsetctr \or % 9 \tmpsetctr=\tmpsetansctr \divide\tmpsetctr 10\relax \multiply\tmpsetctr 10\relax \advance\tmpsetansctr -\tmpsetctr \else % error \tmpsetansctr=\z@ \fi \fi #3=\tmpsetansctr} % \end{macrocode} % \end{macro} % % \begin{macro}{\deletenumfromset} % \cs{deletenumfromset}\marg{digit}\marg{set}\marg{cnt} removes the % \meta{digit} from the \meta{set} and sets the \cs{count} \meta{cnt} % to the reulting modified set. If \meta{digit} was the only member % then the result is that digit negated. For example: \\ % \verb?9? from \verb?[...11] -> [...10]? \\ % \verb?8? from \verb?[0...010] -> -8? % \begin{macrocode} %%\deletenumfromset{digit}{set}{returnctr} %% deletes num from the [set], returning the modified set or a -ve number if %% the digit was the only member. %% e.g., 9 from [...11] -> [...10], 8 from [0...010] -> -8 \newcommand*{\deletenumfromset}[3]{ \global\setchangedfalse \tmpsetctr=#2\relax \tmpsetansctr=#2\relax \ifnum\tmpsetctr<\z@ % represents a solved number, do nothing \else \ifcase #1\relax \or % 1 \divide\tmpsetctr by 100000000\relax \ifodd\tmpsetctr% it's there \advance\tmpsetansctr -100000000\relax \global\setchangedtrue \fi \or % 2 \divide\tmpsetctr by 10000000\relax \ifodd\tmpsetctr% it's there \advance\tmpsetansctr -10000000\relax \global\setchangedtrue \fi \or % 3 \divide\tmpsetctr by 1000000\relax \ifodd\tmpsetctr% it's there \advance\tmpsetansctr -1000000\relax \global\setchangedtrue \fi \or % 4 \divide\tmpsetctr by 100000\relax \ifodd\tmpsetctr% it's there \advance\tmpsetansctr -100000\relax \global\setchangedtrue \fi \or % 5 \divide\tmpsetctr by 10000\relax \ifodd\tmpsetctr% it's there \advance\tmpsetansctr -10000\relax \global\setchangedtrue \fi \or % 6 \divide\tmpsetctr by 1000\relax \ifodd\tmpsetctr% it's there \advance\tmpsetansctr -1000\relax \global\setchangedtrue \fi \or % 7 \divide\tmpsetctr by 100\relax \ifodd\tmpsetctr% it's there \advance\tmpsetansctr -100\relax \global\setchangedtrue \fi \or % 8 \divide\tmpsetctr by 10\relax \ifodd\tmpsetctr% it's there \advance\tmpsetansctr -10\relax \global\setchangedtrue \fi \or % 9 \ifodd\tmpsetctr% it's there \advance\tmpsetansctr -1\relax \global\setchangedtrue \fi \fi \fi #3=\tmpsetansctr} % \end{macrocode} % \end{macro} % % \begin{macro}{\displaystatus} % This macro typesets a tabular showing the current real and potential % solutions for the grid. A real solution is shown as a negative number; % positive numbers are the potential solution digits for the cell. % \begin{macrocode} %% typeset current answers plus potential answer digits \newcommand*{\displaystatus}{% \begin{tabular}{||c|c|c||c|c|c||c|c|c||}\hline\hline \settonum{\the\useknt{s@lans1}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans2}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans3}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans4}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans5}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans6}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans7}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans8}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans9}}{\s@dtempcnta}\the\s@dtempcnta \\ \hline \settonum{\the\useknt{s@lans10}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans11}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans12}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans13}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans14}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans15}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans16}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans17}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans18}}{\s@dtempcnta}\the\s@dtempcnta \\ \hline \settonum{\the\useknt{s@lans19}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans20}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans21}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans22}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans23}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans24}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans25}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans26}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans27}}{\s@dtempcnta}\the\s@dtempcnta \\ \hline\hline \settonum{\the\useknt{s@lans28}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans29}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans30}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans31}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans32}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans33}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans34}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans35}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans36}}{\s@dtempcnta}\the\s@dtempcnta \\ \hline \settonum{\the\useknt{s@lans37}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans38}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans39}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans40}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans41}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans42}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans43}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans44}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans45}}{\s@dtempcnta}\the\s@dtempcnta \\ \hline \settonum{\the\useknt{s@lans46}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans47}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans48}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans49}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans50}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans51}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans52}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans53}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans54}}{\s@dtempcnta}\the\s@dtempcnta \\ \hline\hline \settonum{\the\useknt{s@lans55}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans56}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans57}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans58}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans59}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans60}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans61}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans62}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans63}}{\s@dtempcnta}\the\s@dtempcnta \\ \hline \settonum{\the\useknt{s@lans64}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans65}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans66}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans67}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans68}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans69}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans70}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans71}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans72}}{\s@dtempcnta}\the\s@dtempcnta \\ \hline \settonum{\the\useknt{s@lans73}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans74}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans75}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans76}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans77}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans78}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans79}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans80}}{\s@dtempcnta}\the\s@dtempcnta & \settonum{\the\useknt{s@lans81}}{\s@dtempcnta}\the\s@dtempcnta \\ \hline\hline \end{tabular}} % \end{macrocode} % \end{macro} % % \subsubsection{Problem initialisation} % % \begin{macrocode} %%%%%%%%%%%%%%%%%%%% get the problem and initialise the solution %%%%%%%%% % \end{macrocode} % % \begin{macro}{\getproblem} % \cs{getproblem}\marg{file} initialises the solution grid and reads the % puzzle from the sudoku file \meta{file}. It calls \cs{initialsoln} % to read the file and insert the clues into the grid. % \begin{macrocode} %% read the problem and initialise the problem (solution) \newcommand*{\getproblem}[1]{\bgroup \initialisesuddata \global\solcnt\z@ \immediate\closein\s@dread \immediate\openin\s@dread=#1 \initialsoln \typeout{Sudoku problem #1, \the\solcnt\space initial clues} \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\initialsoln} % Get the clues from the puzzle file, line by line, and insert them into % the grid. \cs{s@dline} holds one line from the file. % \begin{macrocode} %% insert the clues from the input game file \newcommand*{\initialsoln}{% \firsts@dcluetrue \s@dnrow\@ne \s@lcnta\@ne \loop \ifnum\s@dnrow<10\relax \read\s@dread to \s@dline \firsts@dcluetrue \s@dncol\@ne \dos@dinitialcols \advance\s@dnrow\@ne \repeat \immediate\closein\s@dread} % \end{macrocode} % \end{macro} % % \begin{macro}{\dos@dinitialcols} % Insert the clues from one line of the puzzle file into one row of the grid. % \begin{macrocode} %% insert the clues from one line of the game file \newcommand*{\dos@dinitialcols}{\bgroup \loop \ifnum\s@dncol<10\relax \fixentry \advance\s@dncol\@ne \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\fixentry} % Inserts a clue from the current line into the grid. % \begin{macrocode} %% insert a clue from the current line of the game file \newcommand*{\fixentry}{% \iffirsts@dclue \expandafter\splitoff\expandafter{\s@dline}% \global\firsts@dcluefalse \else \expandafter\splitoff\expandafter{\restchars}% \fi \ifx\s@dfstop\istchar \else \global\useknt{s@lans\the\s@lcnta}=-\istchar \global\advance\solcnt\@ne \global\advance\numcluesctr\@ne \fi \global\advance\s@lcnta\@ne} % \end{macrocode} % \end{macro} % % \subsection{Solution methods} % % % Three facts are used to generate a solution. % \begin{enumerate} % \item A digit must be unique within a row, a column, and a block % Thus, if a solution, say N, is known for a cell, then the % potential solution N must be deleted from all cells in the % row, column, and block that the solved cell is in. I have % called this a simple reduction. The simple reductions are repeated % until there are no changes to the potential solutions. % % \item If among all the cells in a row (column, block) there is a digit % that occurs only once among all the potential solutions, then that % digit is the solution for its cell. I have termed this a loner. % If a loner solution is found then simple reductions are repeated. % % \item If among all the cells in a row (column, block) there are two digits % which occur twice only in the row, each time as a pair (e.g., 39 % and 39) then one or other of the two digits must be a solution for % a cell in which the pairs occur. This means that the two digits in % the pair cannot occur anywhere else in the row (column, block). % If there are no loners then the problem is examined for pairs. If % there is any change in a potential solution then the simple % reduction process is applied. % \end{enumerate} % % The process stops either when all 81 cells have been solved or there % is no change in any potential solution after going through all the above % reductions. % % There are more sophisticated solution techniques that could be applied % but they are also increasingly difficult to code in \TeX. % % \begin{macro}{\reduceacell} % \cs{reduceacell} looks at the solution set for the current cell (the % \cs{s@lcnta} cell) and if the cell has been solved then it deletes the % solution digit from the row, column, and box in which the cell appears. % This may result in new solutions for other cells. % % Given a cell number $N$ ($080\relax \keeponfalse \fi \ifanychange\else \keeponfalse \fi} % \end{macrocode} % \end{macro} % % \begin{macro}{\keepreducingcells} % Keep on trying the simple reduction. % \begin{macrocode} %% Keep performing the simple reduction \newcommand*{\keepreducingcells}{\bgroup \commentary{Simple reductions}% \ifnum\difficultyctr<\tw@ \global\difficultyctr\tw@ \fi \changedtrue \loop \ifchanged \reduceallcells \checksimplereductions \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\checksimplereductions} % Determines whether or not to keep on trying simple reductions. % \begin{macrocode} \newcommand*{\checksimplereductions}{% \ifchanged\else \typesimplestatus \fi \ifnum\solcnt>80\relax% solution found! \changedfalse \fi} % \end{macrocode} % \end{macro} % % \begin{macrocode} %%%%%%%%%%%%%%%%%%%%% reduce loners %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \end{macrocode} % % \begin{macro}{\reduceloners} % Reduce via the loner digits, trying rows first, and if no change % then trying columns, and if still no change then trying boxes. % \begin{macrocode} %% reduce the loner digits, per row, column and box \newcommand*{\reduceloners}{% \commentary{reduceloners}% \global\lonerchangedfalse \ifnum\difficultyctr<4\relax \global\difficultyctr=4\relax \fi \ifnum\solcnt>80\else \bgroup \reducerowloners \iflonerchanged\else \reducecolloners \iflonerchanged\else \reduceboxloners \fi \fi \typelonestatus \egroup \fi} % \end{macrocode} % \end{macro} % % \begin{macro}{\reducerowloners} % Loop through the rows and reduce the first loner found. % \begin{macrocode} %% Loop through the rows, reducing loners \newcommand*{\reducerowloners}{% \sumctr\z@ \s@dnrow\@ne \loop \ifnum\s@dnrow<10\relax \s@lcnta=\s@dnrow \advance\s@lcnta\m@ne \multiply\s@lcnta 9\relax \advance\s@lcnta\@ne \sumrowsets \ifnum\sumctr>\z@ \getloner{\the\sumctr}{\s@dtempcntb} \ifnum\s@dtempcntb=\z@ \else \reducelonerrowcell{\the\s@lcnta}{\the\s@dtempcntb} \iflonerchanged \advance\s@dnrow 10\relax \fi \fi \fi \advance\s@dnrow\@ne \repeat} % \end{macrocode} % \end{macro} % % \begin{macro}{\sumrowsets} % Add together all the solution binary sets for the unsolved cells % in the current row (\cs{s@lcnta}). The result is in \cs{sumctr}. % \begin{macrocode} %% add the sets in the current row \newcommand*{\sumrowsets}{% \bgroup \s@dncol=\s@lcnta \toprangectr=\s@dncol \advance\toprangectr 9\relax \global\sumctr\z@ \loop \ifnum\s@dncol<\toprangectr \ifnum\useknt{s@lans\the\s@dncol}>\z@ \global\advance\sumctr\useknt{s@lans\the\s@dncol} \fi \advance\s@dncol\@ne \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\getloner} % \cs{getloner}\marg{setsum}\marg{cnt} examines (the sum of) a solution set % and returns the first loner (i.e., the first occurrence of the digit 1), or % zero if there is none. The result is converted to a solution digit and % assigned to the \cs{count} \meta{cnt}. % % For example, given the set \verb?[000200110]? it will return \verb?7? (the % set indicates two 4s, one 7, and one 8). % \begin{macrocode} %% get the loner from a setsum %% \getloner{setsum}{returnctr} returnes the (first) loner in a potential set, %% or zero \newcommand*{\getloner}[2]{\bgroup \ifnum #1>\z@ \s@dtemploopcnta\@ne \loop \ifnum\s@dtemploopcnta<10\relax \numofnuminset{\the\s@dtemploopcnta}{#1}{\s@dtempcnta} \ifnum\s@dtempcnta=\@ne% found a lone digit \s@dtempcnta=\s@dtemploopcnta \s@dtemploopcnta=100\relax \fi \advance\s@dtemploopcnta\@ne \repeat \ifnum\s@dtemploopcnta>99 \else \s@dtempcnta=\z@ \fi \global#2=\s@dtempcnta \else \s@dtempcnta=\z@ \global#2=\s@dtempcnta \fi \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\reducelonerowcell} % \cs{reducelonerowcell}\marg{rowcell}\marg{digit}. % Given (the cell at) the start of a row and a lone digit, find the cell % in the row with that digit in its solution set, and make the digit the % solution of that cell. % \begin{macrocode} %% \reducelonerowcell{startofrowcell}{digit} %% given a row and a lone digit, find the cell containing the digit %% and make the digit a solution of that cell. \newcommand*{\reducelonerrowcell}[2]{\bgroup \s@dncol=#1 \toprangectr=\s@dncol \advance\toprangectr 9\relax \ifnum #2<\@ne \advance\s@dncol 100\relax \fi \loop \ifnum\s@dncol<\toprangectr \numofnuminset{#2}{\the\useknt{s@lans\the\s@dncol}}{\lonecellctr} \ifnum\lonecellctr=\@ne% this cell has the loner \lonecellctr=#2 \global\useknt{s@lans\the\s@dncol}=-\lonecellctr \global\lonerchangedtrue \global\advance\solcnt\@ne \commentary{\the\solcnt\space solved (#2 loner in row starting #1)}% \s@dncol=\toprangectr \fi \advance\s@dncol\@ne \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\reducecolloners} % Loop through the columns and reduce the first loner found. % \begin{macrocode} %% Loop through the columns, reducing loners \newcommand*{\reducecolloners}{\bgroup \sumctr\z@ \s@dncol\@ne \loop \ifnum\s@dncol<10\relax \s@lcnta=\s@dncol \sumcolsets \ifnum\sumctr>\z@ \getloner{\the\sumctr}{\s@dtempcntb} \ifnum\s@dtempcntb=\z@ \else \reducelonercolcell{\the\s@lcnta}{\the\s@dtempcntb} \iflonerchanged \advance\s@dncol 10\relax \fi \fi \fi \advance\s@dncol\@ne \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\sumcolsets} % Sum all the solution sets of the unsolved cells in the current column % (\cs{s@lcnta}). The result is in \cs{sumctr}. % \begin{macrocode} %% add the sets in the current column \newcommand*{\sumcolsets}{\bgroup \s@dnrow=\s@lcnta \toprangectr=\s@dnrow \advance\toprangectr 73\relax \global\sumctr\z@ \loop \ifnum\s@dnrow<\toprangectr \ifnum\useknt{s@lans\the\s@dnrow}>\z@ \global\advance\sumctr\useknt{s@lans\the\s@dnrow} \fi \advance\s@dnrow 9\relax \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\reducelonercolcell} % \cs{reducelonercolcell}\marg{colcell}\marg{digit}. % Given (the cell at) the start of a column and a lone digit, find the cell % in the column with that digit in its solution set, and make the digit % the solution of that cell. % \begin{macrocode} %% \reducelonercolcell{startofcolcell}{digit} %% given a col and a lone digit, find the cell containing the digit %% and make the digit a solution of that cell. \newcommand*{\reducelonercolcell}[2]{\bgroup \s@dnrow=#1 \toprangectr=\s@dnrow \advance\toprangectr 73\relax \ifnum #2<\@ne \advance\s@dnrow 7300\relax \fi \loop \ifnum\s@dnrow<\toprangectr \numofnuminset{#2}{\the\useknt{s@lans\the\s@dnrow}}{\lonecellctr} \ifnum\lonecellctr=\@ne% this cell has the loner \lonecellctr=#2 \global\useknt{s@lans\the\s@dnrow}=-\lonecellctr \global\lonerchangedtrue \global\advance\solcnt\@ne \commentary{\the\solcnt\space solved (#2 loner in column starting #1)}% \s@dnrow=\toprangectr \fi \advance\s@dnrow 9\relax \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\reduceboxloners} % Loop through the boxes and reduce the first loner found. % \begin{macrocode} %% Loop through the boxes, reducing loners \newcommand*{\reduceboxloners}{\bgroup \sumctr\z@ \boxctr\@ne \loop \ifnum\boxctr<10\relax % \end{macrocode} % The next bit of code calculates the corner cell of the Nth box. % \begin{macrocode} \ifcase\boxctr \or \s@lcnta=\@ne \or \s@lcnta=4\relax \or \s@lcnta=7\relax \or \s@lcnta=28\relax \or \s@lcnta=31\relax \or \s@lcnta=34\relax \or \s@lcnta=55\relax \or \s@lcnta=58\relax \or \s@lcnta=61\relax \fi \sumboxsets \ifnum\sumctr>\z@ \getloner{\the\sumctr}{\s@dtempcntb} \ifnum\s@dtempcntb=\z@ \else \reducelonerboxcell{\the\s@lcnta}{\the\s@dtempcntb} \iflonerchanged \advance\boxctr 10\relax \fi \fi \fi \advance\boxctr\@ne \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\sumboxsets} % Sum all the solution sets of the unsolved cells in the current box % (\cs{s@lcnta}). The result is in \cs{sumctr}. % \begin{macrocode} %% add the sets in the current box \newcommand*{\sumboxsets}{\bgroup \s@dncol=\s@lcnta \toprangectr=\s@dncol \advance\toprangectr 3\relax \global\sumctr\z@ \loop \ifnum\s@dncol<\toprangectr \s@dnrow=\s@dncol \ifnum\useknt{s@lans\the\s@dnrow}>\z@ \global\advance\sumctr\useknt{s@lans\the\s@dnrow} \fi \advance\s@dnrow 9\relax \ifnum\useknt{s@lans\the\s@dnrow}>\z@ \global\advance\sumctr\useknt{s@lans\the\s@dnrow} \fi \advance\s@dnrow 9\relax \ifnum\useknt{s@lans\the\s@dnrow}>\z@ \global\advance\sumctr\useknt{s@lans\the\s@dnrow} \fi \advance\s@dncol\@ne \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\reducelonerboxcell} % \cs{reducelonerboxcell}\marg{boxcell}\marg{digit}. % Given (the cell at) the start of a box and a lone digit, find the cell % in the box with that digit in its solution set, and make the digit % the solution of that cell. % \begin{macrocode} %% \reducelonerboxcell{startofboxcell}{digit} %% given a box and a lone digit, find the cell containing the digit %% and make the digit a solution of that cell. \newcommand*{\reducelonerboxcell}[2]{\bgroup \s@dncol=\s@lcnta \toprangectr=\s@dncol \advance\toprangectr 3\relax \global\sumctr\z@ \loop \ifnum\s@dncol<\toprangectr \s@dnrow=\s@dncol \numofnuminset{#2}{\the\useknt{s@lans\the\s@dnrow}}{\lonecellctr} \ifnum\lonecellctr=\@ne% this cell has the loner \lonecellctr=#2 \global\useknt{s@lans\the\s@dnrow}=-\lonecellctr \global\lonerchangedtrue \global\advance\solcnt\@ne \commentary{\the\solcnt\space solved (#2 loner in box starting #1)}% \s@dncol=\toprangectr \fi \iflonerchanged\else \advance\s@dnrow 9\relax \numofnuminset{#2}{\the\useknt{s@lans\the\s@dnrow}}{\lonecellctr} \ifnum\lonecellctr=\@ne% this cell has the loner \lonecellctr=#2 \global\useknt{s@lans\the\s@dnrow}=-\lonecellctr \global\lonerchangedtrue \global\advance\solcnt\@ne \commentary{\the\solcnt\space solved (#2 loner in box starting #1)}% \s@dncol=\toprangectr \fi \fi \iflonerchanged\else \advance\s@dnrow 9\relax \numofnuminset{#2}{\the\useknt{s@lans\the\s@dnrow}}{\lonecellctr} \ifnum\lonecellctr=\@ne% this cell has the loner \lonecellctr=#2 \global\useknt{s@lans\the\s@dnrow}=-\lonecellctr \global\lonerchangedtrue \global\advance\solcnt\@ne \commentary{\the\solcnt\space solved (#2 loner in box starting #1)}% \s@dncol=\toprangectr \fi \fi \advance\s@dncol\@ne \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macrocode} %%%%%%%%%%%%%%%%%%%%% reduce pairs %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \end{macrocode} % % \begin{macro}{\reducepairs} % Perform pair reduction, reducing the first pair found. First try % by row, then by column, and lastly by box. % \begin{macrocode} %% reduce the pairs, per row, column and box \newcommand*{\reducepairs}{\bgroup \commentary{reducepairs}% **************************************}% \global\pairchangedfalse \ifnum\difficultyctr<8\relax \global\difficultyctr=8\relax \fi \ifnum\solcnt>80\else \reducerowpairs \ifpairchanged\else \reducecolpairs \ifpairchanged\else \reduceboxpairs \fi \fi \fi \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\reducerowpairs} % Loop through the rows and reduce the first pair found. % \begin{macrocode} %% Loop through the rows, reducing pairs \newcommand*{\reducerowpairs}{% \sumctr\z@ \s@dnrow\@ne \loop \ifnum\s@dnrow<10\relax \s@lcnta=\s@dnrow \advance\s@lcnta\m@ne \multiply\s@lcnta 9\relax \advance\s@lcnta\@ne \sumrowsets \ifnum\sumctr>\z@ \reducearowpair{\the\s@lcnta} \ifpairchanged \advance\s@dnrow 10\relax \fi \fi \advance\s@dnrow\@ne \repeat} % \end{macrocode} % \end{macro} % % \begin{macro}{\reducearowpair} % \cs{reducearowpair}\marg{rowcell} reduces a pair in the row starting % with cell \meta{rowcell}. % \begin{macrocode} %% reducearowpair{row} \newcommand*{\reducearowpair}[1]{% \bgroup \s@dncol=#1\relax \toprangectr=\s@dncol \advance\toprangectr 9\relax \maxrangectr=\toprangectr \advance\maxrangectr\m@ne \global\sumctr\z@ \loop \ifnum\s@dncol<\maxrangectr \asetctr=\useknt{s@lans\the\s@dncol}% \ifnum\asetctr>\z@ \findrowpair \fi \advance\s@dncol\@ne \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\findrowpair} % \cs{findrowpair} attempts to find a pair in the current row. % \begin{macrocode} \newcommand*{\findrowpair}{\bgroup \secondctr=\s@dncol \advance\secondctr\@ne \loop \ifnum\secondctr<\toprangectr \ifnum\asetctr=\useknt{s@lans\the\secondctr} \checksetforpair{\the\asetctr} \ifnum\numdigitsctr=\tw@ %% first row cell is \s@lcnta %% first pair cell is \s@dncol, second pair cell is \secondctr %% digits are \digitictr and \digitiictr \deleterowpairdigits \fi \fi \advance\secondctr\@ne \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\checksetforpair} % \cs{checksetforpair}\marg{set} attempts to find a pair in a set. % It sets \cs{digitictr} and \cs{digitiictr} as the first and second digits % in the set and \cs{numdigitsctr} to the total number of digits in the % set (which is 2 for a pair). % \begin{macrocode} %% \checksetforpair{set} returns with: %% \digitictr = first digit %% \digitiictr = second digit %% \numdigitsctr = number of digits (2 for a pair) \newcommand*{\checksetforpair}[1]{\bgroup \s@dtemploopcnta\@ne \global\numdigitsctr\z@ \global\digitictr\z@ \global\digitiictr\z@ \loop \ifnum\s@dtemploopcnta<10\relax \numofnuminset{\the\s@dtemploopcnta}{#1}{\s@dtempcnta} \ifnum\s@dtempcnta=\@ne \global\advance\numdigitsctr\@ne \ifcase\numdigitsctr \or \global\digitictr=\s@dtemploopcnta \or \global\digitiictr=\s@dtemploopcnta \else \advance\s@dtemploopcnta 10\relax \fi \fi \advance\s@dtemploopcnta\@ne \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\deleterowpairdigits} % \cs{deleterowpairdigits} deletes the pair digits from non-pair cells % in a row. The first cell in the row is \cs{s@lcnta}, the cells that % contain the two pairs are \cs{s@dncol} and \cs{secondctr}, and the % digits are \cs{digitictr} and \cs{digitiictr}. % \begin{macrocode} %% first row cell is \s@lcnta %% first pair cell is \s@dncol, second pair cell is \secondctr %% digits are \digitictr and \digitiictr \newcommand*{\deleterowpairdigits}{\bgroup \global\pairchangedfalse \s@dtemploopcnta=\s@lcnta \toprangectr=\s@dtemploopcnta \advance\toprangectr 9\relax \loop \ifnum\s@dtemploopcnta<\toprangectr \ifnum\s@dtemploopcnta=\s@dncol \else \ifnum\s@dtemploopcnta=\secondctr \else \deletenumfromset{\the\digitictr}% {\the\useknt{s@lans\the\s@dtemploopcnta}}{\s@dtempcnta} \ifsetchanged \global\useknt{s@lans\the\s@dtemploopcnta}=\s@dtempcnta \global\pairchangedtrue \fi \deletenumfromset{\the\digitiictr}% {\the\useknt{s@lans\the\s@dtemploopcnta}}{\s@dtempcnta} \ifsetchanged \global\useknt{s@lans\the\s@dtemploopcnta}=\s@dtempcnta \global\pairchangedtrue \fi \fi \fi \advance\s@dtemploopcnta\@ne \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\reducecolpairs} % Loop through the rows and reduce the first pair found. % \begin{macrocode} %% Loop through the columns, reducing pairs \newcommand*{\reducecolpairs}{% \sumctr\z@ \s@dncol\@ne \loop \ifnum\s@dncol<10\relax \s@lcnta=\s@dncol \sumcolsets \ifnum\sumctr>\z@ \reduceacolpair{\the\s@lcnta} \ifpairchanged \advance\s@dncol 10\relax \fi \fi \advance\s@dncol\@ne \repeat} % \end{macrocode} % \end{macro} % % \begin{macro}{\reduceacolpair} % \cs{reduceacolpair}\marg{colcell} reduces a pair in the column starting % with cell \meta{colcell}. % \begin{macrocode} %% reduceacolpair{col} \newcommand*{\reduceacolpair}[1]{\bgroup \s@dnrow=#1\relax \toprangectr=\s@dnrow \advance\toprangectr 73\relax \maxrangectr=\toprangectr \advance\maxrangectr -9\relax \global\sumctr\z@ \loop \ifnum\s@dnrow<\maxrangectr \asetctr=\useknt{s@lans\the\s@dnrow}% \ifnum\asetctr>\z@ \findcolpair \fi \advance\s@dnrow 9\relax \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\findcolpair} % \cs{findcolpair} attempts to find a pair in the current column. % \begin{macrocode} \newcommand*{\findcolpair}{\bgroup \secondctr=\s@dnrow \advance\secondctr 9\relax \loop \ifnum\secondctr<\toprangectr \ifnum\asetctr=\useknt{s@lans\the\secondctr} \checksetforpair{\the\asetctr} \ifnum\numdigitsctr=\tw@ %% first row cell is \s@lcnta %% first pair cell is \s@dnrow, second pair cell is \secondctr %% digits are \digitictr and \digitiictr \deletecolpairdigits \fi \fi \advance\secondctr 9\relax \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\deletecolpairdigits} % \cs{deletecolpairdigits} deletes the pair digits from non-pair cells % in a column. The first cell in the column is \cs{s@lcnta}, the cells that % contain the two pairs are \cs{s@dncol} and \cs{secondctr}, and the % digits are \cs{digitictr} and \cs{digitiictr}. % \begin{macrocode} %% first col cell is \s@lcnta %% first pair cell is \s@dnrow, second pair cell is \secondctr %% digits are \digitictr and \digitiictr \newcommand*{\deletecolpairdigits}{\bgroup \global\pairchangedfalse \s@dtemploopcnta=\s@lcnta \toprangectr=\s@dtemploopcnta \advance\toprangectr 73\relax \loop \ifnum\s@dtemploopcnta<\toprangectr \ifnum\s@dtemploopcnta=\s@dnrow \else \ifnum\s@dtemploopcnta=\secondctr \else \deletenumfromset{\the\digitictr}% {\the\useknt{s@lans\the\s@dtemploopcnta}}{\s@dtempcnta} \ifsetchanged \global\useknt{s@lans\the\s@dtemploopcnta}=\s@dtempcnta \global\pairchangedtrue \fi \deletenumfromset{\the\digitiictr}% {\the\useknt{s@lans\the\s@dtemploopcnta}}{\s@dtempcnta} \ifsetchanged \global\useknt{s@lans\the\s@dtemploopcnta}=\s@dtempcnta \global\pairchangedtrue \fi \fi \fi \advance\s@dtemploopcnta 9\relax \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\reduceboxpairs} % Loop through the boxes and reduce the first pair found. % \begin{macrocode} %% Loop through the boxes, reducing pairs \newcommand*{\reduceboxpairs}{\bgroup \sumctr\z@ \boxctr\@ne \loop \ifnum\boxctr<10\relax \ifcase\boxctr \or \s@lcnta=\@ne \or \s@lcnta=4\relax \or \s@lcnta=7\relax \or \s@lcnta=28\relax \or \s@lcnta=31\relax \or \s@lcnta=34\relax \or \s@lcnta=55\relax \or \s@lcnta=58\relax \or \s@lcnta=61\relax \fi \sumboxsets \ifnum\sumctr>\z@ \reduceaboxpair{\the\s@lcnta} \ifpairchanged \advance\boxctr 10\relax \fi \fi \advance\boxctr\@ne \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\getnthboxcell} % \cs{getnthboxcell}\marg{n}\marg{firstcell}\marg{cnt}. Given the first cell % (\meta{firstcell}) in a box and a number, \meta{n}, between 1 and 9, set % the \cs{count} \meta{cnt} to the cell number of the \meta{n}th cell in the % box. % \begin{macrocode} %% \getnthboxcell{n}{firstcell}{returnctr} \newcommand*{\getnthboxcell}[3]{\bgroup \s@dtempcnta=#2 \ifcase#1 \or \or \advance\s@dtempcnta 9\relax \or \advance\s@dtempcnta 18\relax \or \advance\s@dtempcnta \@ne \or \advance\s@dtempcnta 10\relax \or \advance\s@dtempcnta 19\relax \or \advance\s@dtempcnta \tw@ \or \advance\s@dtempcnta 11\relax \or \advance\s@dtempcnta 20\relax \fi \global #3=\s@dtempcnta \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\reduceaboxpair} % \cs{reduceaboxpair}\marg{boxcell} reduces a pair in the box starting % with cell \meta{boxcell}. % \begin{macrocode} %% \reduceaboxpair{startofboxcell} \newcommand*{\reduceaboxpair}[1]{\bgroup \s@dtemploopcnta\@ne \toprangectr=\s@dtemploopcnta \advance\toprangectr 9\relax \maxrangectr=\toprangectr \advance\maxrangectr\m@ne \loop \ifnum\s@dtemploopcnta<\maxrangectr \getnthboxcell{\the\s@dtemploopcnta}{#1}{\s@dtempcnta} \asetctr=\useknt{s@lans\the\s@dtempcnta} \ifnum\asetctr>\z@ \s@dnrow=\s@dtemploopcnta \findboxpair{#1} \fi \advance\s@dtemploopcnta\@ne \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\findboxpair} % \cs{findboxpair} attempts to find a pair in the current box, and then does % a pair reduction for the box. % \begin{macrocode} %% \findboxpair{startofboxcell} \newcommand*{\findboxpair}[1]{% \bgroup \secondctr=\s@dtemploopcnta \advance\secondctr\@ne \loop \ifnum\secondctr<\toprangectr \getnthboxcell{\the\secondctr}{#1}{\s@dtempcntb} \ifnum\asetctr=\useknt{s@lans\the\s@dtempcntb} \checksetforpair{\the\asetctr} \ifnum\numdigitsctr=\tw@ %% first box cell is #1 (=\s@lcnta) %% first pair cell is \s@dnrow, second pair cell is \secondctr %% digits are \digitictr and \digitiictr \deleteboxpairdigits{#1} \fi \fi \advance\secondctr \@ne \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\deleteboxpairdigits} % \cs{deleteboxpairdigits}\marg{boxcell} deletes the pair digits from % non-pair cells % in a box. The first cell in the box is \meta{boxcell}, the cells that % contain the two pairs are \cs{s@dnrow} and \cs{secondctr}, and the % digits are \cs{digitictr} and \cs{digitiictr}. % \begin{macrocode} %% first box cell is #1 %% first pair cell is \s@dnrow, second pair cell is \secondctr %% digits are \digitictr and \digitiictr \newcommand*{\deleteboxpairdigits}[1]{\bgroup \global\pairchangedfalse \s@dtemploopcnta=\@ne \toprangectr=\s@dtemploopcnta \advance\toprangectr 9\relax \loop \ifnum\s@dtemploopcnta<\toprangectr \ifnum\s@dtemploopcnta=\s@dnrow \else \ifnum\s@dtemploopcnta=\secondctr \else \getnthboxcell{\the\s@dtemploopcnta}{#1}{\s@dtempcntb} \deletenumfromset{\the\digitictr}% {\the\useknt{s@lans\the\s@dtempcntb}}{\s@dtempcnta} \ifsetchanged \global\useknt{s@lans\the\s@dtempcntb}=\s@dtempcnta \global\pairchangedtrue \fi \deletenumfromset{\the\digitiictr}% {\the\useknt{s@lans\the\s@dtempcntb}}{\s@dtempcnta} \ifsetchanged \global\useknt{s@lans\the\s@dtempcntb}=\s@dtempcnta \global\pairchangedtrue \fi \fi \fi \advance\s@dtemploopcnta \@ne \repeat \egroup} % \end{macrocode} % \end{macro} % % \subsubsection{Checking the solution} % % \begin{macrocode} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% check solution %%%%%%%%%%%%%%%%%%%%%%%%% % \end{macrocode} % % We have found a solution when all the binary sets are negative. % It's less efficient, but probably more useful, to check each % row, column, and block (3 times 81 tests instead of 81). % % \begin{macro}{\checksolution} % Check the solution by rows, columns, and boxes. % \begin{macrocode} \newcommand*{\checksolution}{% \checkrows \checkcols \checkboxes} % \end{macrocode} % \end{macro} % % \begin{macro}{\checkrows} % Check the row solutions. A row is said to be correct if a solution has % been assigned to each cell in the row, thus relying on the assumption % that the solver never makes a mistake. The check is not sufficient for % a solution obtained in another manner. % \begin{macrocode} \newcommand*{\checkrows}{% \sumctr\z@ \s@dnrow\@ne \loop \ifnum\s@dnrow<10\relax \s@lcnta=\s@dnrow \advance\s@lcnta\m@ne \multiply\s@lcnta 9\relax \advance\s@lcnta\@ne \sumrowsets \ifnum\sumctr=\z@\else \typeout{Row \the\s@dnrow\space is incorrect}% Row \the\s@dnrow\space is incorrect. \\ \fi \advance\s@dnrow\@ne \repeat} % \end{macrocode} % \end{macro} % % \begin{macro}{\checkcols} % Check the column solutions. % \begin{macrocode} \newcommand*{\checkcols}{% \bgroup \sumctr\z@ \s@dncol\@ne \loop \ifnum\s@dncol<10\relax \s@lcnta=\s@dncol \sumcolsets \ifnum\sumctr=\z@\else \typeout{Column \the\s@dncol\space is incorrect}% Column \the\s@dncol\space is incorrect. \\ \fi \advance\s@dncol\@ne \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\checkboxes} % Check the box solutions. % \begin{macrocode} \newcommand*{\checkboxes}{% \bgroup \sumctr\z@ \boxctr\@ne \loop \ifnum\boxctr<10\relax \ifcase\boxctr \or \s@lcnta=\@ne \or \s@lcnta=4\relax \or \s@lcnta=7\relax \or \s@lcnta=28\relax \or \s@lcnta=31\relax \or \s@lcnta=34\relax \or \s@lcnta=55\relax \or \s@lcnta=58\relax \or \s@lcnta=61\relax \fi \sumboxsets \ifnum\sumctr=\z@\else \typeout{Box \the\boxctr\space is incorrect}% Box \the\boxctr\space is incorrect. \\ \fi \advance\boxctr\@ne \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\typesimplestatusX} % May be used to display the cuurrent status of the (partial) solution % following simple reductions. % \begin{macrocode} %% typeset the current status of the partial solution \newcommand*{\typesimplestatusX}{% \par\noindent\begin{minipage}{\linewidth} \begin{center} Simple reductions stopped (with \the\solcnt\space solutions)\\ %\footnotesize \displaystatus \end{center} \end{minipage}} % \end{macrocode} % \end{macro} % % \begin{macro}{\typelonestatusX} % May be used to display the current status of the (partial) solution after a % loner reduction. % \begin{macrocode} %% typeset the current status after loner processing \newcommand*{\typelonestatusX}{% \par\noindent\begin{minipage}{\linewidth} \begin{center} Loners processed (with \the\solcnt\space solutions)\\ %\footnotesize \displaystatus \end{center} \end{minipage}} % \end{macrocode} % \end{macro} % % \begin{macro}{\hideprogress} % \begin{macro}{\showprogess} % Normally the progress towards a solution is not displayed. It will be % displayed in the document, though, after the \cs{showprogress} declaration. % The \cs{hideprogress} declaration switches off the displays. % \begin{macrocode} %% For curiosity as to how a solution is developing call the \showprogess %% declaration (\hideprogess turns this off). \newcommand*{\hideprogress}{% \let\typesimplestatus\relax \let\typelonestatus\relax} \newcommand*{\showprogress}{% \let\typesimplestatus\typesimplestatusX \let\typelonestatus\typelonestatusX} \hideprogress %\showprogress % \end{macrocode} % \end{macro} % \end{macro} % % % \begin{macrocode} %%%%%%%%%%%%%%%%%% write solution to a game file %%%%%%%%%%%%%%% % \end{macrocode} % % \begin{macro}{\sudsolnfile} % \begin{macro}{\writegame} % \cs{writegame} writes the (partial) solution to the file \cs{sudsolnfile} % (default \file{sud.out}). % \begin{macrocode} %% write out the solution to game file \sudsolnfile. \newcommand*{\sudsolnfile}{sud.out} \newcommand*{\writegame}{% \immediate\closeout\s@dwrite \immediate\openout\s@dwrite=\sudsolnfile \s@dnrow\@ne \loop \ifnum\s@dnrow<81\relax \gatherline{\the\s@dnrow} \immediate\write\s@dwrite{\sudaline} \advance\s@dnrow 9\relax \repeat \immediate\closeout\s@dwrite} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\gatherline} % \begin{macro}{\sudaline} % \cs{gatherline}\marg{rowstartcell} collects the solutions from one % row in the grid % and converts them into the corresponding characters for one line % in a sudoku file, putting the characters into the \cs{sudaline} macro. % \begin{macrocode} %% \gatherline{colstart} %% collect all the characters for one line in a game file \newcommand*{\gatherline}[1]{\bgroup \gdef\sudaline{} \s@dncol=#1\relax \toprangectr=\s@dncol \advance\toprangectr 9\relax \loop \ifnum\s@dncol<\toprangectr \s@dtempcnta=\useknt{s@lans\the\s@dncol} \ifnum\s@dtempcnta>\m@ne \g@addto@macro{\sudaline}{.} \else \s@dtempcnta=-\s@dtempcnta \ifcase\s@dtempcnta \or \g@addto@macro{\sudaline}{1} \or \g@addto@macro{\sudaline}{2} \or \g@addto@macro{\sudaline}{3} \or \g@addto@macro{\sudaline}{4} \or \g@addto@macro{\sudaline}{5} \or \g@addto@macro{\sudaline}{6} \or \g@addto@macro{\sudaline}{7} \or \g@addto@macro{\sudaline}{8} \or \g@addto@macro{\sudaline}{9} \else \g@addto@macro{\sudaline}{.} \fi \fi \advance\s@dncol\@ne \repeat \egroup} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macrocode} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% THE END GOAL %%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%% \sudoksolve{} %%%%%%%%%%%%%%%%%%%%%% % \end{macrocode} % % \begin{macro}{\sudokusolve} % \cs{sudokesolve}\marg{file} reads a sudoku puzzle from the \meta{file} % sudoku file, typesets the problem, does its best to solve it. % It writes the solution to the \cs{sudsolnfile} file, then reads % it back in again and typesets it. % \begin{macrocode} %% Read in and typeset the problem, solve it, and typeset the answer \newcommand{\sudokusolve}[1]{% \begin{center} \sudoku{#1}% \end{center} \getproblem{#1}% \reduceallcells \keepreducing \writegame \noindent\begin{minipage}{\linewidth} THE ANSWER \begin{center} \cluefont\normalsize \cellsize{1.5\baselineskip} \sudoku{\sudsolnfile} \end{center} \end{minipage}} % \end{macrocode} % \end{macro} % % % The end of the package. % \begin{macrocode} % % \end{macrocode} % % % \subsection{The \Lpack{createsudoku} package} % % The \Lpack{createsudoku} package lets you automatically generate % Sudoku puzzles. The package requires Donald Arseneau's \file{random.tex} % and also the \Lpack{solvesudoku} package, which in turn % requires the \Lpack{printsudoku} package. % % \begin{macrocode} %<*create> \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{createsudoku}[2006/02/16 v1.0 create sudoku puzzles] \input{random} \RequirePackage{solvesudoku} % \end{macrocode} % % \begin{macro}{\oldcommentary} % \begin{macro}{\commentary} % \begin{macro}{\gencommentary} % To avoid clutter it's a good % idea to switch off \Lpack{solvesudoku}'s commentary. On the other hand % it could be useful for this package to provide its own commentary. % \begin{macrocode} \let\oldcommentary\commentary \let\commentary\@gobble \newcommand*{\gencommentary}[1]{\typeout{#1}} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\genfile} % \begin{macro}{\prevfile} % \begin{macro}{\currfile} % We need a file to write out the puxzzle to, and we also need two % temporary files. % \begin{macrocode} \newcommand*{\genfile}{gensud.sud} \newcommand*{\prevfile}{genprev.sdx} \newcommand*{\currfile}{gencurr.sdx} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\randomi} % \begin{macro}{\setsudrandom} % This sets the seed for the random number generator. The default is % setting it to -1, which makes the seed depend on the date and time. % \begin{macrocode} \randomi\m@ne \newcommand*{\setsudrandom}[1]{% \randomi=#1\relax \ifnum\randomi<\@ne\else \nextrandom \nextrandom \nextrandom \typeout{random initialised to #1}% \fi} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\generategrid} % \begin{macro}{\printsudresults} % \cs{generategrid}\oarg{file} generates a new puzzle. If the sudoko file % \meta{file} is specified this is taken for the starting grid, otherwise % a default one is used. The starting grid should be a complete solution. % % The pairs of rows, and pairs of columns, in the starting grid are % exchanged in a random fashion (\cs{swaps}) and then the cell solutions % are eliminated (\cs{elimclues}) until the puzzle is sufficiently complicated. % \begin{macrocode} \newcommand*{\generategrid}[1][\@empty]{% \ifx\@empty #1 \writestartgrid \getproblem{\prevfile} \else \getproblem{#1} \fi \swaps \elimclues \printsudresults} \newcommand*{\printsudresults}{% \sudokusolve{\genfile}% } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\writestartgrid} % Write out an initial fully solved grid to \cs{prevfile}. % \begin{macrocode} %% the starting data \newcommand*{\writestartgrid}{% \immediate\closeout\s@dwrite \immediate\openout\s@dwrite=\prevfile \immediate\write\s@dwrite{123456789} \immediate\write\s@dwrite{456789123} \immediate\write\s@dwrite{789123456} \immediate\write\s@dwrite{234567891} \immediate\write\s@dwrite{567891234} \immediate\write\s@dwrite{891234567} \immediate\write\s@dwrite{345678912} \immediate\write\s@dwrite{678912345} \immediate\write\s@dwrite{912345678} \immediate\closeout\s@dwrite} % \end{macrocode} % \end{macro} % % \begin{macro}{\swaps} % \cs{swaps} randomly exchanges the contents of pairs of columns and pairs % of rows. In order to preserve the number uniqueness constraint for boxes, % only pairs of columns/rows that are in the same box may be exchanged. % \begin{macrocode} \newcommand*{\swaps}{\bgroup \setrannum{\maxrangectr}{36}{48}% \gencommentary{number of swaps (36--48) = maxrangectr = \the\maxrangectr} \s@dtemploopcnta\@ne \loop \ifnum\s@dtemploopcnta<\maxrangectr \setrannum{\s@dtempcntb}{1}{18}% %%\typeout{\space\space\space swap no \the\s@dtemploopcnta\space is \the\s@dtempcntb} \ifcase\s@dtempcntb \or \swapcolpair{1}{2}% \or \swapcolpair{1}{3}% \or \swapcolpair{2}{3}% \or \swapcolpair{4}{5}% \or \swapcolpair{4}{6}% \or \swapcolpair{5}{6}% \or \swapcolpair{7}{8}% \or \swapcolpair{7}{9}% \or \swapcolpair{8}{9}% \or \swaprowpair{1}{10}% \or \swaprowpair{1}{19}% \or \swaprowpair{10}{19}% \or \swaprowpair{28}{37}% \or \swaprowpair{28}{46}% \or \swaprowpair{37}{46}% \or \swaprowpair{55}{64}% \or \swaprowpair{55}{73}% \or \swaprowpair{64}{73}% \fi \advance\s@dtemploopcnta\@ne \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\swaprowpair} % \cs{swaprowpair}\marg{rowstartcell1}\marg{rowstartcell2} swaps the % contents of the two rows starting at \meta{rowstartcell1} and % \meta{rowstartcell2}. % \begin{macrocode} %% swap the data in rows starting at #1, and #2 \newcommand*{\swaprowpair}[2]{\bgroup \s@dncol=#1\relax \s@dcolpos=#2\relax \s@dtemploopcnta\@ne \maxrangectr=10\relax \loop \ifnum\s@dtemploopcnta<\maxrangectr \s@dtempcnta=\useknt{s@lans\the\s@dncol}% \global\useknt{s@lans\the\s@dncol}=\useknt{s@lans\the\s@dcolpos}% \global\useknt{s@lans\the\s@dcolpos}=\s@dtempcnta \advance\s@dncol\@ne \advance\s@dcolpos\@ne \advance\s@dtemploopcnta\@ne \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\swapcolpair} % \cs{swapcolpair}\marg{colstartcell1}\marg{colowstartcell2} swaps the % contents of the two columns starting at \meta{colstartcell1} and % \meta{colstartcell2}. % \begin{macrocode} %% swap the data in cols starting #1 and #2 \newcommand*{\swapcolpair}[2]{\bgroup \s@dnrow=#1\relax \s@drowpos=#2\relax \s@dtemploopcnta\@ne \maxrangectr=10\relax \loop \ifnum\s@dtemploopcnta<\maxrangectr \s@dtempcnta=\useknt{s@lans\the\s@dnrow}% \global\useknt{s@lans\the\s@dnrow}=\useknt{s@lans\the\s@drowpos}% \global\useknt{s@lans\the\s@drowpos}=\s@dtempcnta \advance\s@dnrow 9\relax \advance\s@drowpos 9\relax \advance\s@dtemploopcnta\@ne \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\elimclues} % \cs{elimclues} first eliminates a set of clues from the (full) grid, writing % the resulting puzzle to the two temporary files \cs{prevfile} and % \cs{currfile}. It % then eliminates clues one-by-one until the puzzle has been finally % generated, the result having been written to the \cs{prevfile}, % then writing it out to the file \cs{genfile}. % \begin{macrocode} \newcommand*{\elimclues}{\bgroup \initialelimination \writestate{\prevfile}% \writestate{\currfile}% \elimcluesonebyone \getproblem{\prevfile} \writestate{\genfile} \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\elimseventeen} % \cs{elimseventeen} randomly eliminates the solutions for 17 cells in the % grid (apparently if two numbers are completely eliminated as clues in a % puzzle, then at best the solution is ambiguous). % \begin{macrocode} \newcommand*{\elimseventeen}{\bgroup \s@dtemploopcnta\@ne \maxrangectr 18\relax \loop \ifnum\s@dtemploopcnta<\maxrangectr \setrannum{\s@dtempcnta}{1}{81} \global\useknt{s@lans\the\s@dtempcnta}=111111111\relax \advance\s@dtemploopcnta\@ne \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\elimcross} % Eliminate all solutions in column 5 and row 5. % \begin{macrocode} %% eliminates all clues in column 5 and row 5 \newcommand*{\elimcross}{\bgroup \s@dtemploopcnta 5\relax \loop \ifnum\s@dtemploopcnta<78\relax% 78 = 5 + 73 \global\useknt{s@lans\the\s@dtemploopcnta}=111111111\relax \advance\s@dtemploopcnta 9\relax \repeat \s@dtemploopcnta 37\relax \loop \ifnum\s@dtemploopcnta<46\relax% 46 = 37 + 9 \global\useknt{s@lans\the\s@dtemploopcnta}=111111111\relax \advance\s@dtemploopcnta \@ne \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\elimnum} % \cs{elimnum}\marg{num} (\verb?0 < num < 10?) eliminates all % instances of the \meta{num} solution from the grid. % \begin{macrocode} \newcommand*{\elimnum}[1]{\bgroup \s@dtemploopcnta\@ne \loop \ifnum\s@dtemploopcnta<82\relax \ifnum\useknt{s@lans\the\s@dtemploopcnta}=-#1\relax \global\useknt{s@lans\the\s@dtemploopcnta}=111111111\relax \fi \advance\s@dtemploopcnta \@ne \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\elimcrossandnines} % Eliminate all 9's and the solutions in column 5 and row 5. % \begin{macrocode} \newcommand*{\elimcrossandnines}{\bgroup \elimcross \s@dtemploopcnta\@ne \loop \ifnum\s@dtemploopcnta<82\relax \ifnum\useknt{s@lans\the\s@dtemploopcnta}=-9\relax \global\useknt{s@lans\the\s@dtemploopcnta}=111111111\relax \fi \advance\s@dtemploopcnta \@ne \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\elimex} % Eliminate all solutions on the diagonals of the grid. % \begin{macrocode} \newcommand*{\elimex}{\bgroup \s@dtemploopcnta\@ne \loop \ifnum\s@dtemploopcnta<82\relax \global\useknt{s@lans\the\s@dtemploopcnta}=111111111\relax \advance\s@dtemploopcnta 10\relax \repeat \s@dtemploopcnta=9\relax \loop \ifnum\s@dtemploopcnta<81\relax \global\useknt{s@lans\the\s@dtemploopcnta}=111111111\relax \advance\s@dtemploopcnta 8\relax \repeat \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\elimcrossandex} % Eliminate all solutions in column 5 and row 5 and on the diagonals. % \begin{macrocode} \newcommand*{\elimcrossandex}{\bgroup \elimcross \elimex \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\elimcrossandexandnines} % Eliminate all solutions in column 5 and row 5 and on the diagonals, % and all 9's. % \begin{macrocode} \newcommand*{\elimcrossandexandnines}{\bgroup \elimcross \elimex \elimnum{9} \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\initialelimination} % \cs{initialelimination} eliminates an initial set of solutions from the grid. % Several predefined sets are provided. % \begin{macrocode} \let\initialelimination\elimseventeen \let\initialelimination\elimcross \let\initialelimination\elimcrossandnines \let\initialelimination\elimcrossandex \let\initialelimination\elimcrossandexandnines % \end{macrocode} % \end{macro} % % % \begin{macro}{\toomanyloops} % \begin{macro}{\elimcluesonebyone} % Eliminate solutions from the grid one-by-one until the puzzle cannot be % solved. Then reinstate the last solution deleted to produce the final puzzle. % I'm not sure if this is needed, but just in case the process stops after % 81 attempts to remove solutions (highly unlikely but the random number % generator could keep producing numbers corresponding to clueless cells). % % We use the \cs{currfile} and \cs{prevfile} to hold the current state of % affairs and the previous state. % \begin{macrocode} \newcount\toomanyloops \newcommand*{\elimcluesonebyone}{\bgroup %%%\typeout{***elimcluesonebyone} \toomanyloops\z@ \s@dtempcntb=81\relax \loop \ifnum\s@dtempcntb>80\relax \advance\toomanyloops\@ne % \end{macrocode} % Read the current puzzle from \cs{currfile} and try to solve it. % \begin{macrocode} \getproblem{\currfile} \trysolution \ifnum\solcnt=81\relax % can delete another clue % \end{macrocode} % The puzzle was solvable so try deleting another clue. Read the (unsolved) % puzzle again from \cs{currfile} and write its state to \cs{prevfile}. % \begin{macrocode} \getproblem{\currfile} \writestate{\prevfile} % \end{macrocode} % Now delete a clue, writing the resultant puzzle to \cs{currfile}, and % go round the loop again. % \begin{macrocode} \deleteaclue \writestate{\currfile}% \s@dtempcntb=81\relax \else % done % \end{macrocode} % The puzzle was not solvable, and the state before the last clue deletion % is in file \cs{prevfile}. % \begin{macrocode} \typeout{Solver failed, solcnt = \the\solcnt} \s@dtempcntb=\@ne \fi \ifnum\toomanyloops>80\relax \typeout{Too much looping} \s@dtempcntb=\@ne \fi \repeat \egroup} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\ifacluenotdeleted} % \begin{macro}{\deleteaclue} % Keep calling the random number generator until it returns a cell that has % a solution, % then delete the solution. % \begin{macrocode} \newif\ifacluenotdeleted \newcommand*{\deleteaclue}{\bgroup \acluenotdeletedtrue \loop \ifacluenotdeleted \setrannum{\s@dtempcnta}{1}{81}% \ifnum\useknt{s@lans\the\s@dtempcnta}<\z@% found a clue \gencommentary{Deleting clue for cell \the\s@dtempcnta}% \global\useknt{s@lans\the\s@dtempcnta}=111111111\relax \acluenotdeletedfalse \fi \repeat \egroup} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\trysolution} % \cs{trysolution} attempts to solve the current puzzle state. % \begin{macrocode} \newcommand*{\trysolution}{\bgroup \reduceallcells \keepreducing \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\writestate} % \cs{writestate}\marg{file} writes the current state (clues and blanks) % to the sudoku file \meta{file}. % \begin{macrocode} %% \writestate{} \newcommand*{\writestate}[1]{\bgroup \immediate\closeout\s@dwrite \immediate\openout\s@dwrite=#1 \s@dnrow\@ne \loop \ifnum\s@dnrow<81\relax \gatherline{\the\s@dnrow}% \immediate\write\s@dwrite{\sudaline}% \advance\s@dnrow 9\relax \repeat \immediate\closeout\s@dwrite \egroup} % \end{macrocode} % \end{macro} % The end of the package. % \begin{macrocode} % % \end{macrocode} % % \section{Example sudoku puzzles} % % LaTeXing the following file will provide you with a selection of Sudoku % puzzles. You can try solving them yourself and/or get Latex to do it for % you. The \Lpack{solvesudoku} package is able to solve most, but not all % of the puzzles. % % \begin{macrocode} %<*examples> \documentclass[twoside]{article} \usepackage{comment} \usepackage{url} \usepackage{printsudoku} \newcommand*{\Lpack}[1]{\textsf{#1}} \title{Example Sudoku Puzzles} \author{Peter Wilson} \date{16 February 2006} \raggedbottom \begin{document} \maketitle A Sudoku puzzle consists of a 9 by 9 array of squares, some of which have numbers in them, the numbers ranging from 1 through 9. The problem is to fill in all the squares such that each row, column, and 3 by 3 box includes the numbers 1 through 9 with no repetitions. This is a collection of some 54 Sudoku puzzles which I have culled from various places. The sources include, among others: the \emph{Sudoku Solver}~\cite{SSBL} website (labelled SE, SM, SH and SVH), \emph{The Daily Telegraph}~\cite{DT2} (labelled TG, TM, and TT), \emph{The Seattle Times} (labelled ST), and some automatically generated by the \Lpack{createsudoku} package~\cite{SUDOKUBUNDLE} (labelled CS). You can try solving them yourself and/or get LaTeX to do it for you. The \Lpack{solvesudoku} package~\cite{SUDOKUBUNDLE} is able to solve most, but not all of the puzzles. Other LaTeX packages may do better or worse. The puzzles are presented in approximately increasing order of difficulty. Each source, though, has its own set of categories which don't necessarily agree with each other (and sometimes not within one source). I have included an indication of the difficulty as stated by the relevant source. The parameters for the puzzles created via \Lpack{createsudoku} are given in the table. \begin{table}[hbp] \centering \begin{tabular}{lll} \hline Number & Seed & \verb?initialelimination? \\ \hline CS1 & 1505263462 & \verb?\elimcrossandexandnines? \\ CS2 & 1495929734 & \verb?\elimcrossandex? \\ CS3 & 1487762722 & \verb?\elimcrossandexandnines? \\ CS4 & 1508763610 & \verb?\elimcrossandex? \\ CS5 & 839068723 & \verb?\elimseventeen? \\ CS6 & 833235143 & \verb?\elimcrossandexandnines? \\ \hline \end{tabular} \end{table} \cleardoublepage \cluefont{\LARGE} \cellsize{2.25\baselineskip} \markboth{EASY}{EASY} \pagestyle{headings} \renewcommand*{\puzzlefile}{se5.sud} \writepuzzle% {.2...5863}{56.2.3.9.}{.3...7251}% {..975....}{..6..47.9}{.7..286..}% {6.58...7.}{8....1..6}{3.7.6..4.}% [SSBL easy 5] \vfill \begin{minipage}{0.95\linewidth}\begin{center} SE5 (easy) \\ \sudoku{se5.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{se10.sud} \writepuzzle% {..6.497..}{.82.1.6..}{79..8.145}% {649.5.27.}{..7.6..5.}{.3..72.96}% {.2....81.}{.7..28...}{......5.7}% [SSBL easy 10] \vfill \begin{minipage}{0.95\linewidth}\begin{center} SE10 (easy) \\ \sudoku{se10.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{se15.sud} \writepuzzle% {4.67.39.2}{..16.84..}{.7...4..1}% {5...4.21.}{.2.....6.}{.68.7...9}% {6..5...9.}{..24.93..}{9.53.17.4}% [SSBL easy 15] \vfill \begin{minipage}{0.95\linewidth}\begin{center} SE15 (easy) \\ \sudoku{se15.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{se20.sud} \writepuzzle% {36.9..5..}{..54.8.2.}{.....78.9}% {2....3.68}{.83.9....}{.4.7..2.3}% {6.71..3..}{13.8.59.2}{..9.7..56}% [SSBL easy 20] \vfill \begin{minipage}{0.95\linewidth}\begin{center} SE20 (easy) \\ \sudoku{se20.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{se25.sud} \writepuzzle% {....63.5.}{6.5.1.839}{..1...2..}% {823...7..}{.5...7...}{.64.9...1}% {4.25796.3}{.9.1.65.8}{.1...89.7}% [SSBL easy 25] \vfill \begin{minipage}{0.95\linewidth}\begin{center} SE25 (easy) \\ \sudoku{se25.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{se30.sud} \writepuzzle% {.3.12....}{1.87..4.6}{..98....1}% {5....7.3.}{.73.9.2.4}{.92..65..}% {.4...8.5.}{3...7...8}{2..4.596.}% [SSBL easy 30] \vfill \begin{minipage}{0.95\linewidth}\begin{center} SE30 (easy) \\ \sudoku{se30.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{tg5.sud} \writepuzzle% {.6.1.9.8.}{.19...74.}{2.......1}% {..79.26..}{.3.....2.}{..14.35..}% {1.......5}{.75...23.}{.9.5.6.7.}% [DT2 gentle 5] \vfill \begin{minipage}{0.95\linewidth}\begin{center} TG5 (gentle) \\ \sudoku{tg5.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{tg10.sud} \writepuzzle% {....96..4}{..1.....2}{56...8...}% {2.8....9.}{9.63.52.7}{.3....4.6}% {...9...58}{7.....9..}{8..45....}% [DT2 gentle 10] \vfill \begin{minipage}{0.95\linewidth}\begin{center} TG10 (gentle) \\ \sudoku{tg10.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{tg15.sud} \writepuzzle% {...1.8...}{.57...18.}{98.....26}% {..67419..}{.........}{..42536..}% {72.....94}{.19...73.}{...3.9...}% [DT2 gentle 15] \vfill \begin{minipage}{0.95\linewidth}\begin{center} TG15 (gentle) \\ \sudoku{tg15.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{tg20.sud} \writepuzzle% {...7.9...}{.8.3.6.5.}{7.9...6.8}% {..42.18..}{.6.....4.}{..35.41..}% {9.2...5.7}{.4.8.7.1.}{...1.2...}% [DT2 gentle 20] \vfill \begin{minipage}{0.95\linewidth}\begin{center} TG20 (gentle) \\ \sudoku{tg20.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{tg25.sud} \writepuzzle% {7..4..5..}{.61..5.7.}{.9.7.1..6}% {8...27...}{.........}{...34...1}% {1..8.2.3.}{.7.1..62.}{..3..9..7}% [DT2 gentle 25] \vfill \begin{minipage}{0.95\linewidth}\begin{center} TG25 (gentle) \\ \sudoku{tg25.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{tg30.sud} \writepuzzle% {37.4.....}{9....61.4}{....23...}% {.4.1..9..}{.12...79.}{..5..7.4.}% {...36....}{4.32....6}{.....9.57}% [DT2 gentle 30] \vfill \begin{minipage}{0.95\linewidth}\begin{center} TG30 (gentle) \\ \sudoku{tg30.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{st1226.sud} \writepuzzle% {9....4.31}{7452.....}{.8..674..}% {.26.4...5}{5..6.9..8}{4...2.37.}% {..759..6.}{.....1823}{21.3....7}% [Seattle Times 2005/12/26 1 star] \vfill \begin{minipage}{0.95\linewidth}\begin{center} ST1226 (1 star) \\ \sudoku{st1226.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{st0206.sud} \writepuzzle% {17.42...5}{..2.1..96}{849..3...}% {....718..}{.25...67.}{..826....}% {...5..749}{53..9.1..}{6...48.23}% [Seattle Times 2005/02/06 1 star] \vfill \begin{minipage}{0.95\linewidth}\begin{center} ST0206 (1 star) \\ \sudoku{st0206.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{st0213.sud} \writepuzzle% {.94.2...7}{.36...1.5}{28.35....}% {..92...5.}{6.21.49.8}{.7...63..}% {....13.46}{1.5...78.}{8...4.29.}% [Seattle Times 2006/02/13 1 star] \vfill \begin{minipage}{0.95\linewidth}\begin{center} ST0213 (1 star) \\ \sudoku{st0213.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{cs1.sud} \writepuzzle% {.46..731.}{2.36.4...}{87.3.1.45}% {657...423}{.........}{.81...756}% {43.8.6..1}{7..2..5.4}{..25.386.}% [CreateSudoku 1 (level 2)] \vfill \begin{minipage}{0.95\linewidth}\begin{center} CS1 (level 2) \\ \sudoku{cs1.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{cs2.sud} \writepuzzle% {.7.3.265.}{...6..9.7}{64.9.8.2.}% {..9...765}{.........}{756...4.2}% {29.5...76}{...2.15.3}{..4..7.1.}% [CreateSudoku 2 (level 2)] \vfill \begin{minipage}{0.95\linewidth}\begin{center} CS2 (level 2) \\ \sudoku{cs2.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{cs3.sud} \writepuzzle% {.5.8.71..}{..35.....}{78.2.1.56}% {.34...8.1}{.........}{8.1...56.}% {.4.7.6.12}{...4.36.8}{.781..34.}% [CreateSudoku 3 (level 2)] \vfill \begin{minipage}{0.95\linewidth}\begin{center} CS3 (level 2) \\ \sudoku{cs3.sud} \end{center}\end{minipage} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% moderate \clearpage \markboth{MODERATE}{MODERATE} \renewcommand*{\puzzlefile}{sm5.sud} \writepuzzle% {..76..24.}{.46....9.}{92..85...}% {8....29..}{..3...4..}{..49....6}% {...73..24}{.5....86.}{.32..67..}% [SSBL medium 5] \vfill \begin{minipage}{0.95\linewidth}\begin{center} SM5 (medium) \\ \sudoku{sm5.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{sm10.sud} \writepuzzle% {..57.82..}{4.......6}{.7..6..8.}% {52.9.4.31}{.........}{86.1.7.54}% {.9..3..6.}{7.......5}{..24.61..}% [SSBL medium 10] \vfill \begin{minipage}{0.95\linewidth}\begin{center} SM10 (medium) \\ \sudoku{sm10.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{sm15.sud} \writepuzzle% {85...4..2}{4...2.9..}{...8...7.}% {..6.....1}{.4..8..3.}{2.....5..}% {.34..7...}{.87.9...6}{6..1...47}% [SSBL medium 15] \vfill \begin{minipage}{0.95\linewidth}\begin{center} SM15 (medium) \\ \sudoku{sm15.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{sm20.sud} \writepuzzle% {..34.2.97}{..4....2.}{.7.6....8}% {....9....}{.38...47.}{....1....}% {4....5.1.}{.5....6..}{72.3.19..}% [SSBL medium 20] \vfill \begin{minipage}{0.95\linewidth}\begin{center} SM20 (medium) \\ \sudoku{sm20.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{sm25.sud} \writepuzzle% {...4.79..}{7.6...2..}{..5..83.6}% {56..298..}{..8..1...}{.3.7....5}% {.......38}{....93...}{.4.5.....}% [SSBL medium 25] \vfill \begin{minipage}{0.95\linewidth}\begin{center} SM25 (medium) \\ \sudoku{sm25.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{sm30.sud} \writepuzzle% {..58.....}{....79...}{..461..7.}% {.5.3....4}{.23...65.}{9....8.3.}% {.3..572..}{...42....}{.....61..}% [SSBL medium 30] \vfill \begin{minipage}{0.95\linewidth}\begin{center} SM30 (medium) \\ \sudoku{sm30.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{tm35.sud} \writepuzzle% {5..3.8..6}{..4.5.8..}{2.8...1.5}% {..62.74..}{.........}{..94.32..}% {9.5...6.4}{..2.1.9..}{1..8.9..2}% [DT2 moderate 35] \vfill \begin{minipage}{0.95\linewidth}\begin{center} TM35 (moderate) \\ \sudoku{tm35.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{tm40.sud} \writepuzzle% {...1...92}{9...7..36}{3....2...}% {.3....7.9}{.8.9.5.6.}{4.5....8.}% {...8....5}{54..2...7}{12...3...}% [DT2 moderate 40] \vfill \begin{minipage}{0.95\linewidth}\begin{center} TM40 (moderate) \\ \sudoku{tm40.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{tm45.sud} \writepuzzle% {.1.2.8.3.}{..87.94..}{9.......6}% {..9.8.5..}{6.......3}{..3.5.6..}% {2.......7}{..73.51..}{.6.4.7.9.}% [DT2 moderate 45] \vfill \begin{minipage}{0.95\linewidth}\begin{center} TM45 (moderate) \\ \sudoku{tm45.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{tm50.sud} \writepuzzle% {...9.2..4}{4..3.5...}{3.....7.6}% {6..8..3..}{1.3...9.7}{..9..7..2}% {9.5.....8}{...2.9..1}{2..7.4...}% [DT2 moderate 50] \vfill \begin{minipage}{0.95\linewidth}\begin{center} TM50 (moderate) \\ \sudoku{tm50.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{tm55.sud} \writepuzzle% {7........}{24.1.8...}{.6..72..3}% {..4.29.8.}{.7.....6.}{.9.46.7..}% {1..68..3.}{...3.7.91}{........6}% [DT2 moderate 55] \vfill \begin{minipage}{0.95\linewidth}\begin{center} TM55 (moderate) \\ \sudoku{tm55.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{tm60.sud} \writepuzzle% {724.9.5..}{.5..2...8}{.8.5.7...}% {...7..64.}{....8....}{.79..6...}% {...8.5.2.}{6...4..8.}{..8.3.174}% [DT2 moderate 60] \vfill \begin{minipage}{0.95\linewidth}\begin{center} TM60 (moderate) \\ \sudoku{tm60.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{st0914.sud} \writepuzzle% {.6.29..8.}{..8....3.}{.1..78...}% {.217.9..8}{6.......3}{7..6.492.}% {...12..4.}{.7....3..}{.5..86.7.}% [Seattle Times 2005/09/14 2 stars] \vfill \begin{minipage}{0.95\linewidth}\begin{center} ST0914 (2 stars) \\ \sudoku{st0914.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{st0207.sud} \writepuzzle% {.......46}{5..8.9.73}{...6..5.1}% {.592..1..}{6...1...7}{..3..785.}% {2.5..6...}{19.7.5..8}{34.......}% [Seattle Times 2005/02/07 2 stars] \vfill \begin{minipage}{0.95\linewidth}\begin{center} ST0207 (2 stars) \\ \sudoku{st0207.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{cs4.sud} \writepuzzle% {...4.597.}{..67.83.2}{78.1.2.45}% {891...75.}{.........}{567...423}% {.1...4.67}{..89.15..}{.4....29.}% [CreateSudoku 4 (level 8)] \vfill \begin{minipage}{0.95\linewidth}\begin{center} CS4 (level 4) \\ \sudoku{cs4.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{cs5.sud} \writepuzzle% {...6..978}{..498...2}{.97.21...}% {..84.27..}{.7.....23}{3...6...9}% {7.6..95..}{...87...1}{.2..4.867}% [CreateSudoku 5 (level 4)] \vfill \begin{minipage}{0.95\linewidth}\begin{center} CS5 (level 4) \\ \sudoku{cs5.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{cs6.sud} \writepuzzle% {.126.4.7.}{6.5..73.2}{.7.3.1.4.}% {756...423}{.........}{18......6}% {.3.8.6..1}{2.1.....7}{..72...3.}% [CreateSudoku 6 (level 4)] \vfill \begin{minipage}{0.95\linewidth}\begin{center} CS6 (level 4) \\ \sudoku{cs6.sud} \end{center}\end{minipage} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% hard \clearpage \markboth{HARD}{HARD} \renewcommand*{\puzzlefile}{sh5.sud} \writepuzzle% {..9..5...}{47...2...}{.836.4.1.}% {.15....8.}{...3.7...}{.2....74.}% {.4.5.187.}{...7...52}{...2..1..}% [SSBL hard 5] \vfill \begin{minipage}{0.95\linewidth}\begin{center} SH5 (hard) \\ \sudoku{sh5.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{sh10.sud} \writepuzzle% {.3.921..5}{15.83....}{.........}% {59......4}{37.....81}{6......53}% {.........}{....19.26}{9..574.1.}% [SSBL hard 10] \vfill \begin{minipage}{0.95\linewidth}\begin{center} SH10 (hard) \\ \sudoku{sh10.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{sh15.sud} \writepuzzle% {2..9.....}{.7..6..59}{...4...61}% {7.1..2..4}{....4....}{8..1..9.6}% {12...3...}{53..2..7.}{.....9..2}% [SSBL hard 15] \vfill \begin{minipage}{0.95\linewidth}\begin{center} SH15 (hard) \\ \sudoku{sh15.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{sh20.sud} \writepuzzle% {.6.2...3.}{9...3...1}{....9.2..}% {1..7.....}{.32...46.}{.....4..2}% {..7.4....}{2...5...8}{.4...6.5.}% [SSBL hard 20] \vfill \begin{minipage}{0.95\linewidth}\begin{center} SH20 (hard) \\ \sudoku{sh20.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{sh25.sud} \writepuzzle% {4....1..8}{..7.3845.}{..24...1.}% {28.9.....}{..4...5..}{.....4.86}% {.4...92..}{.2134.8..}{9..6....1}% [SSBL hard 25] \vfill \begin{minipage}{0.95\linewidth}\begin{center} SH25 (hard) \\ \sudoku{sh25.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{sh30.sud} \writepuzzle% {....5..9.}{.53..78..}{78.4.....}% {3....9.2.}{.72...38.}{.1.3....4}% {.....1.35}{..58..41.}{.2..3....}% [SSBL hard 30] \vfill \begin{minipage}{0.95\linewidth}\begin{center} SH30 (hard) \\ \sudoku{sh30.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{tt100.sud} \writepuzzle% {...896..7}{..23.5...}{..8...5.1}% {15...9...}{3.......9}{...6...54}% {8.1...7..}{...9.18..}{6..428...}% [DT2 tough 100] \vfill \begin{minipage}{0.95\linewidth}\begin{center} TT100 (tough) \\ \sudoku{tt100.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{tt105.sud} \writepuzzle% {..5.7..46}{6..25....}{.3...6...}% {2..7.....}{.78...35.}{.....1..7}% {...8...2.}{....97..5}{81..2.9..}% [DT2 tough 105] \vfill \begin{minipage}{0.95\linewidth}\begin{center} TT105 (tough) \\ \sudoku{tt105.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{tt110.sud} \writepuzzle% {.79.1....}{.4.5....7}{1..6.....}% {9368..1..}{..4...9..}{..7..4632}% {.....8..1}{5....6.9.}{....4.82.}% [DT2 tough 110] \vfill \begin{minipage}{0.95\linewidth}\begin{center} TT110 (tough) \\ \sudoku{tt110.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{tt115.sud} \writepuzzle% {432.5....}{.....3...}{75.1.....}% {..5.823..}{.6.5.1.4.}{..193.2..}% {.....6.58}{...3.....}{....2.934}% [DT2 tough 115] \vfill \begin{minipage}{0.95\linewidth}\begin{center} TT115 (tough) \\ \sudoku{tt115.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{tt120.sud} \writepuzzle% {..8.1.7..}{.4.67.8..}{..2..461.}% {.9....1.8}{.........}{2.1....9.}% {.759..4..}{..4.52.6.}{..9.3.5..}% [DT2 tough 120] \vfill \begin{minipage}{0.95\linewidth}\begin{center} TT120 (tough) \\ \sudoku{tt120.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{st1130.sud} \writepuzzle% {8..356...}{5....4.1.}{34.......}% {7.156..2.}{.6.....7.}{.2..796.5}% {.......32}{.9.4....8}{...682..9}% [Seattle Times 2005/11/30 3 stars] \vfill \begin{minipage}{0.95\linewidth}\begin{center} ST1130 (3 stars) \\ \sudoku{st1130.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{st1207.sud} \writepuzzle% {...483..6}{.....57.2}{......38.}% {..8..16..}{.26.5.17.}{..57..2..}% {.82......}{9.18.....}{4..527...}% [Seattle Times 2005/12/07 3 stars] \vfill \begin{minipage}{0.95\linewidth}\begin{center} ST1207 (3 stars) \\ \sudoku{st1207.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{st1209.sud} \writepuzzle% {...6.....}{.4..8..5.}{.519..2.8}% {..729...3}{.9.....1.}{4...679..}% {6.8..957.}{.7..2..9.}{.....4...}% [Seattle Times 2005/12/09 5 stars] \vfill \begin{minipage}{0.95\linewidth}\begin{center} ST1209 (5 stars) \\ \sudoku{st1209.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{st1221.sud} \writepuzzle% {.....392.}{4....5.7.}{29.4...63}% {..4....5.}{...2.1...}{.5....3..}% {74...2.96}{.6.5....7}{.217.....}% [Seattle Times 2005/12/21 3 stars] \vfill \begin{minipage}{0.95\linewidth}\begin{center} ST1221 (3 stars) \\ \sudoku{st1221.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{st1228.sud} \writepuzzle% {6..1..5..}{......379}{.942.....}% {..5...8.3}{.4.....9.}{9.7...6..}% {.....623.}{138......}{..6..8..7}% [Seattle Times 2005/12/28 3 stars] \vfill \begin{minipage}{0.95\linewidth}\begin{center} ST1228 (3 stars) \\ \sudoku{st1228.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{st0126.sud} \writepuzzle% {..36...7.}{1...352..}{..4......}% {..6....29}{7.......4}{32....5..}% {......1..}{..824...5}{.4...93..}% [Seattle Times 2006/01/26 4 stars] \vfill \begin{minipage}{0.95\linewidth}\begin{center} ST0126 (4 stars) \\ \sudoku{st0126.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{st0127.sud} \writepuzzle% {25.8.....}{....9.8.2}{9..4.7...}% {64.....9.}{.9.1.3.4.}{.7.....21}% {...5.4..7}{7.6.8....}{.....1.83}% [Seattle Times 2006/01/27 5 stars] \vfill \begin{minipage}{0.95\linewidth}\begin{center} ST0127 (5 stars) \\ \sudoku{st0127.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{st0204.sud} \writepuzzle% {.5..2.8.6}{.....6..3}{.6..132..}% {.7....96.}{4.......1}{.16....3.}% {..723..8.}{6..7.....}{2.4.9..7.}% [Seattle Times 2006/02/04 6 stars] \vfill \begin{minipage}{0.95\linewidth}\begin{center} ST0204 (6 stars) \\ \sudoku{st0204.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{st0208.sud} \writepuzzle% {21.9....7}{5.9..421.}{..7......}% {..875....}{3.14.95.8}{....361..}% {......4..}{.325..9.1}{1....8.25}% [Seattle Times 2005/02/08 3 stars] \vfill \begin{minipage}{0.95\linewidth}\begin{center} ST0208 (3 stars) \\ \sudoku{st0208.sud} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{st0209.sud} \writepuzzle% {..9......}{.523.1...}{8.12.6...}% {..4....1.}{97..2..84}{.2....9..}% {...8.41.5}{...6.524.}{......8..}% [Seattle Times 2005/02/09 4 stars] \vfill \begin{minipage}{0.95\linewidth}\begin{center} ST0209 (4 stars) \\ \sudoku{st0209.sud} \end{center}\end{minipage} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% answers \clearpage \pagestyle{empty} \cleardoublepage \pagestyle{myheadings} \markboth{SOLUTIONS}{SOLUTIONS} \cluefont{\normalsize} \cellsize{1.5\baselineskip} \renewcommand*{\puzzlefile}{se5.ans} \writepuzzle% {724195863}{561283497}{938647251}% {189756324}{256314789}{473928615}% {645839172}{892471536}{317562948}% [SSBL easy 5 solution] \renewcommand*{\puzzlefile}{se10.ans} \writepuzzle% {156349782}{482715639}{793286145}% {649853271}{217964358}{835172496}% {524697813}{371528964}{968431527}% [SSBL easy 10 solution] \vfill \noindent\begin{minipage}{0.47\linewidth}\begin{center} SE5 (easy solution) \\ \sudoku{se5.ans} \end{center}\end{minipage} \hfill \begin{minipage}{0.47\linewidth}\begin{center} SE10 (easy solution) \\ \sudoku{se10.ans} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{se15.ans} \writepuzzle% {456713982}{231698475}{879254631}% {597846213}{124935867}{368172549}% {643527198}{712489356}{985361724}% [SSBL easy 15 solution] \renewcommand*{\puzzlefile}{se20.ans} \writepuzzle% {368912547}{975438621}{412657839}% {291543768}{783296414}{546781293}% {657129384}{134865972}{829374156}% [SSBL easy 20 solution] \vfill \noindent\begin{minipage}{0.47\linewidth}\begin{center} SE15 (easy solution) \\ \sudoku{se15.ans} \end{center}\end{minipage} \hfill \begin{minipage}{0.47\linewidth}\begin{center} SE20 (easy solution) \\ \sudoku{se20.ans} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{se25.ans} \writepuzzle% {278963154}{645712839}{931854276}% {823641795}{159387462}{764295381}% {482579613}{397126548}{516438927}% [SSBL easy 25 solution] \renewcommand*{\puzzlefile}{se30.ans} \writepuzzle% {436129875}{128753496}{759864321}% {514287639}{673591284}{892346517}% {941638752}{365972148}{287415963}% [SSBL easy 30 solution] \vfill \noindent\begin{minipage}{0.47\linewidth}\begin{center} SE25 (easy solution) \\ \sudoku{se25.ans} \end{center}\end{minipage} \hfill \begin{minipage}{0.47\linewidth}\begin{center} SE30 (easy solution) \\ \sudoku{se30.ans} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{tg5.ans} \writepuzzle% {764159382}{519238746}{823674951}% {457982613}{936715428}{281463597}% {142397865}{675841239}{398526174}% [DT2 gentle 5 solution] \renewcommand*{\puzzlefile}{tg10.ans} \writepuzzle% {382196574}{491573862}{567248139}% {278614395}{946385217}{135729486}% {624931758}{753862941}{819457623}% [DT2 gentle 10 solution] \vfill \noindent\begin{minipage}{0.47\linewidth}\begin{center} TG5 (gentle solution) \\ \sudoku{tg5.ans} \end{center}\end{minipage} \hfill \begin{minipage}{0.47\linewidth}\begin{center} TG10 (gentle solution) \\ \sudoku{tg10.ans} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{tg15.ans} \writepuzzle% {462198573}{357462189}{981537426}% {236741958}{175986342}{894253617}% {723615894}{619824735}{548379261}% [DT2 gentle 15 solution] \renewcommand*{\puzzlefile}{tg20.ans} \writepuzzle% {256789431}{481326759}{739415628}% {594261873}{167938245}{823574196}% {912643587}{645897312}{378152964}% [DT2 gentle 20 solution] \vfill \noindent\begin{minipage}{0.47\linewidth}\begin{center} TG15 (gentle solution) \\ \sudoku{tg15.ans} \end{center}\end{minipage} \hfill \begin{minipage}{0.47\linewidth}\begin{center} TG20 (gentle solution) \\ \sudoku{tg20.ans} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{tg25.ans} \writepuzzle% {782463519}{461295378}{395781246}% {819527463}{634918752}{527346891}% {256872934}{978134625}{243659187}% [DT2 gentle 25 solution] \renewcommand*{\puzzlefile}{tg30.ans} \writepuzzle% {376418529}{928756134}{154923678}% {749132865}{612584793}{835697241}% {597361482}{483275916}{261849357}% [DT2 gentle 30 solution] \vfill \noindent\begin{minipage}{0.47\linewidth}\begin{center} TG25 (gentle solution) \\ \sudoku{tg25.ans} \end{center}\end{minipage} \hfill \begin{minipage}{0.47\linewidth}\begin{center} TG30 (gentle solution) \\ \sudoku{tg30.ans} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{st1226.ans} \writepuzzle% {962854731}{745213689}{183967452}% {326748915}{571639248}{498125376}% {837592164}{659471823}{214386597}% [Seattle Times 2005/12/26 1 star solution] \renewcommand*{\puzzlefile}{st0206.ans} \writepuzzle% {176429385}{352817496}{849653217}% {463971852}{925384671}{718265934}% {281536749}{534792168}{697148523}% [Seattle Times 2005/02/06 1 star solution] \vfill \noindent\begin{minipage}{0.47\linewidth}\begin{center} ST1226 (1 star solution) \\ \sudoku{st1226.ans} \end{center}\end{minipage} \hfill \begin{minipage}{0.47\linewidth}\begin{center} ST0206 (1 star solution) \\ \sudoku{st0206.ans} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{st0123.ans} \writepuzzle% {594621837}{736489125}{281357469}% {319278654}{652134978}{478596312}% {927813546}{145962783}{863745291}% [Seattle Times 2006/01/23 1 star solution] \renewcommand*{\puzzlefile}{cs1.ans} \writepuzzle% {546987312}{213654978}{879321645}% {657198423}{324765189}{981432756}% {435876291}{768219534}{192543867}% [CreateSudoku 1 (level 2) solution] \vfill \noindent\begin{minipage}{0.47\linewidth}\begin{center} ST0123 (1 star solution) \\ \sudoku{st0123.ans} \end{center}\end{minipage} \hfill \begin{minipage}{0.47\linewidth}\begin{center} CS1 (level 2 solution) \\ \sudoku{cs1.ans} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{cs2.ans} \writepuzzle% {978312654}{312645987}{645978321}% {189423765}{423756198}{756189432}% {291534876}{867291543}{534867219}% [CreateSudoku 2 (level 2) solution] \renewcommand*{\puzzlefile}{cs3.ans} \writepuzzle% {456897123}{123564789}{789231456}% {234675891}{567918234}{891342567}% {345786912}{912453678}{678129345}% [CreateSudoku 3 (level 2) solution] \vfill \noindent\begin{minipage}{0.47\linewidth}\begin{center} CS2 (level 2 solution) \\ \sudoku{cs2.ans} \end{center}\end{minipage} \hfill \begin{minipage}{0.47\linewidth}\begin{center} CS3 (level 2 solution) \\ \sudoku{cs3.ans} \end{center}\end{minipage} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% medium \renewcommand*{\puzzlefile}{sm5.ans} \writepuzzle% {387691245}{546273198}{921485637}% {865342971}{193567482}{274918356}% {618739524}{759124863}{432856719}% [SSBL medium 5 solution] \renewcommand*{\puzzlefile}{sm10.ans} \writepuzzle% {635748219}{418392576}{279561483}% {527984631}{941653827}{863127954}% {194835762}{786219345}{352476198}% [SSBL medium 10 solution] \vfill \noindent\begin{minipage}{0.47\linewidth}\begin{center} SM5 (medium solution) \\ \sudoku{sm5.ans} \end{center}\end{minipage} \hfill \begin{minipage}{0.47\linewidth}\begin{center} SM10 (medium solution) \\ \sudoku{sm10.ans} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{sm15.ans} \writepuzzle% {853974612}{471326958}{962815473}% {396542781}{745681239}{218739564}% {134267895}{587493126}{629158347}% [SSBL medium 15 solution] \renewcommand*{\puzzlefile}{sm20.ans} \writepuzzle% {863452197}{594178326}{172639548}% {617894235}{938526471}{234713869}% {489265713}{351947682}{726381954}% [SSBL medium 20 solution] \vfill \noindent\begin{minipage}{0.47\linewidth}\begin{center} SM15 (medium solution) \\ \sudoku{sm15.ans} \end{center}\end{minipage} \hfill \begin{minipage}{0.47\linewidth}\begin{center} SM20 (medium solution) \\ \sudoku{sm20.ans} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{sm25.ans} \writepuzzle% {382467951}{716935284}{495218376}% {564329817}{278651493}{139784625}% {927146538}{651893742}{843572169}% [SSBL medium 25 solution] \renewcommand*{\puzzlefile}{sm30.ans} \writepuzzle% {765834921}{318279465}{294615378}% {657392814}{823741659}{941568732}% {439157286}{186423597}{572986143}% [SSBL medium 30 solution] \vfill \noindent\begin{minipage}{0.47\linewidth}\begin{center} SM25 (medium solution) \\ \sudoku{sm25.ans} \end{center}\end{minipage} \hfill \begin{minipage}{0.47\linewidth}\begin{center} SM30 (medium solution) \\ \sudoku{sm30.ans} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{tm35.ans} \writepuzzle% {591328746}{674951823}{238674195}% {356297481}{427185369}{819463257}% {985732614}{742516938}{163849572}% [DT2 moderate 35 solution] \renewcommand*{\puzzlefile}{tm40.ans} \writepuzzle% {874136592}{952478136}{316592874}% {631284759}{287915463}{495367281}% {763841925}{548629317}{129753648}% [DT2 moderate 40 solution] \vfill \noindent\begin{minipage}{0.47\linewidth}\begin{center} TM35 (moderate solution) \\ \sudoku{tm35.ans} \end{center}\end{minipage} \hfill \begin{minipage}{0.47\linewidth}\begin{center} TM40 (moderate solution) \\ \sudoku{tm40.ans} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{tm45.ans} \writepuzzle% {716248935}{538769421}{924531786}% {179683542}{652974813}{483152679}% {241896357}{897325164}{365417298}% [DT2 moderate 45 solution] \renewcommand*{\puzzlefile}{tm50.ans} \writepuzzle% {751962834}{468375219}{392148756}% {627891345}{143526987}{589437162}% {975613428}{834259671}{216784593}% [DT2 moderate 50 solution] \vfill \noindent\begin{minipage}{0.47\linewidth}\begin{center} TM45 (moderate solution) \\ \sudoku{tm45.ans} \end{center}\end{minipage} \hfill \begin{minipage}{0.47\linewidth}\begin{center} TM50 (moderate solution) \\ \sudoku{tm50.ans} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{tm55.ans} \writepuzzle% {731946528}{245138679}{968572143}% {614729385}{572813964}{893465712}% {159684237}{426357891}{387291456}% [DT2 moderate 55 solution] \renewcommand*{\puzzlefile}{tm60.ans} \writepuzzle% {734198562}{156324798}{982567431}% {813752649}{465983217}{279416853}% {341875926}{697241385}{528639174}% [DT2 moderate 60 solution] \vfill \noindent\begin{minipage}{0.47\linewidth}\begin{center} TM55 (moderate solution) \\ \sudoku{tm55.ans} \end{center}\end{minipage} \hfill \begin{minipage}{0.47\linewidth}\begin{center} TM60 (moderate solution) \\ \sudoku{tm60.ans} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{st0914.ans} \writepuzzle% {567293184}{298461537}{413578692}% {321759468}{649812753}{785634921}% {936127845}{872945316}{154386279}% [Seattle Times 2005/09/14 2 star solution] \renewcommand*{\puzzlefile}{st0207.ans} \writepuzzle% {872351946}{561849273}{934672581}% {759283164}{628514397}{413967852}% {285436719}{196725438}{347198625}% [Seattle Times 2005/02/07 2 star solution] \vfill \noindent\begin{minipage}{0.47\linewidth}\begin{center} ST0914 (2 star solution) \\ \sudoku{st0914.ans} \end{center}\end{minipage} \hfill \begin{minipage}{0.47\linewidth}\begin{center} ST0207 (2 star solution) \\ \sudoku{st0207.ans} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{cs4.ans} \writepuzzle% {123465978}{456798312}{789132645}% {891243756}{234576189}{567819423}% {912354867}{678921534}{345687291}% [CreateSudoku 4 (level 4) solution] \renewcommand*{\puzzlefile}{cs5.ans} \writepuzzle% {231654978}{564987312}{897321645}% {918432756}{675198423}{342765189}% {786219534}{453876291}{129543867}% [CreateSudoku 5 (level 4) solution] \vfill \noindent\begin{minipage}{0.47\linewidth}\begin{center} CS4 (level 8 solution) \\ \sudoku{cs4.ans} \end{center}\end{minipage} \hfill \begin{minipage}{0.47\linewidth}\begin{center} CS5 (level 8 solution) \\ \sudoku{cs5.ans} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{cs6.ans} \writepuzzle% {312654978}{645987312}{978321645}% {756198423}{423765189}{189432756}% {534876291}{291543867}{867219534}% [CreateSudoku 6 (level 4) solution] \renewcommand*{\puzzlefile}{sh5.ans} \writepuzzle% {269175438}{471832965}{583694217}% {715426389}{894317526}{326958741}% {942561873}{138749652}{657283194}% [SSBL hard 5 solution] \vfill \noindent\begin{minipage}{0.47\linewidth}\begin{center} CS6 (level 4 solution) \\ \sudoku{cs6.ans} \end{center}\end{minipage} \hfill \begin{minipage}{0.47\linewidth}\begin{center} SH5 (hard solution) \\ \sudoku{sh5.ans} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{sh10.ans} \writepuzzle% {437921865}{156837492}{289456137}% {598163274}{374295681}{621748953}% {713682549}{845319726}{962574318}% [SSBL hard 10 solution] \renewcommand*{\puzzlefile}{sh15.ans} \writepuzzle% {216935847}{478261359}{395478261}% {761392584}{952846713}{843157926}% {124783695}{539624178}{687519432}% [SSBL hard 15 solution] \vfill \noindent\begin{minipage}{0.47\linewidth}\begin{center} SH10 (hard solution) \\ \sudoku{sh10.ans} \end{center}\end{minipage} \hfill \begin{minipage}{0.47\linewidth}\begin{center} SH15 (hard solution) \\ \sudoku{sh15.ans} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{sh20.ans} \writepuzzle% {468271935}{925438671}{713695284}% {154762893}{832519467}{679384512}% {587943126}{296157348}{341826759}% [SSBL hard 20 solution] \renewcommand*{\puzzlefile}{sh25.ans} \writepuzzle% {439561728}{167238459}{852497613}% {286953174}{794816532}{513724986}% {348179265}{621345897}{975682341}% [SSBL hard 25 solution] \vfill \noindent\begin{minipage}{0.47\linewidth}\begin{center} SH20 (hard solution) \\ \sudoku{sh20.ans} \end{center}\end{minipage} \hfill \begin{minipage}{0.47\linewidth}\begin{center} SH25 (hard solution) \\ \sudoku{sh25.ans} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{sh30.ans} \writepuzzle% {461258793}{253917846}{789463152}% {346789521}{572146389}{918325674}% {894671235}{635892417}{127534968}% [SSBL hard 30 solution] \renewcommand*{\puzzlefile}{tt100.ans} \writepuzzle% {513896427}{742315698}{968742531}% {154289376}{376154289}{289637154}% {891563742}{425971863}{637428915}% [DT2 tough 100 solution] \vfill \noindent\begin{minipage}{0.47\linewidth}\begin{center} SH30 (hard solution) \\ \sudoku{sh30.ans} \end{center}\end{minipage} \hfill \begin{minipage}{0.47\linewidth}\begin{center} TT100 (tough solution) \\ \sudoku{tt100.ans} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{tt105.ans} \writepuzzle% {925378146}{681254793}{734916582}% {256739418}{178462359}{349581267}% {597843621}{462197835}{813625974}% [DT2 tough 105 solution] \renewcommand*{\puzzlefile}{tt110.ans} \writepuzzle% {379412586}{648539217}{125687349}% {936825174}{214763958}{857194632}% {492358761}{581276493}{763941825}% [DT2 tough 110 solution] \vfill \noindent\begin{minipage}{0.47\linewidth}\begin{center} TT105 (tough solution) \\ \sudoku{tt105.ans} \end{center}\end{minipage} \hfill \begin{minipage}{0.47\linewidth}\begin{center} TT110 (tough solution) \\ \sudoku{tt110.ans} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{tt115.ans} \writepuzzle% {432758196}{196243587}{758169423}% {945682371}{263571849}{871934265}% {329416758}{584397612}{617825934}% [DT2 tough 115 solution] \renewcommand*{\puzzlefile}{tt120.ans} \writepuzzle% {968215734}{143679852}{752384619}% {496523178}{537198246}{281746395}% {875961423}{314852967}{629437581}% [DT2 tough 120 solution] \vfill \noindent\begin{minipage}{0.47\linewidth}\begin{center} TT115 (tough solution) \\ \sudoku{tt115.ans} \end{center}\end{minipage} \hfill \begin{minipage}{0.47\linewidth}\begin{center} TT120 (tough solution) \\ \sudoku{tt120.ans} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{st1130.ans} \writepuzzle% {819356247}{576924813}{342817596}% {781563924}{965248371}{423179685}% {658791432}{297435168}{134682759} [Seattle Times 2005/11/30 3 star solution] \renewcommand*{\puzzlefile}{st1207.ans} \writepuzzle% {217483956}{834695712}{659172384}% {798231645}{326954178}{145768239}% {582319467}{971846523}{463527891}% [Seattle Times 2005/12/07 3 star solution] \vfill \noindent\begin{minipage}{0.47\linewidth}\begin{center} ST1130 (3 star solution) \\ \sudoku{st1130.ans} \end{center}\end{minipage} \hfill \begin{minipage}{0.47\linewidth}\begin{center} ST1207 (3 star solution) \\ \sudoku{st1207.ans} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{st1209.ans} \writepuzzle% {839652147}{246781359}{751943268}% {167295483}{592438716}{483167925}% {628319574}{374526891}{915874632}% [Seattle Times 2005/12/09 5 star solution] \renewcommand*{\puzzlefile}{st1221.ans} \writepuzzle% {517863924}{436925178}{298417563}% {174389652}{683251749}{952674381}% {745132896}{369548217}{821796435}% [Seattle Times 2005/12/21 3 star solution] \vfill \noindent\begin{minipage}{0.47\linewidth}\begin{center} ST1209 (5 star solution) \\ \sudoku{st1209.ans} \end{center}\end{minipage} \hfill \begin{minipage}{0.47\linewidth}\begin{center} ST1221 (3 star solution) \\ \sudoku{st1221.ans} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{st1228.ans} \writepuzzle% {673189524}{812654379}{594273186}% {265791843}{341865792}{987342651}% {795416238}{138927465}{426538917}% [Seattle Times 2005/12/28 3 star solution] \renewcommand*{\puzzlefile}{st0126.ans} \writepuzzle% {253698471}{197435286}{864127953}% {416573829}{785912634}{329864517}% {972356148}{638241795}{541789362}% [Seattle Times 2006/01/26 4 star solution] \vfill \noindent\begin{minipage}{0.47\linewidth}\begin{center} ST1228 (3 star solution) \\ \sudoku{st1228.ans} \end{center}\end{minipage} \hfill \begin{minipage}{0.47\linewidth}\begin{center} ST0126 (4 star solution) \\ \sudoku{st0126.ans} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{st0127.ans} \writepuzzle% {253816479}{467395812}{918427536}% {641752398}{892163745}{375948621}% {189534267}{736289154}{524671983}% [Seattle Times 2006/01/27 5 star solution] \renewcommand*{\puzzlefile}{st0204.ans} \writepuzzle% {153427896}{742986513}{869513247}% {375142968}{428369751}{916875432}% {597321684}{681754329}{234698175}% [Seattle Times 2006/02/04 6 star solution] \vfill \noindent\begin{minipage}{0.47\linewidth}\begin{center} ST0127 (5 star solution) \\ \sudoku{st0127.ans} \end{center}\end{minipage} \hfill \begin{minipage}{0.47\linewidth}\begin{center} ST0204 (6 star solution) \\ \sudoku{st0204.ans} \end{center}\end{minipage} \renewcommand*{\puzzlefile}{st0208.ans} \writepuzzle% {213985647}{589674213}{647213859}% {928751364}{361429578}{754836192}% {875192436}{432567981}{196348725}% [Seattle Times 2005/02/08 3 star solution] \renewcommand*{\puzzlefile}{st0209.ans} \writepuzzle% {639587421}{752341698}{841296753}% {584769312}{976123584}{123458976}% {297834165}{318675249}{465912837}% [Seattle Times 2005/02/09 4 star solution] \vfill \noindent\begin{minipage}{0.47\linewidth}\begin{center} ST0208 (3 star solution) \\ \sudoku{st0208.ans} \end{center}\end{minipage} \hfill \begin{minipage}{0.47\linewidth}\begin{center} ST0209 (4 star solution) \\ \sudoku{st0209.ans} \end{center}\end{minipage} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bibliography \cleardoublepage \bibliographystyle{alpha} \begingroup \raggedright \begin{thebibliography}{GMSN94A} \bibitem[Mep05]{DT2} Michael Mepham. \emph{The Daily Telegraph Sudoku 2}. \newblock Pan Books, 2005. \newblock ISBN 0-330-44203-3. \bibitem[Wil06]{SUDOKUBUNDLE} Peter Wilson. \emph{The sudoku bundle for displaying, solving and generating Sudoku puzzles}. \newblock February 2006. \newblock (Available from CTAN in \url{macros/latex/contrib/sudokubundle}). \bibitem[SOL]{SOL} \emph{Sudoku Online: Home of the Sudokulist}. \newblock \url{http://www.sudoku.org.uk} \bibitem[SSBL]{SSBL} \emph{Sudoku Solver ... by logic}. \newblock \url{http://www.sudokusolver.co.uk} \end{thebibliography} \endgroup \end{document} % % \end{macrocode} % % \Finale % % \endinput %% \CharacterTable %% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z %% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z %% Digits \0\1\2\3\4\5\6\7\8\9 %% Exclamation \! Double quote \" Hash (number) \# %% Dollar \$ Percent \% Ampersand \& %% Acute accent \' Left paren \( Right paren \) %% Asterisk \* Plus \+ Comma \, %% Minus \- Point \. Solidus \/ %% Colon \: Semicolon \; Less than \< %% Equals \= Greater than \> Question mark \? %% Commercial at \@ Left bracket \[ Backslash \\ %% Right bracket \] Circumflex \^ Underscore \_ %% Grave accent \` Left brace \{ Vertical bar \| %% Right brace \} Tilde \~}