  
  [1m[4m[31m6. Examples of Applications based on [22m[32mNCurses.BrowseGeneric[1m[4m[31m[0m
  
  This  chapter  introduces  the  operation  [1m[34mBrowse[0m  ([1m6.1-1[0m) and lists several
  examples  how the function [1m[34mNCurses.BrowseGeneric[0m ([1m4.3-1[0m) can be utilized for
  rendering  [1mGAP[0m related data or for playing games. Each section describes the
  relevant  [1mGAP[0m  functions  and  briefly sketches the technical aspects of the
  implementation; more details can be found in the [1mGAP[0m files.
  
  Only  Section  [1m6.3[0m  describes  a  standard  application  in the sense of the
  introduction  to  Chapter  [1m4.[0m, perhaps except for a special function that is
  needed  to compare table entries. The other examples in this chapter require
  some of the programming described in Chapter [1m5.[0m.
  
  
  [1m[4m[31m6.1 The Operation [22m[32mBrowse[1m[4m[31m[0m
  
  [1m[4m[31m6.1-1 Browse[0m
  
  [1m[34m> Browse( [0m[22m[34mobj[, arec][0m[1m[34m ) ___________________________________________[0moperation
  
  This operation displays the [1mGAP[0m object [22m[34mobj[0m in a nice, formatted way, similar
  to the operation [1m[34mDisplay[0m ([1mReference: Display[0m). The difference is that [22m[32mBrowse[0m
  is intended to use [22m[32mncurses[0m facilities.
  
  Currently  there  are  methods for character tables (see[1m[34mBrowse[0m ([1m6.2-1[0m)) and
  for tables of marks (see[1m[34mBrowse[0m ([1m6.3-1[0m)).
  
  
  [1m[4m[31m6.2 Character Table Display[0m
  
  The [1mGAP[0m library provides a [1m[34mDisplay[0m ([1mReference: Display[0m) method for character
  tables  that  breaks  the  table  into columns fitting on the screen. [1mBrowse[0m
  provides  an  alternative,  using  the  standard  facilities of the function
  [1m[34mNCurses.BrowseGeneric[0m  ([1m4.3-1[0m),  i.e.,  one  can  scroll  in  the matrix of
  character values, searching and sorting are provided etc.
  
  The [22m[32mBrowse[0m method for character tables can be called instead of [22m[32mDisplay[0m. For
  convenience,  one  can  additionally  make this function the default [22m[32mDisplay[0m
  method for character tables, by assigning it to the [22m[32mDisplay[0m component in the
  global  record  [22m[32mCharacterTableDisplayDefaults.User[0m, see[1m`Reference: Printing
  Character  Tables'[0m;  for  example,  one  can  do  this in one's [1m.gaprc[0m file,
  see[1m`Reference:  The  .gaprc  file'[0m.  (This  can  be undone by unbinding the
  component [22m[32mCharacterTableDisplayDefaults.User.Display[0m.)
  
  [1m[4m[31m6.2-1 Browse[0m
  
  [1m[34m> Browse( [0m[22m[34mtbl[, options][0m[1m[34m ) ___________________________________________[0mmethod
  
  This  method  displays  the  character  table  [22m[34mtbl[0m in a window. The optional
  record  [22m[34moptions[0m  describes what shall be displayed, the supported components
  and  the  default  values  are  described  in[1m`Reference: Printing Character
  Tables'[0m.
  
  The  full  functionality  of  the  function [1m[34mNCurses.BrowseGeneric[0m ([1m4.3-1[0m) is
  available.
  
  [22m[35m---------------------------  Example  ----------------------------[0m
    [22m[35mgap> BrowseData.SetReplay( Concatenation([0m
    [22m[35m>         # scroll in the table[0m
    [22m[35m>         "DRULdddddrrrrrlluu",[0m
    [22m[35m>         # select an entry and move it around[0m
    [22m[35m>         "seddrruuuddlll",[0m
    [22m[35m>         # search for the pattern 135 (six times)[0m
    [22m[35m>         "/135", [ NCurses.keys.ENTER ], "nnnnn",[0m
    [22m[35m>         # deselect the entry, select the first column[0m
    [22m[35m>         "qLsc",[0m
    [22m[35m>         # sort and categorize by this column[0m
    [22m[35m>         "sc",[0m
    [22m[35m>         # select the first row, move down the selection[0m
    [22m[35m>         "srdddd",[0m
    [22m[35m>         # expand the selected category, scroll the selection down[0m
    [22m[35m>         "xd",[0m
    [22m[35m>         # and quit the application[0m
    [22m[35m>         "Q" ) );[0m
    [22m[35mgap> Browse( CharacterTable( "HN" ) );[0m
    [22m[35mgap> BrowseData.SetReplay( false );[0m
  [22m[35m------------------------------------------------------------------[0m
  
  [22m[36mImplementation  remarks[0m: The first part of the code in the [22m[32mBrowse[0m method for
  character  tables  is almost identical with the code for extracting the data
  to   be   displayed  from  the  input  data  in  the  [1mGAP[0m  library  function
  [22m[32mCharacterTableDisplayDefault[0m.  The  second part of the code transforms these
  data  into  a  browse  table.  Character names and (if applicable) indicator
  values are used as row labels, and centralizer orders, power maps, and class
  names  are used as column labels. The identifier of the table is used as the
  static  header.  When an irrational entry is selected, a description of this
  entry is shown in the dynamic footer.
  
  Due  to  an extension of the standard modes in [1m[34mBrowseData[0m ([1m5.4-1[0m) by two new
  actions,  a  pager  can  be  opened  that  gives  an  overview  of  all  all
  irrationalities  in  the table, and an overview of all those irrationalities
  that  have  been  shown on the screen in the current call, respectively. The
  corresponding  user  inputs  are the [1m[46mI[0m and the [1m[46mi[0m key. (The names assigned to
  the  irrationalities  are generated column-wise. If one just scrolls through
  the  table,  without  jumping,  then  these  names  coincide  with the names
  generated  by  the  defaults [22m[32mDisplay[0m method for character tables; this is in
  general  [22m[36mnot[0m  the  case  for  example when a row-wise search in the table is
  performed.)
  
  In  order  to keep the required space small also for large character tables,
  caching  of  formatted  matrix  entries  is  disabled, and the strings to be
  displayed  are computed on demand with a [22m[32mMain[0m function in the [22m[32mwork[0m component
  of  the  browse  table. For the same reason, the constant height one for all
  table  rows  is set in advance, so one need not inspect a whole character if
  only a few values of it shall be shown.
  
  Special  functions  are  provided  for sorting (concerning the comparison of
  character values, which can be integers or irrationalities) and categorizing
  the table by a column (the value in the category row involves the class name
  of the column in question).
  
  The code can be found in the file [1mlib/ctbldisp.g[0m of the package.
  
  
  [1m[4m[31m6.3 Table of Marks Display[0m
  
  The  [1mGAP[0m  library  provides a [22m[32mDisplay[0m method for tables of marks that breaks
  the  table into columns fitting on the screen. Similar to the situation with
  character  tables,  see Section[1m6.2[0m, but with a much simpler implementation,
  [1mBrowse[0m  provides  an alternative based on the function [1m[34mNCurses.BrowseGeneric[0m
  ([1m4.3-1[0m).
  
  [22m[32mBrowse[0m can be called instead of [22m[32mDisplay[0m for tables of marks, cf.[1m`Reference:
  Printing Tables of Marks'[0m.
  
  [1m[4m[31m6.3-1 Browse[0m
  
  [1m[34m> Browse( [0m[22m[34mtom[, options][0m[1m[34m ) ___________________________________________[0mmethod
  
  This method displays the table of marks [22m[34mtom[0m in a window. The optional record
  [22m[34moptions[0m  describes what shall be displayed, the supported components and the
  default values are described in[1m`Reference: Printing Tables of Marks'[0m.
  
  The  full  functionality  of  the  function [1m[34mNCurses.BrowseGeneric[0m ([1m4.3-1[0m) is
  available.
  
  [22m[35m---------------------------  Example  ----------------------------[0m
    [22m[35mgap> BrowseData.SetReplay( Concatenation([0m
    [22m[35m>         # scroll in the table[0m
    [22m[35m>         "DDRRR",[0m
    [22m[35m>         # search for the (exact) value 100 (three times)[0m
    [22m[35m>         "/100",[0m
    [22m[35m>         [ NCurses.keys.DOWN, NCurses.keys.DOWN, NCurses.keys.RIGHT ],[0m
    [22m[35m>         [ NCurses.keys.DOWN, NCurses.keys.DOWN, NCurses.keys.DOWN ],[0m
    [22m[35m>         [ NCurses.keys.RIGHT, NCurses.keys.ENTER ], "nn",[0m
    [22m[35m>         # no more occurrences of 100, confirm[0m
    [22m[35m>         [ NCurses.keys.ENTER ],[0m
    [22m[35m>         # and quit the application[0m
    [22m[35m>         "Q" ) );[0m
    [22m[35mgap> Browse( TableOfMarks( "A10" ) );[0m
    [22m[35mgap> BrowseData.SetReplay( false );[0m
  [22m[35m------------------------------------------------------------------[0m
  
  [22m[36mImplementation remarks[0m: Rows and columns are indexed by their positions. The
  identifier of the table is used as the static header, there is no footer.
  
  In  order  to  keep the required space small also for large tables of marks,
  caching  of  formatted  matrix  entries  is  disabled, and the strings to be
  displayed  are computed on demand with a [22m[32mMain[0m function in the [22m[32mwork[0m component
  of  the  browse  table. For the same reason, the constant height one for the
  table  rows is set in advance. (For example, the table of marks of the group
  with  identifier  [22m[32m"O8+(2)"[0m,  with  11171 rows and columns, can be shown with
  [22m[32mBrowse[0m in a [1mGAP[0m session requiring about 100 MB.)
  
  The code can be found in the file [1mlib/tomdisp.g[0m of the package.
  
  
  [1m[4m[31m6.4 Table of Contents of [1mAtlasRep[1m[4m[31m[0m
  
  The  [1mGAP[0m  package  [1mAtlasRep[0m  (see[WP+04])  is an interface to a database of
  representations and related data. The table of contents of this database can
  be  displayed via the function [1m[34mDisplayAtlasInfo[0m ([1mAtlasRep: DisplayAtlasInfo[0m)
  of  this  package.  The  [1mBrowse[0m package provides an alternative based on the
  function  [1m[34mNCurses.BrowseGeneric[0m  ([1m4.3-1[0m);  one can scroll, search, and fetch
  representations for later use.
  
  [1m[4m[31m6.4-1 BrowseAtlasInfo[0m
  
  [1m[34m> BrowseAtlasInfo( [0m[22m[34m[0m[1m[34m ) ______________________________________________[0mfunction
  [1mReturns:[0m  the list of "clicked" representations.
  
  This  function  shows the table of contents of the [1mGAP[0m package [1mAtlasRep[0m in a
  browse table, cf. Section[1m`AtlasRep: Accessing Data of the AtlasRep Package'[0m
  in the package manual. When one "clicks" on one of the table rows or entries
  then  a  browse  table with an overview of the available representations for
  this  group  is  shown,  and  "clicking"  on  one  of  its  rows  adds  this
  representation to the list of return values of [22m[32mBrowseAtlasInfo[0m.
  
  The  full  functionality  of  the  function [1m[34mNCurses.BrowseGeneric[0m ([1m4.3-1[0m) is
  available.
  
  The  following  example  shows  how  [22m[32mBrowseAtlasInfo[0m  can  be  used to fetch
  permutation representations of the alternating groups A_5 and A_6: We search
  for  the  group  name  [22m[32m"A5"[0m in the overview table, and the first cell in the
  table  row  for  A_5  becomes  selected;  hitting the [1m[46mEnter[0m key causes a new
  window  to  be opened, with an overview of the available representations for
  A_5;  moving  down  by  one  row  and hitting the [1m[46mEnter[0m key again causes the
  second  representation  to be added to the result list, the second window is
  closed,  and  we  are back in the overview table; we move the selection down
  twice  (to  the  row for the group A_6), and choose the first representation
  for this group; finally we leave the table, and the return value is the list
  with the data for the two representations.
  
  [22m[35m---------------------------  Example  ----------------------------[0m
    [22m[35mgap> d:= [ NCurses.keys.DOWN ];;  r:= [ NCurses.keys.RIGHT ];;[0m
    [22m[35mgap> c:= [ NCurses.keys.ENTER ];;[0m
    [22m[35mgap> BrowseData.SetReplay( Concatenation([0m
    [22m[35m>        "/A5",         # Find the string A5 ...[0m
    [22m[35m>        d, d, r,       # ... such that just the word matches,[0m
    [22m[35m>        c,             # start the search,[0m
    [22m[35m>        c,             # click the table entry A5,[0m
    [22m[35m>        d,             # move down by one row,[0m
    [22m[35m>        c,             # click the row for this representation,[0m
    [22m[35m>        d, d,          # move down by two rows,[0m
    [22m[35m>        c,             # click the table entry A6,[0m
    [22m[35m>        c,             # click the first row,[0m
    [22m[35m>        "Q" ) );       # and quit the application.[0m
    [22m[35mgap> tworeps:= BrowseAtlasInfo();;[0m
    [22m[35mgap> BrowseData.SetReplay( false );[0m
    [22m[35mgap> if fail in tworeps then[0m
    [22m[35m>      Print( "no access to the Web ATLAS\n" );[0m
    [22m[35m>    else[0m
    [22m[35m>      Print( List( tworeps, x -> x.identifier[1] ), "\n" );[0m
    [22m[35m>    fi;[0m
    [22m[35m[ "A5", "A6" ][0m
  [22m[35m------------------------------------------------------------------[0m
  
  [22m[36mImplementation remarks[0m: The first browse table shown has a static header, no
  footer  and row labels, one row of column labels describing the type of data
  summarized in the columns. When a row is selected, the "click" functionality
  opens  a  new  window  (via  a  second  level  call to [1m[34mNCurses.BrowseGeneric[0m
  ([1m4.3-1[0m)), in which a browse table with the list of available representations
  for  the  given group is shown; in this table, "click" results in adding the
  selected  representation  to  the  result list, and leaving the second level
  table,  So  one  returns  to  the  first browse table and can choose further
  representations,  perhaps  of  other  groups.  When the first level table is
  left, the list of chosen representations is returned.
  
  This function is available only if the [1mGAP[0m package [1mAtlasRep[0m is available.
  
  The code can be found in the file [1mlib/atlasbrowse.g[0m of the package.
  
  
  [1m[4m[31m6.5 Access to [1mGAP[1m[4m[31m Manuals -- a Variant[0m
  
  A  [1mBrowse[0m  adapted way to access several manuals is to show the hierarchy of
  books, chapters, sections, and subsections as collapsible category rows, and
  to  regard  the  contents  of each subsection as a data row of a matrix with
  only one column.
  
  This  application  is  mainly  intended  as an example with table cells that
  exceed the screen, and as an example with several category levels.
  
  [1m[4m[31m6.5-1 BrowseGapManuals[0m
  
  [1m[34m> BrowseGapManuals( [0m[22m[34m[start][0m[1m[34m ) ______________________________________[0mfunction
  
  This function displays the contents of the [1mGAP[0m manuals (the main [1mGAP[0m manuals
  as  well  as  the loaded package manuals) in a window. The optional argument
  [22m[34mstart[0m  describes  the  initial  status,  admissible  values  are the strings
  [22m[32m"inline/collapsed"[0m,      [22m[32m"inline/expanded"[0m,      [22m[32m"pager/collapsed"[0m,      and
  [22m[32m"pager/expanded"[0m.
  
  In the [22m[32minline[0m cases, the parts of the manuals are shown in the browse table,
  and  in  the  [22m[32mpager[0m  case, the parts of the manuals are shown in a different
  window  when they are "clicked", using the user's favourite help viewer, see
  [1m`Reference: Changing the Help Viewer'[0m.
  
  In the [22m[32mcollapsed[0m case, all category rows are collapsed, and the first row is
  selected;  typical  next  steps  are moving down the selection and expanding
  single  category rows. In the [22m[32mexpanded[0m case, all category rows are expanded,
  and  nothing is selected; a typical next step in the [22m[32minline/expanded[0m case is
  a  search  for  a string in the manuals. (Note that searching in quite slow:
  For  viewing  a part of a manual, the file with the corresponding section is
  read  into [1mGAP[0m, the text is formatted, the relevant part is cut out from the
  section, perhaps markup is stripped off, and finally the search is performed
  in the resulting strings.)
  
  If  no  argument  is  given  then the user is asked for selecting an initial
  status, using [1m[34mNCurses.Select[0m ([1m3.1-2[0m).
  
  The  full  functionality  of  the  function [1m[34mNCurses.BrowseGeneric[0m ([1m4.3-1[0m) is
  available.
  
  [22m[35m---------------------------  Example  ----------------------------[0m
    [22m[35mgap> BrowseData.SetReplay( "xdxdzzzQ" );  # expand a Tutorial section[0m
    [22m[35mgap> BrowseGapManuals( "inline/collapsed" );[0m
    [22m[35mgap> BrowseData.SetReplay( Concatenation([0m
    [22m[35m>        "/Browse", [ NCurses.keys.ENTER ],  # search for "Browse"[0m
    [22m[35m>        "xdxddxdzzz",                       # expand a section[0m
    [22m[35m>        "Q" ) );                            # and quit[0m
    [22m[35mgap> BrowseGapManuals( "inline/collapsed" );[0m
    [22m[35mgap> BrowseData.SetReplay( false );[0m
  [22m[35m------------------------------------------------------------------[0m
  
  [22m[36mImplementation  remarks[0m:  The  browse table has a dynamic header showing the
  name  of  the currently selected manual, no footer, no row or column labels,
  and  exactly  one  column  of  fixed  width  equal  to the screen width. The
  category rows are precomputed, i.e., they do not arise from a table column;
  this  way, the contents of each data cell can be computed on demand, as soon
  as  it  is  shown  on  the  screen,  in particular the category hierarchy is
  computed  without  reading the manuals into [1mGAP[0m. Also, the data rows are not
  cached.  There is no return value. The heights of many cells are bigger than
  the  screen  height, so scrolling is a mixture of scrolling to the next cell
  and  scrolling  inside a cell. The different initial states are realized via
  executing different initial steps before the table is shown to the user.
  
  For  the  variants  that  show  the manuals in a pager, the code temporarily
  replaces  the  [22m[32mshow[0m function of the default viewer [22m[32m"screen"[0m (see [1m`Reference:
  Changing  the  Help  Viewer'[0m) by a function that uses [1m[34mNCurses.Pager[0m ([1m3.1-4[0m).
  Note  that in the case that the manual bit in question fits into one screen,
  the  default [22m[32mshow[0m function writes this text directly to the screen, but this
  is used already by the browse table.
  
  The implementation should be regarded as a sketch.
  
  For  example, the markup available in the text file format of [1mGAPDoc[0m manuals
  (using  [1m[46mEsc[0m  sequences)  is stripped off instead of being transferred to the
  attribute lines that arise, because of the highlighting problem mentioned in
  Section[1m2.2-3[0m.
  
  Some  heuristics  used  in  the  code  are due to deficiencies of the manual
  formats.
  
  For  the  inline  variant  of  the  browse  table,  the  titles of chapters,
  sections, and subsections are [22m[36mnot[0m regarded as parts of the actual text since
  they appear already as category rows; however, the functions of the [1mGAP[0m help
  system  deliver  the text [22m[36mtogether with[0m these titles, so these lines must be
  stripped off afterwards.
  
  The  category  hierarchy representing the tables of contents is created from
  the  [1mmanual.six[0m  files  of  the  manuals.  These files do not contain enough
  information  for  determining  whether  several  functions  define  the same
  subsection,  in  the  sense  that there is a common description text after a
  series  of  manual lines introducing different functions. In such cases, the
  browse  table  contains a category row for each of these functions (with its
  own number), but the corresponding text appears only under the [22m[36mlast[0m of these
  category  rows,  the  data rows for the others are empty. (This problem does
  not  occur  in  the  [1mGAPDoc[0m  manual  format because this introduces explicit
  subsection   titles,   involving   only   the   [22m[36mfirst[0m  of  several  function
  definitions.)
  
  Also, index entries and sectioning entries in [1mmanual.six[0m files of manuals in
  [1mGAPDoc[0m format are not explicitly distinguished.
  
  The code can be found in the file [1mlib/manual.g[0m of the package.
  
  
  [1m[4m[31m6.6 Overview of the [1mGAP[1m[4m[31m Bibliography[0m
  
  The  [1mGAP[0m  documentation contains a bibliography of [1mGAP[0m related publications,
  see[xxx].  [1mBrowse[0m  provides  access  to  this information in [1mGAP[0m, using the
  standard  facilities  of  the function [1m[34mNCurses.BrowseGeneric[0m ([1m4.3-1[0m), i.e.,
  one  can  scroll  in  the  list,  search for entries, sort by year, sort and
  categorize by authors etc.
  
  The   [1mBrowse[0m   package   contains  a  (perhaps  outdated)  version  of  this
  bibliography. One can get an updated version as follows.
  
  [22m[32mwget -N http://www.gap-system.org/Doc/Bib/gap-publishednicer.bib[0m
  
  [1m[4m[31m6.6-1 BrowseBibliography[0m
  
  [1m[34m> BrowseBibliography( [0m[22m[34m[bibfiles][0m[1m[34m ) _________________________________[0mfunction
  [1mReturns:[0m  a list of strings representing BibTeX entries.
  
  This  function  shows  the  list of BibTeX entries in the files given by the
  strings  in  the  list  [22m[34mbibfiles[0m.  If  no  argument  is  given then the file
  [1mbibl/gap-publishednicer.bib[0m  in  the  [1mBrowse[0m package directory is taken. The
  return  value is a list of strings that contain the BibTeX entries that have
  been "clicked" in visual mode.
  
  The  full  functionality  of  the  function [1m[34mNCurses.BrowseGeneric[0m ([1m4.3-1[0m) is
  available.
  
  [22m[35m---------------------------  Example  ----------------------------[0m
    [22m[35mgap> # sort and categorize by year, scroll down, expand a category row[0m
    [22m[35mgap> BrowseData.SetReplay( "scrrscsedddddxdddddQ" );[0m
    [22m[35mgap> BrowseBibliography();;[0m
    [22m[35mgap> # sort & categorize by authors, expand all category rows, scroll down[0m
    [22m[35mgap> BrowseData.SetReplay( "scscXseddddddQ" );[0m
    [22m[35mgap> BrowseBibliography();;[0m
    [22m[35mgap> # sort and categorize by journal, search for a journal name, expand[0m
    [22m[35mgap> BrowseData.SetReplay( Concatenation( "scrrrsc/J. Algebra",[0m
    [22m[35m>        [ NCurses.keys.ENTER ], "nxdddQ" ) );[0m
    [22m[35mgap> BrowseBibliography();;[0m
    [22m[35mgap> BrowseData.SetReplay( false );[0m
  [22m[35m------------------------------------------------------------------[0m
  
  [22m[36mImplementation  remarks[0m: The browse table has a static header, no footer and
  row  labels,  one  row  of column labels is given by the descriptions of the
  table  columns (authors, title, year, journal). For categorizing by authors,
  a  special  [22m[32mCategoryValues[0m function is provided that distributes the authors
  to  different  category  rows, such that each entry appears once for each of
  its  authors  in  the categorized table. When a data row or an entry in this
  row  is  selected, "click" adds the corresponding BibTeX entry to the result
  list.  The  width of the title column is preset, in order to avoid computing
  all values in advance; note that the contents of this column is formatted as
  a paragraph, using the function [22m[32mFormatParagraph[0m.
  
  For  three  columns,  the  sort  parameters  are  customized as follows: The
  authors  column  does  not  become  hidden  when  the  table  is categorized
  according to this column, sorting by year yields a descending order, and the
  category  rows  arising  from the three columns show the numbers of the data
  rows that belong to them.
  
  This  function  requires  some  of the utilities provided by the [1mGAP[0m package
  [1mGAPDoc[0m   (see[LN06]),   such   as   [22m[32mFormatParagraph[0m,  [22m[32mNormalizedWhitespace[0m,
  [22m[32mNormalizeNameAndKey[0m, [22m[32mParseBibFiles[0m, and [22m[32mPrintBibAsBib[0m.
  
  The code can be found in the file [1mlib/gapbibl.g[0m of the package.
  
  
  [1m[4m[31m6.7 A Puzzle[0m
  
  We  consider  an m by n rectangle of squares numbered from 1 to m n - 1, the
  bottom  right  square  is  left  empty. The numbered squares are permuted by
  successively  exchanging the empty square and a neighboring square such that
  in the end, the empty cell is again in the bottom right corner.
  
     -----------------------
      | 7  | 13 | 14 | 2  | 
     -----------------------
      | 1  | 4  | 15 | 11 | 
     -----------------------
      | 6  | 8  | 3  | 9  | 
     -----------------------
      | 10 | 5  | 12 |    | 
     -----------------------
  
  The aim of the game is to order the numbered squares via these moves.
  
  For  the  case  m  =  n  = 4, the puzzle is known under the name "Sam Loyd's
  Fifteen", see[B] and[OR] for more information and references.
  
  [1m[4m[31m6.7-1 BrowsePuzzle[0m
  
  [1m[34m> BrowsePuzzle( [0m[22m[34m[m, n[, pi]][0m[1m[34m ) _____________________________________[0mfunction
  [1mReturns:[0m  a record describing the initial and final status of the puzzle.
  
  This function shows the rectangle in a window.
  
  The  arguments  [22m[34mm[0m and [22m[34mn[0m are the dimensions of the rectangle, the default for
  both values is 4. The initial distribution of the numbers in the squares can
  be  prescribed  via a permutation [22m[34mpi[0m, the default is a random element in the
  alternating  group on the points 1, 2, ..., [22m[34mm[0m [22m[34mn[0m - 1. (Note that the game has
  not always a solution.)
  
  In  any  case, the empty cell is selected, and the selection can be moved to
  neighboring cells via the arrow keys.
  
  The  return  value  is a record with the components [22m[32mdim[0m (the pair [22m[32m[ m, n ][0m),
  [22m[32minit[0m  (the  initial  permutation),  [22m[32mfinal[0m (the final permutation), and [22m[32msteps[0m
  (the number of steps that were needed).
  
  [22m[35m---------------------------  Example  ----------------------------[0m
    [22m[35mgap> BrowseData.SetReplay( Concatenation([0m
    [22m[35m>        BrowsePuzzleSolution.steps, "Q" ) );[0m
    [22m[35mgap> BrowsePuzzle( 4, 4, BrowsePuzzleSolution.init );;[0m
    [22m[35mgap> BrowseData.SetReplay( false );[0m
  [22m[35m------------------------------------------------------------------[0m
  
  An  implementation using mouse clicks instead of key strokes is available in
  the [1mGAP[0m package [1mXGAP[0m (see[CN04]).
  
  [22m[36mImplementation  remarks[0m:  The  game board is implemented via a browse table,
  without  row  and  column  labels,  with  static header, dynamic footer, and
  individual  [22m[32mminyx[0m  function.  Only  one  mode is needed in which one cell is
  selected,  and  besides  the standard actions for quitting the table, asking
  for  help,  and  saving the current window contents, only the four moves via
  the arrow keys are admissible.
  
  Some   standard   [1m[34mNCurses.BrowseGeneric[0m   ([1m4.3-1[0m)   functionality,  such  as
  scrolling, selecting, and searching, are not available in this application.
  
  The code can be found in the file [1mlib/puzzle.g[0m of the package.
  
  
  [1m[4m[31m6.8 Peg Solitaire[0m
  
  Peg  solitaire  is  a  board game for one player. The game board consists of
  several  holes some of which contain pegs. In each step of the game, one peg
  is  moved  horizontally  or  vertically to an empty hole at distance two, by
  jumping over a neighboring peg which is then removed from the board. 
                -------------
                | o | o | o |
                -------------
                | o | o | o |
        -----------------------------
        | o | o | o | o | o | o | o |
        -----------------------------
        | o | o | o |   | o | o | o |
        -----------------------------
        | o | o | o | o | o | o | o |
        -----------------------------
                | o | o | o |
                -------------
                | o | o | o |
                -------------
  
  
  We  consider  the game that in the beginning, exactly one hole is empty, and
  in the end, exactly one peg is left.
  
  [1m[4m[31m6.8-1 PegSolitaire[0m
  
  [1m[34m> PegSolitaire( [0m[22m[34m[format][,][nrholes][,][twoModes][0m[1m[34m ) ________________[0mfunction
  
  This function shows the game board in a window.
  
  If  the  argument [22m[34mformat[0m is one of the strings [22m[32m"small"[0m or [22m[32m"large"[0m then small
  or large pegs are shown, the default is [22m[32m"small"[0m.
  
  Three  shapes  of  the  game board are supported, with 33, 37, and 45 holes,
  respectively;  this  number  can  be specified via the argument [22m[34mnrholes[0m, the
  default  is  33.  In  the cases of 33 and 45 holes, the position of both the
  initial  hole  and  the  destination  of  the  final peg is the middle cell,
  whereas  in  the  case  of  37  holes,  the  initial hole is in the top left
  position and the final peg has to be placed in the bottom right position.
  
  If a Boolean [22m[34mtwoModes[0m is entered as an argument then it determines whether a
  browse  table  with  one  or  two  modes is used; the default [22m[32mfalse[0m yields a
  browse table with only one mode.
  
  In  any  case,  one  cell of the board is selected, and the selection can be
  moved  to  neighboring  cells via the arrow keys. A peg in the selected cell
  jumps  over  a neighboring peg to an adjacent hole via the [22m[32mj[0m key followed by
  the appropriate arrow key.
  
  [22m[35m---------------------------  Example  ----------------------------[0m
    [22m[35mgap> for n in [ 33, 37, 45 ] do[0m
    [22m[35m>      BrowseData.SetReplay( Concatenation([0m
    [22m[35m>          PegSolitaireSolutions.( String( n ) ), "Q" ) );[0m
    [22m[35m>      PegSolitaire( n );[0m
    [22m[35m> od;[0m
    [22m[35mgap> BrowseData.SetReplay( false );[0m
  [22m[35m------------------------------------------------------------------[0m
  
  For more information such as variations of the game and references, see[K].
  Also  the  solutions  stored in the variable [22m[32mPegSolitaireSolutions[0m have been
  taken from this web page.
  
  [22m[36mImplementation  remarks[0m:  The  game board is implemented via a browse table,
  without  row  and  column  labels,  with  static header, dynamic footer, and
  individual  [22m[32mminyx[0m  function.  In fact, two implementations are provided. The
  first  one  needs  only  one  mode in which one cell is selected; moving the
  selection  and  jumping with the peg in the selected cell in one of the four
  directions  are  the supported user actions. The second implementation needs
  two modes, one for moving the selection and one for jumping.
  
  Some   standard   [1m[34mNCurses.BrowseGeneric[0m   ([1m4.3-1[0m)   functionality,  such  as
  scrolling, selecting, and searching, are not available in this application.
  
  The code can be found in the file [1mlib/solitair.g[0m of the package.
  
  
  [1m[4m[31m6.9 Rubik's Cube[0m
  
  We  visualize  the  transformations of Rubik's magic cube in a model that is
  given by "unfolding" the faces and numbering them as follows. 
                     +--------------+
                     |  1    2    3 |
                     |  4   top   5 |
                     |  6    7    8 |
      +--------------+--------------+--------------+--------------+
      |  9   10   11 | 17   18   19 | 25   26   27 | 33   34   35 |
      | 12  left  13 | 20 front  21 | 28 right  29 | 36  back  37 |
      | 14   15   16 | 22   23   24 | 30   31   32 | 38   39   40 |
      +--------------+--------------+--------------+--------------+
                     | 41   42   43 |
                     | 44  down  45 |
                     | 46   47   48 |
                     +--------------+
  
  
  Clockwise  turns of the six layers (top, left, front, right, back, and down)
  are represented by the following permutations.
  
  [22m[35m---------------------------  Example  ----------------------------[0m
    [22m[35mgap> cubegens := [[0m
    [22m[35m>   ( 1, 3, 8, 6)( 2, 5, 7, 4)( 9,33,25,17)(10,34,26,18)(11,35,27,19),[0m
    [22m[35m>   ( 9,11,16,14)(10,13,15,12)( 1,17,41,40)( 4,20,44,37)( 6,22,46,35),[0m
    [22m[35m>   (17,19,24,22)(18,21,23,20)( 6,25,43,16)( 7,28,42,13)( 8,30,41,11),[0m
    [22m[35m>   (25,27,32,30)(26,29,31,28)( 3,38,43,19)( 5,36,45,21)( 8,33,48,24),[0m
    [22m[35m>   (33,35,40,38)(34,37,39,36)( 3, 9,46,32)( 2,12,47,29)( 1,14,48,27),[0m
    [22m[35m>   (41,43,48,46)(42,45,47,44)(14,22,30,38)(15,23,31,39)(16,24,32,40)[0m
    [22m[35m> ];;[0m
  [22m[35m------------------------------------------------------------------[0m
  
  [1mGAP[0m  computations  analyzing  this  permutation  group have been part of the
  announcements  of  [1mGAP[0m3 releases. For a [1mGAP[0m4 equivalent, see[S]. For more
  information and references (not [1mGAP[0m related) about Rubik's cube, see[K].
  
  [1m[4m[31m6.9-1 BrowseRubiksCube[0m
  
  [1m[34m> BrowseRubiksCube( [0m[22m[34m[format][,][pi][0m[1m[34m ) ______________________________[0mfunction
  
  This function shows the model of the cube in a window.
  
  If  the  argument [22m[34mformat[0m is one of the strings [22m[32m"small"[0m or [22m[32m"large"[0m then small
  or large cells are shown, the default is [22m[32m"small"[0m.
  
  The  argument  [22m[34mpi[0m  is the initial permutation of the faces, the default is a
  random permutation in the cube group, see[1m`Reference: Random'[0m.
  
  Supported  user inputs are the keys [1m[46mt[0m, [1m[46ml[0m, [1m[46mf[0m, [1m[46mr[0m, [1m[46mb[0m, and [1m[46md[0m for clockwise turns
  of   the   six   layers,   and   the   corresponding   capital  letters  for
  counter-clockwise  turns.  If the terminal supports colors, according to the
  global  variable  [1m[34mNCurses.attrs.has_colors[0m  ([1m2.2-1[0m),  the  input  [1m[46ms[0m switches
  between  a  screen that shows only the colors of the faces and a screen that
  shows the numbers; the color screen is the default.
  
  The return value is a record with the components [22m[32minputs[0m (a string describing
  the  user inputs), [22m[32minit[0m, and [22m[32mfinal[0m (the initial and final permutation of the
  faces,  respectively).  (The  [22m[32minputs[0m  component  can  be used for the replay
  feature, see the example below.)
  
  In  the  following  example,  a  word  in terms of the generators is used to
  initialize the browse table, and then the letters in this word are used as a
  series  of input steps, except that in between, the display is switched once
  from colors to numbers and back.
  
  [22m[35m---------------------------  Example  ----------------------------[0m
    [22m[35mgap> choice:= List( [ 1 .. 30 ], i -> Random( [ 1 .. 6 ] ) );;[0m
    [22m[35mgap> input:= List( "tlfrbd", INT_CHAR ){ choice };;[0m
    [22m[35mgap> BrowseData.SetReplay( Concatenation([0m
    [22m[35m>        input{ [ 1 .. 20 ] },[0m
    [22m[35m>        "s",                    # switch to number display[0m
    [22m[35m>        input{ [ 21 .. 25 ] },[0m
    [22m[35m>        "s",                    # switch to color display[0m
    [22m[35m>        input{ [ 26 .. 30 ] },[0m
    [22m[35m>        "Q" ) );;               # quit the browse table[0m
    [22m[35mgap> BrowseRubiksCube( Product( cubegens{ choice } ) );;[0m
    [22m[35mgap> BrowseData.SetReplay( false );[0m
  [22m[35m------------------------------------------------------------------[0m
  
  [22m[36mImplementation  remarks[0m: The cube is implemented via a browse table, without
  row  and  column  labels, with static header, dynamic footer, and individual
  [22m[32mminyx[0m  function.  Only  one mode is needed, and besides the standard actions
  for  quitting  the  table,  asking  for  help, and saving the current window
  contents,  only  the  twelve  moves  and the switch between color and number
  display are admissible.
  
  Switching  between  the  two  display  formats is implemented via a function
  [22m[32mwork.Main[0m, so this relies on [22m[36mnot[0m caching the formatted cells in [22m[32mwork.main[0m.
  
  Row  and  column separators of the browse table are whitespace of height and
  width  one.  The  separating lines are drawn using an individual [22m[32mSpecialGrid[0m
  function  in  the  browse  table. Note that the relevant cells do not form a
  rectangular array.
  
  Some   standard   [1m[34mNCurses.BrowseGeneric[0m   ([1m4.3-1[0m)   functionality,  such  as
  scrolling, selecting, and searching, are not available in this application.
  
  The code can be found in the file [1mlib/rubik.g[0m of the package.
  
  
  [1m[4m[31m6.10 Changing Sides[0m
  
  We  consider  a  5 by 5 board of squares filled with two types of stones, as
  follows. The square in the middle is left empty.
  
  
             ---------------------
             | x | x | x | x | x |
             ---------------------
             | o | x | x | x | x |
             ---------------------
             | o | o |   | x | x |
             ---------------------
             | o | o | o | o | x |
             ---------------------
             | o | o | o | o | o |
             ---------------------
  
  
  The aim of the game is to exchange the two types of stones via a sequence of
  single  steps  that  move one stone to the empty position on the board. Only
  those  moves  are  allowed that increase or decrease one coordinate by 2 and
  increase  or  decrease  the  other  by 1; these are the allowed moves of the
  knight in chess.
  
  This game has been part of the MacTutor system [OR00].
  
  [1m[4m[31m6.10-1 BrowseChangeSides[0m
  
  [1m[34m> BrowseChangeSides( [0m[22m[34m[0m[1m[34m ) ____________________________________________[0mfunction
  
  This function shows the game board in a window.
  
  Each  move  is  encoded  as  a  sequence  of  three arrow keys; there are 24
  admissible inputs.
  
  [22m[35m---------------------------  Example  ----------------------------[0m
    [22m[35mgap> for entry in BrowseChangeSidesSolutions do[0m
    [22m[35m>      BrowseData.SetReplay( Concatenation( entry, "Q" ) );[0m
    [22m[35m>      BrowseChangeSides();[0m
    [22m[35m> od;[0m
    [22m[35mgap> BrowseData.SetReplay( false );[0m
  [22m[35m------------------------------------------------------------------[0m
  
  [22m[36mImplementation  remarks[0m:  The  game board is implemented via a browse table,
  without  row  and  column  labels,  with  static header, dynamic footer, and
  individual [22m[32mminyx[0m function. Only one mode is needed, and besides the standard
  actions  for  quitting  the  table,  asking for help, and saving the current
  window  contents,  only  moves  via  combinations of the four arrow keys are
  admissible.
  
  The  separating  lines are drawn using an individual [22m[32mSpecialGrid[0m function in
  the browse table.
  
  Some   standard   [1m[34mNCurses.BrowseGeneric[0m   ([1m4.3-1[0m)   functionality,  such  as
  scrolling, selecting, and searching, are not available in this application.
  
  The code can be found in the file [1mlib/knight.g[0m of the package.
  
  
  [1m[4m[31m6.11 Sudoku[0m
  
  We  consider  a  9  by 9 board of squares. Some squares are initially filled
  with  numbers  from 1 to 9. The aim of the game is to fill the empty squares
  in  such  a  way  that  each row, each column, and each of the marked 3 by 3
  subsquares contains all numbers from 1 to 9. A [22m[36mproper Sudoku game[0m is defined
  as one with a unique solution. Here is an example. 
                   ------------- ------------- -------------
                   |   |   |   | |   |   |   | | 5 |   |   |
                   ------------- ------------- -------------
                   |   | 1 | 5 | | 4 |   | 6 | |   | 2 |   |
                   ------------- ------------- -------------
                   | 9 |   |   | |   | 5 |   | | 3 |   |   |
                   ------------- ------------- -------------
                   ------------- ------------- -------------
                   | 6 |   | 4 | |   |   |   | |   |   |   |
                   ------------- ------------- -------------
                   |   |   |   | | 8 |   |   | |   |   |   |
                   ------------- ------------- -------------
                   | 8 |   |   | | 9 |   |   | |   | 5 | 3 |
                   ------------- ------------- -------------
                   ------------- ------------- -------------
                   |   |   |   | |   |   | 5 | |   |   |   |
                   ------------- ------------- -------------
                   |   | 4 |   | |   |   | 7 | |   |   | 2 |
                   ------------- ------------- -------------
                   |   |   | 9 | | 1 |   |   | | 8 |   |   |
                   ------------- ------------- -------------
  
  
  The [1mBrowse[0m package contains functions to create, play and solve these games.
  There  are  basic  command line functions for this, which we describe first,
  and there is a user interface [1m[34mPlaySudoku[0m ([1m6.11-7[0m) which is implemented using
  the generic browse functionality described in Chapter [1m4.[0m.
  
  [1m[4m[31m6.11-1 Sudoku.Init[0m
  
  [1m[34m> Sudoku.Init( [0m[22m[34m[arg][0m[1m[34m ) _____________________________________________[0mfunction
  [1mReturns:[0m  A record describing a Sudoku board or [22m[32mfail[0m.
  
  This  function constructs a record describing a Sudoku game. This is used by
  the  other  functions described below. There a several possibilities for the
  argument [22m[34marg[0m.
  
  [1m[33m[22m[34marg[0m is a string[0m
        The  entries  of  a Sudoku board are numbered row-wise from 1 to 81. A
        board  is encoded as a string as follows. If one of the numbers 1 to 9
        is  in  entry  i  then the corresponding digit character is written in
        position  i  of the string. If an entry is empty any character, except
        [22m[32m'1'[0m  to  [22m[32m'9'[0m  or  [22m[32m'|'[0m is written in position i of the string. Trailing
        empty  entries  can  be  left  out.  Afterwards  [22m[32m'|'[0m-characters can be
        inserted  in  the string (for example to mark line ends). Such strings
        can be used for [22m[34marg[0m.
  
  [1m[33m[22m[34marg[0m is a matrix[0m
        A  Sudoku board can also be encoded as a 9 by 9-matrix, that is a list
        of  9 lists of length 9, whose (i,j)-th entry is the (i,j)-th entry of
        the  board  as  integer if it is not empty. Empty entries of the board
        correspond to unbound entries in the matrix.
  
  [1m[33m[22m[34marg[0m is a list of integers[0m
        Instead of the matrix just described the argument can also be given by
        the  concatenation  of  the rows of the matrix (so, a list of integers
        and holes).
  
  [22m[35m---------------------------  Example  ----------------------------[0m
    [22m[35mgap> game := Sudoku.Init(" 3   68  | 85  1 69|  97   53|      79 |\[0m
    [22m[35m>  6  47   |45  2    |89   2 1 | 4   8 7 | ");;[0m
  [22m[35m------------------------------------------------------------------[0m
  
  [1m[4m[31m6.11-2 Sudoku.Place[0m
  
  [1m[34m> Sudoku.Place( [0m[22m[34mgame, i, n[0m[1m[34m ) _______________________________________[0mfunction
  [1m[34m> Sudoku.Remove( [0m[22m[34mgame, i[0m[1m[34m ) _________________________________________[0mfunction
  [1mReturns:[0m  The changed [22m[34mgame[0m.
  
  Here  [22m[34mgame[0m is a record describing a Sudoku board, as returned by [1m[34mSudoku.Init[0m
  ([1m6.11-1[0m).  The argument [22m[34mi[0m is the number of an entry, counted row-wise from 1
  to  81,  and  [22m[34mn[0m  is  an integer from 1 to 9 to be placed on the board. These
  functions change [22m[34mgame[0m.
  
  [1m[34mSudoku.Place[0m  tries  to place number [22m[34mn[0m on entry [22m[34mi[0m. It is an error if entry [22m[34mi[0m
  is  not  empty.  The  number  is not placed if [22m[34mn[0m is already used in the row,
  column  or  subsquare of entry [22m[34mi[0m. In this case the component [22m[32mgame.impossible[0m
  is bound.
  
  [1m[34mSudoku.Remove[0m  tries to remove the number placed on position [22m[34mi[0m of the board.
  It  does  not  change the board if entry [22m[34mi[0m is empty, or if entry [22m[34mi[0m was given
  when  the  board  [22m[34mgame[0m  was  created.  In the latter case [22m[32mgame.impossible[0m is
  bound.
  
  [22m[35m---------------------------  Example  ----------------------------[0m
    [22m[35mgap> game := Sudoku.Init(" 3   68  | 85  1 69|  97   53|      79 |\[0m
    [22m[35m>  6  47   |45  2    |89   2 1 | 4   8 7 | ");;[0m
    [22m[35mgap> Sudoku.Place(game, 1, 3);; # 3 is already in first row[0m
    [22m[35mgap> IsBound(game.impossible);[0m
    [22m[35mtrue[0m
    [22m[35mgap> Sudoku.Place(game, 1, 2);; # 2 is not in row, col or subsquare[0m
    [22m[35mgap> IsBound(game.impossible); [0m
    [22m[35mfalse[0m
  [22m[35m------------------------------------------------------------------[0m
  
  [1m[4m[31m6.11-3 Sudoku.RandomGame[0m
  
  [1m[34m> Sudoku.RandomGame( [0m[22m[34m[seed][0m[1m[34m ) ______________________________________[0mfunction
  [1mReturns:[0m  A pair [22m[32m[str, seed][0m of string and seed.
  
  The  optional argument [22m[34mseed[0m, if given, must be an integer. If not given some
  random integer from the current [1mGAP[0m session is used. This function returns a
  random  proper Sudoku game, where the board is described by a string [22m[32mstr[0m, as
  explained  in  [1m[34mSudoku.Init[0m  ([1m6.11-1[0m).  With  the same [22m[34mseed[0m the same board is
  returned.
  
  The  games  computed  by this function have the property that after removing
  any given entry the puzzle does no longer have a unique solution.
  
  [22m[35m---------------------------  Example  ----------------------------[0m
    [22m[35mgap> Sudoku.RandomGame(5833750);                                           [0m
    [22m[35m[ " 1         2     43  2   68   72    8     6 2   1 9 8  8 3   \[0m
    [22m[35m9     47 3   7  18  ", 5833750 ][0m
    [22m[35mgap> last = Sudoku.RandomGame(last[2]);[0m
    [22m[35mtrue[0m
  [22m[35m------------------------------------------------------------------[0m
  
  [1m[4m[31m6.11-4 Sudoku.SimpleDisplay[0m
  
  [1m[34m> Sudoku.SimpleDisplay( [0m[22m[34mgame[0m[1m[34m ) _____________________________________[0mfunction
  
  Displays  a Sudoku board on the terminal. (But see [1m[34mPlaySudoku[0m ([1m6.11-7[0m) for a
  fancier interface.)
  
  [22m[35m---------------------------  Example  ----------------------------[0m
    [22m[35mgap> game := Sudoku.Init(" 3   68  | 85  1 69|  97   53|      79 |\[0m
    [22m[35m>  6  47   |45  2    |89   2 1 | 4   8 7 | ");;[0m
    [22m[35mgap> Sudoku.SimpleDisplay(game);                                        [0m
    [22m[35m 3 |  6|8  [0m
    [22m[35m 85|  1| 69[0m
    [22m[35m  9|7  | 53[0m
    [22m[35m-----------[0m
    [22m[35m   |   |79 [0m
    [22m[35m 6 | 47|   [0m
    [22m[35m45 | 2 |   [0m
    [22m[35m-----------[0m
    [22m[35m89 |  2| 1 [0m
    [22m[35m 4 |  8| 7 [0m
    [22m[35m   |   |   [0m
  [22m[35m------------------------------------------------------------------[0m
  
  [1m[4m[31m6.11-5 Sudoku.OneSolution[0m
  
  [1m[34m> Sudoku.OneSolution( [0m[22m[34mgame[0m[1m[34m ) _______________________________________[0mfunction
  [1mReturns:[0m  A completed Sudoku board that solves [22m[34mgame[0m, or [22m[32mfail[0m.
  
  Here  [22m[34mgame[0m must be a Sudoku board as returned by [1m[34mSudoku.Init[0m ([1m6.11-1[0m). It is
  not  necessary  that  [22m[34mgame[0m  describes  a  proper  Sudoku  game (has a unique
  solution).  It  may  have  several  solutions,  then  one random solution is
  returned. Or it may have no solution, then [22m[32mfail[0m is returned.
  
  [22m[35m---------------------------  Example  ----------------------------[0m
    [22m[35mgap> Sudoku.SimpleDisplay(Sudoku.OneSolution(Sudoku.Init("  3")));[0m
    [22m[35m493|876|251[0m
    [22m[35m861|542|739[0m
    [22m[35m527|193|648[0m
    [22m[35m-----------[0m
    [22m[35m942|618|573[0m
    [22m[35m156|739|482[0m
    [22m[35m738|425|916[0m
    [22m[35m-----------[0m
    [22m[35m289|354|167[0m
    [22m[35m375|961|824[0m
    [22m[35m614|287|395[0m
  [22m[35m------------------------------------------------------------------[0m
  
  [1m[4m[31m6.11-6 Sudoku.UniqueSolution[0m
  
  [1m[34m> Sudoku.UniqueSolution( [0m[22m[34mgame[0m[1m[34m ) ____________________________________[0mfunction
  [1mReturns:[0m  A completed Sudoku board that solves [22m[34mgame[0m, or [22m[32mfalse[0m, or [22m[32mfail[0m.
  
  Here  [22m[34mgame[0m must be a Sudoku board as returned by [1m[34mSudoku.Init[0m ([1m6.11-1[0m). It is
  not  necessary  that  [22m[34mgame[0m describes a proper Sudoku game. If it has several
  solutions,  then  [22m[32mfalse[0m  is  returned.  If  it has no solution, then [22m[32mfail[0m is
  returned. Otherwise a board with the unique solution is returned.
  
  [22m[35m---------------------------  Example  ----------------------------[0m
    [22m[35mgap> s := "      5  | 154 6 2 |9   5 3  |6 4      |   8     |8  9   53\[0m
    [22m[35m> |     5   | 4   7  2|  91  8  ";;[0m
    [22m[35mgap> sol := Sudoku.UniqueSolution(Sudoku.Init(s));;[0m
    [22m[35mgap> Sudoku.SimpleDisplay(sol);[0m
    [22m[35m438|219|576[0m
    [22m[35m715|436|928[0m
    [22m[35m962|758|314[0m
    [22m[35m-----------[0m
    [22m[35m694|573|281[0m
    [22m[35m153|862|749[0m
    [22m[35m827|941|653[0m
    [22m[35m-----------[0m
    [22m[35m281|695|437[0m
    [22m[35m546|387|192[0m
    [22m[35m379|124|865[0m
  [22m[35m------------------------------------------------------------------[0m
  
  [1m[4m[31m6.11-7 PlaySudoku[0m
  
  [1m[34m> PlaySudoku( [0m[22m[34m[arg][0m[1m[34m ) ______________________________________________[0mfunction
  [1mReturns:[0m  A record describing the latest status of a Sudoku board.
  
  This  function  allows  one to solve Sudoku puzzles interactively. There are
  several  possibilities  for  the  optional  argument [22m[34marg[0m. It can either be a
  string,  matrix  or  list  of holes and integers as described in [1m[34mSudoku.Init[0m
  ([1m6.11-1[0m),  or  a  board as returned by [1m[34mSudoku.Init[0m ([1m6.11-1[0m). Furthermore [22m[34marg[0m
  can  be  an integer or not be given, in that case [1m[34mSudoku.RandomGame[0m ([1m6.11-3[0m)
  is called to produce a random game.
  
  The  usage of this function is self-explanatory, pressing the [1m[46m?[0m key displays
  a  help screen. Here, we mention two keys with a particular action: Pressing
  the  [1m[46mh[0m  key  you  get a hint, either an empty entry is filled or the program
  tells you that there is no solution (so you must delete some entries and try
  others).  Pressing the [1m[46ms[0m key the puzzle is solved by the program or it tells
  you that there is no or no unique solution.
  
  [22m[36mImplementation  remarks[0m:  The  game board is implemented via a browse table,
  without  row  and  column  labels,  with  static header, dynamic footer, and
  individual  [22m[32mminyx[0m  function.  Two  modes  are  supported,  with the standard
  actions  for quitting the table and asking for help; one cell is selected in
  each  mode. The first mode provides actions for moving the selected cell via
  arrow  keys, for changing the value in the selected cell, for getting a hint
  or  the  (unique) solution. (Initial entries of the matrix cannot be changed
  via  user  input.  They  are  shown in boldface.) The second mode serves for
  error handling: When the user enters an invalid number, i.e., a number that
  occurs  already  in  the  current  row  or  column  or  subsquare,  then the
  application  switches  to this mode, which causes that a message is shown in
  the  footer,  and the invalid entry is shown in red and blinking; similarly,
  error mode is entered if a hint or solution does not exist.
  
  The  separating  lines are drawn using an individual [22m[32mSpecialGrid[0m function in
  the  browse  table, since they cannot be specified within the generic browse
  table functions.
  
  Some   standard   [1m[34mNCurses.BrowseGeneric[0m   ([1m4.3-1[0m)   functionality,  such  as
  scrolling, selecting, and searching, are not available in this application.
  
  The code can be found in the file [1mlib/sudoku.g[0m of the package.
  
  [1m[4m[31m6.11-8 Sudoku.HTMLGame[0m
  
  [1m[34m> Sudoku.HTMLGame( [0m[22m[34mgame[0m[1m[34m ) __________________________________________[0mfunction
  [1m[34m> Sudoku.LaTeXGame( [0m[22m[34mgame[0m[1m[34m ) _________________________________________[0mfunction
  [1mReturns:[0m  A string with HTML or LaTeX code, respectively.
  
  The  argument of these functions is a record describing a Sudoku game. These
  functions  return  code for including the current status of the board into a
  webpage or a LaTeX document.
  
