Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > media > contrib-release > by-pkgid > 91213ddcfbe7f54821d42c2d9e091326 > files > 22

gap-system-packages-4.4.12-5mdv2010.0.i586.rpm

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>GAP (Browse) - Chapter 6: Examples of Applications based on NCurses.BrowseGeneric
</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="generator" content="GAPDoc2HTML" />
<link rel="stylesheet" type="text/css" href="manual.css" />
</head>
<body>


<div class="chlinktop"><span class="chlink1">Goto Chapter: </span><a href="chap0.html">Top</a>  <a href="chap1.html">1</a>  <a href="chap2.html">2</a>  <a href="chap3.html">3</a>  <a href="chap4.html">4</a>  <a href="chap5.html">5</a>  <a href="chap6.html">6</a>  <a href="chapA.html">A</a>  <a href="chapBib.html">Bib</a>  <a href="chapInd.html">Ind</a>  </div>

<div class="chlinkprevnexttop">&nbsp;<a href="chap0.html">Top of Book</a>&nbsp;  &nbsp;<a href="chap5.html">Previous Chapter</a>&nbsp;  &nbsp;<a href="chapA.html">Next Chapter</a>&nbsp;  </div>

<p><a id="X178D4F8EA179405AF9" name="X178D4F8EA179405AF9"></a></p>
<div class="ChapSects"><a href="chap6.html#X178D4F8EA179405AF9">6 <span class="Heading">Examples of Applications based on <code class="code">NCurses.BrowseGeneric</code>
</span></a>
<div class="ContSect"><span class="nocss">&nbsp;</span><a href="chap6.html#X813F90F7815AB5B3">6.1 <span class="Heading">The Operation <code class="code">Browse</code></span></a>
<span class="ContSS"><br /><span class="nocss">&nbsp;&nbsp;</span><a href="chap6.html#X17FDD696B17DD54A6E">6.1-1 Browse</a></span>
</div>
<div class="ContSect"><span class="nocss">&nbsp;</span><a href="chap6.html#X8720923F17FDE5223">6.2 <span class="Heading">Character Table Display</span></a>
<span class="ContSS"><br /><span class="nocss">&nbsp;&nbsp;</span><a href="chap6.html#X870C744182073CF6">6.2-1 Browse</a></span>
</div>
<div class="ContSect"><span class="nocss">&nbsp;</span><a href="chap6.html#X80E9A03780DE8891">6.3 <span class="Heading">Table of Marks Display</span></a>
<span class="ContSS"><br /><span class="nocss">&nbsp;&nbsp;</span><a href="chap6.html#X17F4BD9C580BBBAA4">6.3-1 Browse</a></span>
</div>
<div class="ContSect"><span class="nocss">&nbsp;</span><a href="chap6.html#X803708271793813FD">6.4 <span class="Heading">Table of Contents of <strong class="pkg">AtlasRep</strong></span></a>
<span class="ContSS"><br /><span class="nocss">&nbsp;&nbsp;</span><a href="chap6.html#X8411AF928194C5AB">6.4-1 BrowseAtlasInfo</a></span>
</div>
<div class="ContSect"><span class="nocss">&nbsp;</span><a href="chap6.html#X17CF9992917B331E01">6.5 <span class="Heading">Access to <strong class="pkg">GAP</strong> Manuals–a Variant</span></a>
<span class="ContSS"><br /><span class="nocss">&nbsp;&nbsp;</span><a href="chap6.html#X17D79DF9181A15EDF">6.5-1 BrowseGapManuals</a></span>
</div>
<div class="ContSect"><span class="nocss">&nbsp;</span><a href="chap6.html#X17CD8EEF2179F984D2">6.6 <span class="Heading">Overview of the <strong class="pkg">GAP</strong> Bibliography</span></a>
<span class="ContSS"><br /><span class="nocss">&nbsp;&nbsp;</span><a href="chap6.html#X17F0FE4CC17F46ABF3">6.6-1 BrowseBibliography</a></span>
</div>
<div class="ContSect"><span class="nocss">&nbsp;</span><a href="chap6.html#X86C730A017855238D">6.7 <span class="Heading">Overview of <strong class="pkg">GAP</strong> Data</span></a>
<span class="ContSS"><br /><span class="nocss">&nbsp;&nbsp;</span><a href="chap6.html#X850C786C87A4877B">6.7-1 BrowseGapData</a></span>
<span class="ContSS"><br /><span class="nocss">&nbsp;&nbsp;</span><a href="chap6.html#X17FC24FCE17A0C6058">6.7-2 BrowseGapDataAdd</a></span>
</div>
<div class="ContSect"><span class="nocss">&nbsp;</span><a href="chap6.html#X17E3FDA9217E62D963">6.8 <span class="Heading">Navigating in a Directory Tree</span></a>
<span class="ContSS"><br /><span class="nocss">&nbsp;&nbsp;</span><a href="chap6.html#X859682DE8397261E">6.8-1 BrowseDirectory</a></span>
</div>
<div class="ContSect"><span class="nocss">&nbsp;</span><a href="chap6.html#X17FAE330317D09CC4E">6.9 <span class="Heading">A Puzzle</span></a>
<span class="ContSS"><br /><span class="nocss">&nbsp;&nbsp;</span><a href="chap6.html#X17EF5FCBD17DAFFAF3">6.9-1 BrowsePuzzle</a></span>
</div>
<div class="ContSect"><span class="nocss">&nbsp;</span><a href="chap6.html#X17FFF943D178A403C9">6.10 <span class="Heading">Peg Solitaire</span></a>
<span class="ContSS"><br /><span class="nocss">&nbsp;&nbsp;</span><a href="chap6.html#X82C8691380FCB674">6.10-1 PegSolitaire</a></span>
</div>
<div class="ContSect"><span class="nocss">&nbsp;</span><a href="chap6.html#X862CB73B17E0BE170">6.11 <span class="Heading">Rubik's Cube</span></a>
<span class="ContSS"><br /><span class="nocss">&nbsp;&nbsp;</span><a href="chap6.html#X8100659E81FFE9A2">6.11-1 BrowseRubiksCube</a></span>
</div>
<div class="ContSect"><span class="nocss">&nbsp;</span><a href="chap6.html#X17ADD618186541123">6.12 <span class="Heading">Changing Sides</span></a>
<span class="ContSS"><br /><span class="nocss">&nbsp;&nbsp;</span><a href="chap6.html#X17FCFC5858584F46E">6.12-1 BrowseChangeSides</a></span>
</div>
<div class="ContSect"><span class="nocss">&nbsp;</span><a href="chap6.html#X17DDE46668321B5E9">6.13 <span class="Heading">Sudoku</span></a>
<span class="ContSS"><br /><span class="nocss">&nbsp;&nbsp;</span><a href="chap6.html#X1789D3D4C818F4BC2">6.13-1 Sudoku.Init</a></span>
<span class="ContSS"><br /><span class="nocss">&nbsp;&nbsp;</span><a href="chap6.html#X86A5C6CE179DD67EE">6.13-2 Sudoku.Place</a></span>
<span class="ContSS"><br /><span class="nocss">&nbsp;&nbsp;</span><a href="chap6.html#X8401B31A879F9F9F">6.13-3 Sudoku.RandomGame</a></span>
<span class="ContSS"><br /><span class="nocss">&nbsp;&nbsp;</span><a href="chap6.html#X86917AC517C25A68F">6.13-4 Sudoku.SimpleDisplay</a></span>
<span class="ContSS"><br /><span class="nocss">&nbsp;&nbsp;</span><a href="chap6.html#X17C73C6D08293B3B8">6.13-5 Sudoku.OneSolution</a></span>
<span class="ContSS"><br /><span class="nocss">&nbsp;&nbsp;</span><a href="chap6.html#X865DDBDC17E16217F">6.13-6 Sudoku.UniqueSolution</a></span>
<span class="ContSS"><br /><span class="nocss">&nbsp;&nbsp;</span><a href="chap6.html#X17D192244178E86BB4">6.13-7 PlaySudoku</a></span>
<span class="ContSS"><br /><span class="nocss">&nbsp;&nbsp;</span><a href="chap6.html#X804D66D617B908F30">6.13-8 Sudoku.HTMLGame</a></span>
</div>
</div>

<h3>6 <span class="Heading">Examples of Applications based on <code class="code">NCurses.BrowseGeneric</code>
</span></h3>

<p>This chapter introduces the operation <code class="func">Browse</code> (<a href="chap6.html#X17FDD696B17DD54A6E"><b>6.1-1</b></a>) and lists several examples how the function <code class="func">NCurses.BrowseGeneric</code> (<a href="chap4.html#X85FC163D87FAFD12"><b>4.3-1</b></a>) can be utilized for rendering <strong class="pkg">GAP</strong> related data or for playing games. Each section describes the relevant <strong class="pkg">GAP</strong> functions and briefly sketches the technical aspects of the implementation; more details can be found in the <strong class="pkg">GAP</strong> files, in the <code class="file">app</code> directory of the package.</p>

<p>Only Section <a href="chap6.html#X80E9A03780DE8891"><b>6.3</b></a> describes a standard application in the sense of the introduction to Chapter <a href="chap4.html#X877E60DE17F53FDEC"><b>4</b></a>, 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 <a href="chap5.html#X82DDDC1783B4CA30"><b>5</b></a>.</p>

<p><a id="X813F90F7815AB5B3" name="X813F90F7815AB5B3"></a></p>

<h4>6.1 <span class="Heading">The Operation <code class="code">Browse</code></span></h4>

<p><a id="X17FDD696B17DD54A6E" name="X17FDD696B17DD54A6E"></a></p>

<h5>6.1-1 Browse</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; Browse</code>( <var class="Arg">obj[, arec]</var> )</td><td class="tdright">( operation )</td></tr></table></div>
<p>This operation displays the <strong class="pkg">GAP</strong> object <var class="Arg">obj</var> in a nice, formatted way, similar to the operation <code class="func">Display</code> (<a href="../../../doc/ref/chap6.html#X83A5C592178E13248"><b>Reference: Display</b></a>). The difference is that <code class="func">Browse</code> is intended to use <code class="code">ncurses</code> facilities.</p>

<p>Currently there are methods for character tables (see <code class="func">Browse</code> (<a href="chap6.html#X870C744182073CF6"><b>6.2-1</b></a>)) and for tables of marks (see <code class="func">Browse</code> (<a href="chap6.html#X17F4BD9C580BBBAA4"><b>6.3-1</b></a>)).</p>

<p><a id="X8720923F17FDE5223" name="X8720923F17FDE5223"></a></p>

<h4>6.2 <span class="Heading">Character Table Display</span></h4>

<p>The <strong class="pkg">GAP</strong> library provides a <code class="func">Display</code> (<a href="../../../doc/ref/chap6.html#X83A5C592178E13248"><b>Reference: Display</b></a>) method for character tables that breaks the table into columns fitting on the screen. <strong class="pkg">Browse</strong> provides an alternative, using the standard facilities of the function <code class="func">NCurses.BrowseGeneric</code> (<a href="chap4.html#X85FC163D87FAFD12"><b>4.3-1</b></a>), i. e., one can scroll in the matrix of character values, searching and sorting are provided etc.</p>

<p>The <code class="func">Browse</code> (<a href="chap6.html#X17FDD696B17DD54A6E"><b>6.1-1</b></a>) method for character tables can be called instead of <code class="func">Display</code> (<a href="../../../doc/ref/chap6.html#X83A5C592178E13248"><b>Reference: Display</b></a>). For convenience, one can additionally make this function the default <code class="func">Display</code> (<a href="../../../doc/ref/chap6.html#X83A5C592178E13248"><b>Reference: Display</b></a>) method for character tables, by assigning it to the <code class="code">Display</code> component in the global record <code class="code">CharacterTableDisplayDefaults.User</code>, see <a href="../../../doc/ref/chap69.html#X17C1941F117BE9FC21"><b>Reference: Printing Character Tables</b></a>; for example, one can do this in one's <code class="file">.gaprc</code> file, see <a href="../../../doc/ref/chap3.html#X1790A23BE8348DCF2"><b>Reference: The .gaprc file</b></a>. (This can be undone by unbinding the component <code class="code">CharacterTableDisplayDefaults.User.Display</code>.)</p>

<p><a id="X870C744182073CF6" name="X870C744182073CF6"></a></p>

<h5>6.2-1 Browse</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; Browse</code>( <var class="Arg">tbl[, options]</var> )</td><td class="tdright">( method )</td></tr></table></div>
<p>This method displays the character table <var class="Arg">tbl</var> in a window. The optional record <var class="Arg">options</var> describes what shall be displayed, the supported components and the default values are described in <a href="../../../doc/ref/chap69.html#X17C1941F117BE9FC21"><b>Reference: Printing Character Tables</b></a>.</p>

<p>The full functionality of the function <code class="func">NCurses.BrowseGeneric</code> (<a href="chap4.html#X85FC163D87FAFD12"><b>4.3-1</b></a>) is available.</p>


<table class="example">
<tr><td><pre>
gap&gt; BrowseData.SetReplay( Concatenation(
&gt;         # scroll in the table
&gt;         "DRULdddddrrrrrlluu",
&gt;         # select an entry and move it around
&gt;         "seddrruuuddlll",
&gt;         # search for the pattern 135 (six times)
&gt;         "/135", [ NCurses.keys.ENTER ], "nnnnn",
&gt;         # deselect the entry, select the first column
&gt;         "qLsc",
&gt;         # sort and categorize by this column
&gt;         "sc",
&gt;         # select the first row, move down the selection
&gt;         "srdddd",
&gt;         # expand the selected category, scroll the selection down
&gt;         "xd",
&gt;         # and quit the application
&gt;         "Q" ) );
gap&gt; Browse( CharacterTable( "HN" ) );
gap&gt; BrowseData.SetReplay( false );
</pre></td></tr></table>

<p><em>Implementation remarks</em>: The first part of the code in the <code class="func">Browse</code> (<a href="chap6.html#X17FDD696B17DD54A6E"><b>6.1-1</b></a>) method for character tables is almost identical with the code for extracting the data to be displayed from the input data in the <strong class="pkg">GAP</strong> library function <code class="code">CharacterTableDisplayDefault</code>. 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.</p>

<p>The standard modes in <code class="func">BrowseData</code> (<a href="chap5.html#X86E80E578085F137"><b>5.4-1</b></a>) have been extended by three new actions. The first two of them open pagers giving an overview of all irrationalities in the table, or of all those irrationalities that have been shown on the screen in the current call, respectively. The corresponding user inputs are the <strong class="button">I</strong> and the <strong class="button">i</strong> 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 default <code class="func">Display</code> (<a href="../../../doc/ref/chap6.html#X83A5C592178E13248"><b>Reference: Display</b></a>) method for character tables; this is in general <em>not</em> the case, for example when a row-wise search in the table is performed.) The third new action, which is associated with the <strong class="button">p</strong> key, toggles the visibility status of the column label rows for centralizer orders and power maps.</p>

<p>An individual <code class="code">minyx</code> function does not only check whether the desired table fits into the window but also whether a table with too high column labels (centralizer orders and power maps) would fit if these labels get collapsed via the <strong class="button">p</strong> key. In this case, the labels are automatically collapsed, and the <strong class="button">p</strong> key is disabled.</p>

<p>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 <code class="code">Main</code> function in the <code class="code">work</code> 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.</p>

<p>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).</p>

<p>The code can be found in the file <code class="file">app/ctbldisp.g</code> of the package.</p>

<p><a id="X80E9A03780DE8891" name="X80E9A03780DE8891"></a></p>

<h4>6.3 <span class="Heading">Table of Marks Display</span></h4>

<p>The <strong class="pkg">GAP</strong> library provides a <code class="func">Display</code> (<a href="../../../doc/ref/chap6.html#X83A5C592178E13248"><b>Reference: Display</b></a>) method for tables of marks that breaks the table into columns fitting on the screen. Similar to the situation with character tables, see Section <a href="chap6.html#X8720923F17FDE5223"><b>6.2</b></a>, but with a much simpler implementation, <strong class="pkg">Browse</strong> provides an alternative based on the function <code class="func">NCurses.BrowseGeneric</code> (<a href="chap4.html#X85FC163D87FAFD12"><b>4.3-1</b></a>).</p>

<p><code class="func">Browse</code> (<a href="chap6.html#X17FDD696B17DD54A6E"><b>6.1-1</b></a>) can be called instead of <code class="func">Display</code> (<a href="../../../doc/ref/chap6.html#X83A5C592178E13248"><b>Reference: Display</b></a>) for tables of marks, cf. <a href="../../../doc/ref/chap68.html#X17AC0FB9685DCBCFD"><b>Reference: Printing Tables of Marks</b></a>.</p>

<p><a id="X17F4BD9C580BBBAA4" name="X17F4BD9C580BBBAA4"></a></p>

<h5>6.3-1 Browse</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; Browse</code>( <var class="Arg">tom[, options]</var> )</td><td class="tdright">( method )</td></tr></table></div>
<p>This method displays the table of marks <var class="Arg">tom</var> in a window. The optional record <var class="Arg">options</var> describes what shall be displayed, the supported components and the default values are described in <a href="../../../doc/ref/chap68.html#X17AC0FB9685DCBCFD"><b>Reference: Printing Tables of Marks</b></a>.</p>

<p>The full functionality of the function <code class="func">NCurses.BrowseGeneric</code> (<a href="chap4.html#X85FC163D87FAFD12"><b>4.3-1</b></a>) is available.</p>


<table class="example">
<tr><td><pre>
gap&gt; BrowseData.SetReplay( Concatenation(
&gt;         # scroll in the table
&gt;         "DDRRR",
&gt;         # search for the (exact) value 100 (three times)
&gt;         "/100",
&gt;         [ NCurses.keys.DOWN, NCurses.keys.DOWN, NCurses.keys.RIGHT ],
&gt;         [ NCurses.keys.DOWN, NCurses.keys.DOWN, NCurses.keys.DOWN ],
&gt;         [ NCurses.keys.RIGHT, NCurses.keys.ENTER ], "nn",
&gt;         # no more occurrences of 100, confirm
&gt;         [ NCurses.keys.ENTER ],
&gt;         # and quit the application
&gt;         "Q" ) );
gap&gt; Browse( TableOfMarks( "A10" ) );
gap&gt; BrowseData.SetReplay( false );
</pre></td></tr></table>

<p><em>Implementation remarks</em>: Rows and columns are indexed by their positions. The identifier of the table is used as the static header, there is no footer.</p>

<p>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 <code class="code">Main</code> function in the <code class="code">work</code> 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 <code class="code">"O8+(2)"</code>, with 11171 rows and columns, can be shown with <code class="func">Browse</code> (<a href="chap6.html#X17FDD696B17DD54A6E"><b>6.1-1</b></a>) in a <strong class="pkg">GAP</strong> session requiring about 100 MB.)</p>

<p>The code can be found in the file <code class="file">app/tomdisp.g</code> of the package.</p>

<p><a id="X803708271793813FD" name="X803708271793813FD"></a></p>

<h4>6.4 <span class="Heading">Table of Contents of <strong class="pkg">AtlasRep</strong></span></h4>

<p>The <strong class="pkg">GAP</strong> package <strong class="pkg">AtlasRep</strong> (see <a href="chapBib.html#biBAtlasRep">[WPNBB07]</a>) is an interface to a database of representations and related data. The table of contents of this database can be displayed via the function <code class="func">DisplayAtlasInfo</code> (<a href="../../../pkg/atlasrep/doc/chap2.html#X79DACFFA7E2D1A99"><b>AtlasRep: DisplayAtlasInfo</b></a>) of this package. The <strong class="pkg">Browse</strong> package provides an alternative based on the function <code class="func">NCurses.BrowseGeneric</code> (<a href="chap4.html#X85FC163D87FAFD12"><b>4.3-1</b></a>); one can scroll, search, and fetch representations for later use.</p>

<p><a id="X8411AF928194C5AB" name="X8411AF928194C5AB"></a></p>

<h5>6.4-1 BrowseAtlasInfo</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; BrowseAtlasInfo</code>( <var class="Arg"></var> )</td><td class="tdright">( function )</td></tr></table></div>
<p><b>Returns: </b>the list of "clicked" representations.</p>

<p>This function shows the table of contents of the <strong class="pkg">GAP</strong> package <strong class="pkg">AtlasRep</strong> in a browse table, cf. Section <a href="../../../pkg/atlasrep/doc/chap2.html#X806ED7BB83FD848B"><b>AtlasRep: Accessing Data of the AtlasRep Package</b></a> 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 <code class="func">BrowseAtlasInfo</code>.</p>

<p>The full functionality of the function <code class="func">NCurses.BrowseGeneric</code> (<a href="chap4.html#X85FC163D87FAFD12"><b>4.3-1</b></a>) is available.</p>

<p>The following example shows how <code class="func">BrowseAtlasInfo</code> can be used to fetch permutation representations of the alternating groups A_5 and A_6: We search for the group name <code class="code">"A5"</code> in the overview table, and the first cell in the table row for A_5 becomes selected; hitting the <strong class="button">Enter</strong> 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 <strong class="button">Enter</strong> 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.</p>


<table class="example">
<tr><td><pre>
gap&gt; d:= [ NCurses.keys.DOWN ];;  r:= [ NCurses.keys.RIGHT ];;
gap&gt; c:= [ NCurses.keys.ENTER ];;
gap&gt; BrowseData.SetReplay( Concatenation(
&gt;        "/A5",         # Find the string A5 ...
&gt;        d, d, r,       # ... such that just the word matches,
&gt;        c,             # start the search,
&gt;        c,             # click the table entry A5,
&gt;        d,             # move down by one row,
&gt;        c,             # click the row for this representation,
&gt;        d, d,          # move down by two rows,
&gt;        c,             # click the table entry A6,
&gt;        c,             # click the first row,
&gt;        "Q" ) );       # and quit the application.
gap&gt; tworeps:= BrowseAtlasInfo();;
gap&gt; BrowseData.SetReplay( false );
gap&gt; if fail in tworeps then
&gt;      Print( "no access to the Web ATLAS\n" );
&gt;    else
&gt;      Print( List( tworeps, x -&gt; x.identifier[1] ), "\n" );
[ "A5", "A6" ]
&gt;    fi;
</pre></td></tr></table>

<p><em>Implementation remarks</em>: 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.</p>

<p>Row and column separators are drawn as grids (cf. <code class="func">NCurses.Grid</code> (<a href="chap2.html#X1790715F683BF1E66"><b>2.2-8</b></a>)) composed from the special characters described in Section <a href="chap2.html#X8091936586CCD248"><b>2.1-6</b></a>, using the component <code class="code">work.SpecialGrid</code> of the browse table, see <code class="func">BrowseData</code> (<a href="chap5.html#X86E80E578085F137"><b>5.4-1</b></a>).</p>

<p>When a row is selected, the "click" functionality opens a new window (via a second level call to <code class="func">NCurses.BrowseGeneric</code> (<a href="chap4.html#X85FC163D87FAFD12"><b>4.3-1</b></a>)), 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.</p>

<p>This function is available only if the <strong class="pkg">GAP</strong> package <strong class="pkg">AtlasRep</strong> is available.</p>

<p>The code can be found in the file <code class="file">app/atlasbrowse.g</code> of the package.</p>

<p><a id="X17CF9992917B331E01" name="X17CF9992917B331E01"></a></p>

<h4>6.5 <span class="Heading">Access to <strong class="pkg">GAP</strong> Manuals–a Variant</span></h4>

<p>A <strong class="pkg">Browse</strong> 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.</p>

<p>This application is mainly intended as an example with table cells that exceed the screen, and as an example with several category levels.</p>

<p><a id="X17D79DF9181A15EDF" name="X17D79DF9181A15EDF"></a></p>

<h5>6.5-1 BrowseGapManuals</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; BrowseGapManuals</code>( <var class="Arg">[start]</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p>This function displays the contents of the <strong class="pkg">GAP</strong> manuals (the main <strong class="pkg">GAP</strong> manuals as well as the loaded package manuals) in a window. The optional argument <var class="Arg">start</var> describes the initial status, admissible values are the strings <code class="code">"inline/collapsed"</code>, <code class="code">"inline/expanded"</code>, <code class="code">"pager/collapsed"</code>, and <code class="code">"pager/expanded"</code>.</p>

<p>In the <code class="code">inline</code> cases, the parts of the manuals are shown in the browse table, and in the <code class="code">pager</code> case, the parts of the manuals are shown in a different window when they are "clicked", using the user's favourite help viewer, see <a href="../../../doc/ref/chap2.html#X863FF90817EDA8DF9"><b>Reference: Changing the Help Viewer</b></a>.</p>

<p>In the <code class="code">collapsed</code> cases, 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 <code class="code">expanded</code> cases, all category rows are expanded, and nothing is selected; a typical next step in the <code class="code">inline/expanded</code> 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 <strong class="pkg">GAP</strong>, 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.)</p>

<p>If no argument is given then the user is asked for selecting an initial status, using <code class="func">NCurses.Select</code> (<a href="chap3.html#X833D321E86528981"><b>3.1-2</b></a>).</p>

<p>The full functionality of the function <code class="func">NCurses.BrowseGeneric</code> (<a href="chap4.html#X85FC163D87FAFD12"><b>4.3-1</b></a>) is available.</p>


<table class="example">
<tr><td><pre>
gap&gt; n:= [ 14, 14, 14 ];;  # ``do nothing''
gap&gt; BrowseData.SetReplay( Concatenation(
&gt;        "xdxd",                             # expand a Tutorial section
&gt;        n, "Q" ) );                         # and quit
gap&gt; BrowseGapManuals( "inline/collapsed" );
gap&gt; BrowseData.SetReplay( Concatenation(
&gt;        "/Browse", [ NCurses.keys.ENTER ],  # search for "Browse"
&gt;        "xdxddxd",                          # expand a section
&gt;        n, "Q" ) );                         # and quit
gap&gt; BrowseGapManuals( "inline/collapsed" );
gap&gt; BrowseData.SetReplay( false );
</pre></td></tr></table>

<p><em>Implementation remarks</em>: 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 <strong class="pkg">GAP</strong>. 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.</p>

<p>For the variants that show the manuals in a pager, the code temporarily replaces the <code class="code">show</code> function of the default viewer <code class="code">"screen"</code> (see <a href="../../../doc/ref/chap2.html#X863FF90817EDA8DF9"><b>Reference: Changing the Help Viewer</b></a>) by a function that uses <code class="func">NCurses.Pager</code> (<a href="chap3.html#X87E1B27817F588CC0"><b>3.1-4</b></a>). Note that in the case that the manual bit in question fits into one screen, the default <code class="code">show</code> function writes this text directly to the screen, but this is used already by the browse table.</p>

<p>The implementation should be regarded as a sketch.</p>

<p>For example, the markup available in the text file format of <strong class="pkg">GAPDoc</strong> manuals (using <strong class="button">Esc</strong> sequences) is stripped off instead of being transferred to the attribute lines that arise, because of the highlighting problem mentioned in Section <a href="chap2.html#X81D1FC9217C455AEB"><b>2.2-3</b></a>.</p>

<p>Some heuristics used in the code are due to deficiencies of the manual formats.</p>

<p>For the inline variant of the browse table, the titles of chapters, sections, and subsections are <em>not</em> regarded as parts of the actual text since they appear already as category rows; however, the functions of the <strong class="pkg">GAP</strong> help system deliver the text <em>together with</em> these titles, so these lines must be stripped off afterwards.</p>

<p>The category hierarchy representing the tables of contents is created from the <code class="file">manual.six</code> 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 <em>last</em> of these category rows, the data rows for the others are empty. (This problem does not occur in the <strong class="pkg">GAPDoc</strong> manual format because this introduces explicit subsection titles, involving only the <em>first</em> of several function definitions.)</p>

<p>Also, index entries and sectioning entries in <code class="file">manual.six</code> files of manuals in <strong class="pkg">GAPDoc</strong> format are not explicitly distinguished.</p>

<p>The code can be found in the file <code class="file">app/manual.g</code> of the package.</p>

<p><a id="X17CD8EEF2179F984D2" name="X17CD8EEF2179F984D2"></a></p>

<h4>6.6 <span class="Heading">Overview of the <strong class="pkg">GAP</strong> Bibliography</span></h4>

<p>The <strong class="pkg">GAP</strong> documentation contains a bibliography of <strong class="pkg">GAP</strong> related publications, see <a href="chapBib.html#biBGAPBibliography">[GAP]</a>. <strong class="pkg">Browse</strong> provides access to this information in <strong class="pkg">GAP</strong>, using the standard facilities of the function <code class="func">NCurses.BrowseGeneric</code> (<a href="chap4.html#X85FC163D87FAFD12"><b>4.3-1</b></a>), i. e., one can scroll in the list, search for entries, sort by year, sort and categorize by authors etc.</p>

<p>The <strong class="pkg">Browse</strong> package contains a (perhaps outdated) version of this bibliography. One can get an updated version as follows.</p>

<p><code class="code">wget -N http://www.gap-system.org/Doc/Bib/gap-publishednicer.bib</code></p>

<p><a id="X17F0FE4CC17F46ABF3" name="X17F0FE4CC17F46ABF3"></a></p>

<h5>6.6-1 BrowseBibliography</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; BrowseBibliography</code>( <var class="Arg">[bibfiles]</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p><b>Returns: </b>a record as returned by <code class="func">ParseBibXMLExtFiles</code> (<a href="../../../pkg/gapdoc/doc/chap7.html#X86BD29AE17A453721"><b>GAPDoc: ParseBibXMLextFiles</b></a>).</p>

<p>This function shows the list of bibliography entries in the files given by <var class="Arg">bibfiles</var>, which may be a string or a list of strings (denoting a filename or a list of filenames, respectively) or a record (see below for the supported components).</p>

<p>If no argument is given then the file <code class="file">bibl/gap-publishednicer.bib</code> in the <strong class="pkg">Browse</strong> package directory is taken, and <code class="code">"GAP Bibliography"</code> is used as the header.</p>

<p>Another perhaps interesting data file that should be available in the <strong class="pkg">GAP</strong> distribution is <code class="file">doc/manualbib.xml</code>. This file can be located as follows.</p>


<table class="example">
<tr><td><pre>
gap&gt; file:= Filename( DirectoriesLibrary( "doc" ), "manualbib.xml" );;
</pre></td></tr></table>

<p>Both BibTeX format and the <strong class="pkg">XML</strong> based extended format provided by the <strong class="pkg">GAPDoc</strong> package are supported by <code class="func">BrowseBibliography</code>, see Chapter <a href="../../../pkg/gapdoc/doc/chap7.html#X17EB94CE917ABF7192"><b>GAPDoc: Utilities for Bibliographies</b></a>.</p>

<p>In the case of BibTeX format input, first a conversion to the extended format takes place, via <code class="func">StringBibAsXMLext</code> (<a href="../../../pkg/gapdoc/doc/chap7.html#X85F33C641787A00B7"><b>GAPDoc: StringBibAsXMLext</b></a>) and <code class="func">ParseBibXMLextString</code> (<a href="../../../pkg/gapdoc/doc/chap7.html#X86BD29AE17A453721"><b>GAPDoc: ParseBibXMLextString</b></a>). Note that syntactically incorrect entries are rejected in this conversion –this is signaled with <code class="func">InfoBibTools</code> (<a href="../../../pkg/gapdoc/doc/chap7.html#X85C1D50F17E37A99A"><b>GAPDoc: InfoBibTools</b></a>) warnings– and that only a subset of the possible LaTeX markup is recognized –other markup appears in the browse table except that the leading backslash is removed.</p>

<p>In both cases of input, the problem arises that in visual mode, currently we can show only ASCII characters (and the symbols in <code class="code">NCurses.lineDraw</code>, but these are handled differently, see Section <a href="chap2.html#X8091936586CCD248"><b>2.1-6</b></a>). Therefore, we use the function <code class="func">SimplifiedUnicodeString</code> (<a href="../../../pkg/gapdoc/doc/chap6.html#X818A315617EB30A39"><b>GAPDoc: SimplifiedUnicodeString</b></a>) for replacing other unicode characters by ASCII text.</p>

<p>The return value is a record as returned by <code class="func">ParseBibXMLExtFiles</code> (<a href="../../../pkg/gapdoc/doc/chap7.html#X86BD29AE17A453721"><b>GAPDoc: ParseBibXMLextFiles</b></a>), its <code class="code">entries</code> component corresponds to the bibliography entries that have been "clicked" in visual mode. This record can be used as input for <code class="func">WriteBibFile</code> (<a href="../../../pkg/gapdoc/doc/chap7.html#X17C2B2F65851EAA0B"><b>GAPDoc: WriteBibFile</b></a>) or <code class="func">WriteBibXMLextFile</code> (<a href="../../../pkg/gapdoc/doc/chap7.html#X17811108C17E5B1709"><b>GAPDoc: WriteBibXMLextFile</b></a>), in order to produce a bibliography file, or it can be used as input for <code class="func">StringBibXMLEntry</code> (<a href="../../../pkg/gapdoc/doc/chap7.html#X1790A295680F7CD24"><b>GAPDoc: StringBibXMLEntry</b></a>), in order to produce strings from the entries, in various formats.</p>

<p>The full functionality of the function <code class="func">NCurses.BrowseGeneric</code> (<a href="chap4.html#X85FC163D87FAFD12"><b>4.3-1</b></a>) is available.</p>


<table class="example">
<tr><td><pre>
gap&gt; # sort and categorize by year, scroll down, expand a category row
gap&gt; BrowseData.SetReplay( "scrrscsedddddxdddddQ" );
gap&gt; BrowseBibliography();;
gap&gt; # sort &amp; categorize by authors, expand all category rows, scroll down
gap&gt; BrowseData.SetReplay( "scscXseddddddQ" );
gap&gt; BrowseBibliography();;
gap&gt; # sort and categorize by journal, search for a journal name, expand
gap&gt; BrowseData.SetReplay( Concatenation( "scrrrsc/J. Algebra",
&gt;        [ NCurses.keys.ENTER ], "nxdddQ" ) );
gap&gt; BrowseBibliography();;
gap&gt; BrowseData.SetReplay( false );
</pre></td></tr></table>

<p><em>Implementation remarks</em>: The browse table has a dynamic header (showing the number of entries, which can vary when the table is restricted), no footer and row labels; one row of column labels is given by the descriptions of the table columns (authors, title, year, journal).</p>

<p>Row and column separators are drawn as grids (cf. <code class="func">NCurses.Grid</code> (<a href="chap2.html#X1790715F683BF1E66"><b>2.2-8</b></a>)) composed from the special characters described in Section <a href="chap2.html#X8091936586CCD248"><b>2.1-6</b></a>, using the component <code class="code">work.SpecialGrid</code> of the browse table, see <code class="func">BrowseData</code> (<a href="chap5.html#X86E80E578085F137"><b>5.4-1</b></a>).</p>

<p>For categorizing by authors, the sort parameter <code class="code">"split rows on categorizing"</code> is set to <code class="code">"yes"</code>, so the authors are distributed to different category rows, hence each entry appears once for each of its authors in the categorized table. When a data row or an entry in a data row is selected, "click" adds the corresponding bibliographhy entry to the result.</p>

<p>The width of the title column is preset; usually titles are too long for one line, and the contents of this column is formatted as a paragraph, using the function <code class="func">FormatParagraph</code> (<a href="../../../pkg/gapdoc/doc/chap6.html#X812058CE17C8E9022"><b>GAPDoc: FormatParagraph</b></a>). For the authors and journal columns, maximal widths are prescribed, and <code class="func">FormatParagraph</code> (<a href="../../../pkg/gapdoc/doc/chap6.html#X812058CE17C8E9022"><b>GAPDoc: FormatParagraph</b></a>) is used for longer entries.</p>

<p>For three columns, the sort parameters are defined as follows: The <em>authors</em> column does not become hidden when the table is categorized according to this column, sorting by the <em>year</em> yields a <em>de</em>scending order, and the category rows arising from these columns and the <em>journal</em> column show the numbers of the data rows that belong to them.</p>

<p>Those standard modes in <code class="func">BrowseData</code> (<a href="chap5.html#X86E80E578085F137"><b>5.4-1</b></a>) where an entry or a row of the table is selected have been extended by three new actions, which open a pager showing the BibTeX, HTML, and Text format of the selected entry, respectively. The corresponding user inputs are the <strong class="button">vb</strong>, <strong class="button">vh</strong>, and <strong class="button">vt</strong>.</p>

<p>This function requires some of the utilities provided by the <strong class="pkg">GAP</strong> package <strong class="pkg">GAPDoc</strong> (see <a href="chapBib.html#biBGAPDoc">[LN07]</a>), such as <code class="func">FormatParagraph</code> (<a href="../../../pkg/gapdoc/doc/chap6.html#X812058CE17C8E9022"><b>GAPDoc: FormatParagraph</b></a>), <code class="func">NormalizeNameAndKey</code> (<a href="../../../pkg/gapdoc/doc/chap7.html#X17C9F0C3317A0A0FF0"><b>GAPDoc: NormalizeNameAndKey</b></a>), <code class="func">NormalizedNameAndKey</code> (<a href="../../../pkg/gapdoc/doc/chap7.html#X17C9F0C3317A0A0FF0"><b>GAPDoc: NormalizedNameAndKey</b></a>), <code class="func">ParseBibFiles</code> (<a href="../../../pkg/gapdoc/doc/chap7.html#X82555C3017FDC1817"><b>GAPDoc: ParseBibFiles</b></a>), <code class="func">ParseBibXMLextFiles</code> (<a href="../../../pkg/gapdoc/doc/chap7.html#X86BD29AE17A453721"><b>GAPDoc: ParseBibXMLextFiles</b></a>), <code class="func">ParseBibXMLextString</code> (<a href="../../../pkg/gapdoc/doc/chap7.html#X86BD29AE17A453721"><b>GAPDoc: ParseBibXMLextString</b></a>), <code class="func">RecBibXMLEntry</code> (<a href="../../../pkg/gapdoc/doc/chap7.html#X1786C33ED179F425F1"><b>GAPDoc: RecBibXMLEntry</b></a>), and <code class="func">StringBibAsXMLext</code> (<a href="../../../pkg/gapdoc/doc/chap7.html#X85F33C641787A00B7"><b>GAPDoc: StringBibAsXMLext</b></a>).</p>

<p>The code can be found in the file <code class="file">app/gapbibl.g</code> of the package.</p>

<p>The browse table can be customized by entering a record as the argument of <code class="func">BrowseBibliography</code>, with the following supported components.</p>


<dl>
<dt><strong class="Mark"><code class="code">files</code></strong></dt>
<dd><p>a nonempty list of filenames containing the data to be shown; there is no default for this component.</p>

</dd>
<dt><strong class="Mark"><code class="code">filesshort</code></strong></dt>
<dd><p>a list of the same length as the <code class="code">files</code> component, the entries are strings which are shown in the <code class="code">"sourcefilename"</code> column of the table (if this column is present); the default is the list of filenames.</p>

</dd>
<dt><strong class="Mark"><code class="code">filecontents</code></strong></dt>
<dd><p>a list of the same length as the <code class="code">files</code> component, the entries are strings which are shown as category values when the table is categorized by the <code class="code">"sourcefilename"</code> column; the default is the list of filenames.</p>

</dd>
<dt><strong class="Mark"><code class="code">header</code></strong></dt>
<dd><p>is the constant part of the header shown above the browse table, the default is the first filename.</p>

</dd>
<dt><strong class="Mark"><code class="code">columns</code></strong></dt>
<dd><p>is a list of records that are valid as the second argument of <code class="func">DatabaseAttributeAdd</code> (<a href="chapA.html#X8573522782D939FE"><b>A.1-5</b></a>), where the first argument is a database id enumerator created from the bibliography entries in the files in question. Each entry (and also the corresponding identifier) of this database id enumerator is a list of records obtained from <code class="func">ParseBibXMLextFiles</code> (<a href="../../../pkg/gapdoc/doc/chap7.html#X86BD29AE17A453721"><b>GAPDoc: ParseBibXMLextFiles</b></a>) and <code class="func">RecBibXMLEntry</code> (<a href="../../../pkg/gapdoc/doc/chap7.html#X1786C33ED179F425F1"><b>GAPDoc: RecBibXMLEntry</b></a>), or from <code class="func">ParseBibFiles</code> (<a href="../../../pkg/gapdoc/doc/chap7.html#X82555C3017FDC1817"><b>GAPDoc: ParseBibFiles</b></a>), such that the list elements are regarded as equal, in the sense that their fingerprints (see below) are equal. The records in the <code class="code">columns</code> list are available for constructing the desired browse table, the actual appearance is controlled by the <code class="code">choice</code> component described below. Columns showing authors, title, year, journal, and filename are predefined and need not be listed here.</p>

</dd>
<dt><strong class="Mark"><code class="code">choice</code></strong></dt>
<dd><p>a list of strings denoting the <code class="code">identifier</code> components of those columns that shall actually be shown in the table, the default is <code class="code">[ "authors", "title", "year", "journal" ]</code>.</p>

</dd>
<dt><strong class="Mark"><code class="code">fingerprint</code></strong></dt>
<dd><p>a list of strings denoting component names of the entries of the database id enumerator that is constructed from the data (see above); two data records are regarded as equal if the values of these components are equal; the default is <code class="code">[ "mrnumber", "title", "authorAsList", "editorAsList", "author" ]</code>.</p>

</dd>
<dt><strong class="Mark"><code class="code">sortKeyFunction</code></strong></dt>
<dd><p>either <code class="keyw">fail</code> or a function that takes a record as returned by <code class="func">RecBibXMLEntry</code> (<a href="../../../pkg/gapdoc/doc/chap7.html#X1786C33ED179F425F1"><b>GAPDoc: RecBibXMLEntry</b></a>) and returns a list that is used for comparing and thus sorting the records; the default is <code class="keyw">fail</code>, which means that the rows of the table appear in the same ordering as in the source files.</p>

</dd>
</dl>
<p><a id="X86C730A017855238D" name="X86C730A017855238D"></a></p>

<h4>6.7 <span class="Heading">Overview of <strong class="pkg">GAP</strong> Data</span></h4>

<p>The <strong class="pkg">GAP</strong> system contains several data collections such as libraries of groups and character tables. Clearly the function <code class="func">NCurses.BrowseGeneric</code> (<a href="chap4.html#X85FC163D87FAFD12"><b>4.3-1</b></a>) can be used to visualize interesting information about such data collections, in the form of an "overview table" whose rows correspond to the objects in the collection; each column of the table shows a piece of information about the objects. (One possibility to create such overviews is given by <code class="func">BrowseTableFromDatabaseIdEnumerator</code> (<a href="chapA.html#X17F25A3E586653911"><b>A.2-2</b></a>).)</p>

<p><a id="X850C786C87A4877B" name="X850C786C87A4877B"></a></p>

<h5>6.7-1 BrowseGapData</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; BrowseGapData</code>( <var class="Arg"></var> )</td><td class="tdright">( function )</td></tr></table></div>
<p><b>Returns: </b>the return value of the chosen application if there is one.</p>

<p>The function <code class="func">BrowseGapData</code> shows the choices in the list <code class="code">BrowseData.GapDataOverviews</code>, in a browse table with one column. When an entry is "clicked" then the associated function is called, and the table of choices is closed.</p>

<p>The idea is that each entry of <code class="code">BrowseData.GapDataOverviews</code> describes an overview of a <strong class="pkg">GAP</strong> data collection.</p>

<p>The <strong class="pkg">Browse</strong> package provides overviews of the Conway polynomials in <strong class="pkg">GAP</strong>, the <strong class="pkg">GAP</strong> bibliography (see Section <a href="chap6.html#X17CD8EEF2179F984D2"><b>6.6</b></a>), the <strong class="pkg">GAP</strong> manuals (see Section <a href="chap6.html#X17CF9992917B331E01"><b>6.5</b></a>), <strong class="pkg">GAP</strong> operations and methods, and the installed <strong class="pkg">GAP</strong> packages.</p>

<p>Other <strong class="pkg">GAP</strong> packages may add more overviews to the choices, using the function <code class="func">BrowseGapDataAdd</code> (<a href="chap6.html#X17FC24FCE17A0C6058"><b>6.7-2</b></a>).</p>

<p>Except that always one table cell is selected, the full functionality of the function <code class="func">NCurses.BrowseGeneric</code> (<a href="chap4.html#X85FC163D87FAFD12"><b>4.3-1</b></a>) is available.</p>


<table class="example">
<tr><td><pre>
gap&gt; n:= [ 14, 14, 14 ];;  # ``do nothing''
gap&gt; # open the overview of Conway polynomials
gap&gt; BrowseData.SetReplay( Concatenation( "/Conway Polynomials",
&gt;      [ NCurses.keys.ENTER, NCurses.keys.ENTER ], "srdddd", n, "Q" ) );
gap&gt; BrowseGapData();;
gap&gt; # open the overview of GAP packages
gap&gt; BrowseData.SetReplay( Concatenation( "/GAP Packages",
&gt;      [ NCurses.keys.ENTER, NCurses.keys.ENTER ], "/Browse",
&gt;      [ NCurses.keys.ENTER ], "n", n, "Q" ) );
gap&gt; BrowseGapData();;
gap&gt; BrowseData.SetReplay( false );
</pre></td></tr></table>

<p><em>Implementation remarks</em>: The browse table has a static header, a dynamic footer showing the description of the currently selected entry, no row or column labels, and exactly one column of fixed width equal to the screen width. If the chosen application has a return value then this is returned by <code class="func">BrowseGapData</code>, otherwise nothing is returned. The component <code class="code">work.SpecialGrid</code> of the browse table is used to draw a border around the list of choices and another border around the footer. Only one mode is needed in which an entry is selected.</p>

<p>The code can be found in the file <code class="file">app/gapdata.g</code> of the package.</p>

<p><a id="X17FC24FCE17A0C6058" name="X17FC24FCE17A0C6058"></a></p>

<h5>6.7-2 BrowseGapDataAdd</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; BrowseGapDataAdd</code>( <var class="Arg">title, call, ret, documentation</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p>This function extends the list <code class="code">BrowseData.GapDataOverviews</code> by a new entry. The list is used by <code class="func">BrowseGapData</code> (<a href="chap6.html#X850C786C87A4877B"><b>6.7-1</b></a>).</p>

<p><var class="Arg">title</var> must be a string of length at most 76; it will be shown in the browse table that is opened by <code class="func">BrowseGapData</code> (<a href="chap6.html#X850C786C87A4877B"><b>6.7-1</b></a>). <var class="Arg">call</var> must be a function that takes no arguments; it will be called when <var class="Arg">title</var> is "clicked". <var class="Arg">ret</var> must be <code class="keyw">true</code> if <var class="Arg">call</var> has a return value and if <code class="func">BrowseGapData</code> (<a href="chap6.html#X850C786C87A4877B"><b>6.7-1</b></a>) shall return this value, and <code class="keyw">false</code> otherwise. <var class="Arg">documentation</var> must be a string that describes what happens when the function <var class="Arg">call</var> is called; it will be shown in the footer of the table opened by <code class="func">BrowseGapData</code> (<a href="chap6.html#X850C786C87A4877B"><b>6.7-1</b></a>) when <var class="Arg">title</var> is selected.</p>

<p><a id="X17E3FDA9217E62D963" name="X17E3FDA9217E62D963"></a></p>

<h4>6.8 <span class="Heading">Navigating in a Directory Tree</span></h4>

<p>A natural way to visualize the contents of a directory is via a tree whose leaves denote plain files, and the other vertices denote subdirectories. <strong class="pkg">Browse</strong> provides a function based on <code class="func">NCurses.BrowseGeneric</code> (<a href="chap4.html#X85FC163D87FAFD12"><b>4.3-1</b></a>) for displaying such trees; the leaves correspond to the data rows, and the other vertices correspond to category rows.</p>

<p><a id="X859682DE8397261E" name="X859682DE8397261E"></a></p>

<h5>6.8-1 BrowseDirectory</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; BrowseDirectory</code>( <var class="Arg">[startpath]</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p><b>Returns: </b>a list of the "clicked" filenames.</p>

<p>If no argument is given then the contents of the current directory is shown, see <code class="func">DirectoryCurrent</code> (<a href="../../../doc/ref/chap9.html#X17BAD8036849E8430"><b>Reference: DirectoryCurrent</b></a>). If a string <var class="Arg">startpath</var> is given as the only argument then it is understood as a directory path, in the sense of <code class="func">Directory</code> (<a href="../../../doc/ref/chap9.html#X86A71E9217EEC7EAD"><b>Reference: Directory</b></a>), and the contents of this directory is shown.</p>

<p>The full functionality of the function <code class="func">NCurses.BrowseGeneric</code> (<a href="chap4.html#X85FC163D87FAFD12"><b>4.3-1</b></a>) is available.</p>


<table class="example">
<tr><td><pre>
gap&gt; n:= [ 14, 14, 14 ];;  # ``do nothing''
gap&gt; BrowseData.SetReplay( Concatenation(
&gt;        "q",                                  # leave the selection
&gt;        "X",                                  # expand all categories
&gt;        "/filetree", [ NCurses.keys.ENTER ],  # search for "filetree"
&gt;        n, "Q" ) );                           # and quit
gap&gt; dir:= Filename( DirectoriesPackageLibrary( "Browse", "" ), "" );;
gap&gt; BrowseDirectory( dir );;
gap&gt; BrowseData.SetReplay( false );
</pre></td></tr></table>

<p><em>Implementation remarks</em>: The browse table has a static header, no footer, no row or column labels, and exactly one data column. The category rows are precomputed, i. e., they do not arise from a table column. The tree structure is visualized via a special grid that is shown in the separator column before the table column; the width of this column is computed from the largest nesting depth of files. For technical reasons, category rows representing <em>empty</em> directories are realized via "dummy" table rows; a special <code class="code">ShowTables</code> function guarantees that these rows are always hidden,</p>

<p>When a data row or an entry in this row is selected, "click" adds the corresponding filename to the result list. Initially, the first row is selected. (So if you want to search in the whole tree then you should quit this selection by hitting the <strong class="button">q</strong> key.)</p>

<p>The category hierarchy is computed using <code class="func">DirectoryContents</code> (<a href="../../../doc/ref/chap9.html#X17B225E5282534EDA"><b>Reference: DirectoryContents</b></a>).</p>

<p>This function is available only if the <strong class="pkg">GAP</strong> package <strong class="pkg">IO</strong> (see <a href="chapBib.html#biBIO">[Neu07]</a>) is available, because the check for cycles uses the function <code class="func">IO_stat</code> (<a href="../../../pkg/io/doc/chap3.html#X17F7D238617B45D525"><b>IO: IO_stat</b></a>) from this package.</p>

<p>The code can be found in the file <code class="file">app/filetree.g</code> of the package.</p>

<p><a id="X17FAE330317D09CC4E" name="X17FAE330317D09CC4E"></a></p>

<h4>6.9 <span class="Heading">A Puzzle</span></h4>

<p>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.</p>

<div class="pcenter"><table class="GAPDocTable">
<tr>
<td class="tdcenter">7</td>
<td class="tdcenter">13</td>
<td class="tdcenter">14</td>
<td class="tdcenter">2</td>
</tr>
<tr>
<td class="tdcenter">1</td>
<td class="tdcenter">4</td>
<td class="tdcenter">15</td>
<td class="tdcenter">11</td>
</tr>
<tr>
<td class="tdcenter">6</td>
<td class="tdcenter">8</td>
<td class="tdcenter">3</td>
<td class="tdcenter">9</td>
</tr>
<tr>
<td class="tdcenter">10</td>
<td class="tdcenter">5</td>
<td class="tdcenter">12</td>
<td class="tdcenter"></td>
</tr>
</table><br /><p>&nbsp;</p><br />
</div>

<p>The aim of the game is to order the numbered squares via these moves.</p>

<p>For the case m = n = 4, the puzzle is known under the name "Sam Loyd's Fifteen", see <a href="chapBib.html#biBLoydFifteenWeb">[Bog]</a> and <a href="chapBib.html#biBHistGames">[OR]</a> for more information and references.</p>

<p><a id="X17EF5FCBD17DAFFAF3" name="X17EF5FCBD17DAFFAF3"></a></p>

<h5>6.9-1 BrowsePuzzle</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; BrowsePuzzle</code>( <var class="Arg">[m, n[, pi]]</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p><b>Returns: </b>a record describing the initial and final status of the puzzle.</p>

<p>This function shows the rectangle in a window.</p>

<p>The arguments <var class="Arg">m</var> and <var class="Arg">n</var> 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 <var class="Arg">pi</var>, the default is a random element in the alternating group on the points 1, 2, ..., <var class="Arg">m</var> <var class="Arg">n</var> - 1. (Note that the game has not always a solution.)</p>

<p>In any case, the empty cell is selected, and the selection can be moved to neighboring cells via the arrow keys, or to any place in the same row or column via a mouse click.</p>

<p>The return value is a record with the components <code class="code">dim</code> (the pair <code class="code">[ m, n ]</code>), <code class="code">init</code> (the initial permutation), <code class="code">final</code> (the final permutation), and <code class="code">steps</code> (the number of transpositions that were needed).</p>


<table class="example">
<tr><td><pre>
gap&gt; BrowseData.SetReplay( Concatenation(
&gt;        BrowsePuzzleSolution.steps, "Q" ) );
gap&gt; BrowsePuzzle( 4, 4, BrowsePuzzleSolution.init );;
gap&gt; BrowseData.SetReplay( false );
</pre></td></tr></table>

<p>An implementation using only mouse clicks but no key strokes is available in the <strong class="pkg">GAP</strong> package <strong class="pkg">XGAP</strong> (see <a href="chapBib.html#biBXGAP">[CN04]</a>).</p>

<p><em>Implementation remarks</em>: The game board is implemented via a browse table, without row and column labels, with static header, dynamic footer, and individual <code class="code">minyx</code> 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 and mouse clicks are admissible.</p>

<p>Some standard <code class="func">NCurses.BrowseGeneric</code> (<a href="chap4.html#X85FC163D87FAFD12"><b>4.3-1</b></a>) functionality, such as scrolling, selecting, and searching, are not available in this application.</p>

<p>The code can be found in the file <code class="file">app/puzzle.g</code> of the package.</p>

<p><a id="X17FFF943D178A403C9" name="X17FFF943D178A403C9"></a></p>

<h4>6.10 <span class="Heading">Peg Solitaire</span></h4>

<p>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. </p><div style="text-align:center;"> <img src="solitair.png" alt="[solitaire image]"/> </div><p></p>

<p>We consider the game that in the beginning, exactly one hole is empty, and in the end, exactly one peg is left.</p>

<p><a id="X82C8691380FCB674" name="X82C8691380FCB674"></a></p>

<h5>6.10-1 PegSolitaire</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; PegSolitaire</code>( <var class="Arg">[format, ][nrholes, ][twoModes]</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p>This function shows the game board in a window.</p>

<p>If the argument <var class="Arg">format</var> is one of the strings <code class="code">"small"</code> or <code class="code">"large"</code> then small or large pegs are shown, the default is <code class="code">"small"</code>.</p>

<p>Three shapes of the game board are supported, with 33, 37, and 45 holes, respectively; this number can be specified via the argument <var class="Arg">nrholes</var>, 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.</p>

<p>If a Boolean <var class="Arg">twoModes</var> is entered as an argument then it determines whether a browse table with one or two modes is used; the default <code class="keyw">false</code> yields a browse table with only one mode.</p>

<p>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 <code class="code">j</code> key followed by the appropriate arrow key.</p>


<table class="example">
<tr><td><pre>
gap&gt; for n in [ 33, 37, 45 ] do
&gt;      BrowseData.SetReplay( Concatenation(
&gt;          PegSolitaireSolutions.( String( n ) ), "Q" ) );
&gt;      PegSolitaire( n );
&gt; od;
gap&gt; BrowseData.SetReplay( false );
</pre></td></tr></table>

<p>For more information such as variations of the game and references, see <a href="chapBib.html#biBPegSolitaireWeb">[Köla]</a>. Also the solutions stored in the variable <code class="code">PegSolitaireSolutions</code> have been taken from this web page.</p>

<p><em>Implementation remarks</em>: The game board is implemented via a browse table, without row and column labels, with static header, dynamic footer, and individual <code class="code">minyx</code> 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.</p>

<p>Some standard <code class="func">NCurses.BrowseGeneric</code> (<a href="chap4.html#X85FC163D87FAFD12"><b>4.3-1</b></a>) functionality, such as scrolling, selecting, and searching, are not available in this application.</p>

<p>The code can be found in the file <code class="file">app/solitair.g</code> of the package.</p>

<p><a id="X862CB73B17E0BE170" name="X862CB73B17E0BE170"></a></p>

<h4>6.11 <span class="Heading">Rubik's Cube</span></h4>

<p>We visualize the transformations of Rubik's magic cube in a model that is given by "unfolding" the faces and numbering them as follows. </p><div style="text-align:center;"> <img src="rubik.png" alt="[unfolded Rubik's cube image]"/> </div><p></p>

<p>Clockwise turns of the six layers (top, left, front, right, back, and down) are represented by the following permutations.</p>


<table class="example">
<tr><td><pre>
gap&gt; cubegens := [
&gt;   ( 1, 3, 8, 6)( 2, 5, 7, 4)( 9,33,25,17)(10,34,26,18)(11,35,27,19),
&gt;   ( 9,11,16,14)(10,13,15,12)( 1,17,41,40)( 4,20,44,37)( 6,22,46,35),
&gt;   (17,19,24,22)(18,21,23,20)( 6,25,43,16)( 7,28,42,13)( 8,30,41,11),
&gt;   (25,27,32,30)(26,29,31,28)( 3,38,43,19)( 5,36,45,21)( 8,33,48,24),
&gt;   (33,35,40,38)(34,37,39,36)( 3, 9,46,32)( 2,12,47,29)( 1,14,48,27),
&gt;   (41,43,48,46)(42,45,47,44)(14,22,30,38)(15,23,31,39)(16,24,32,40)
&gt; ];;
</pre></td></tr></table>

<p><strong class="pkg">GAP</strong> computations analyzing this permutation group have been part of the announcements of <strong class="pkg">GAP</strong> 3 releases. For a <strong class="pkg">GAP</strong> 4 equivalent, see <a href="chapBib.html#biBRubiksCubeGAPWeb">[Sch]</a>. For more information and references (not <strong class="pkg">GAP</strong> related) about Rubik's cube, see <a href="chapBib.html#biBRubiksCubeWeb">[Kölb]</a>.</p>

<p><a id="X8100659E81FFE9A2" name="X8100659E81FFE9A2"></a></p>

<h5>6.11-1 BrowseRubiksCube</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; BrowseRubiksCube</code>( <var class="Arg">[format, ][pi]</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p>This function shows the model of the cube in a window.</p>

<p>If the argument <var class="Arg">format</var> is one of the strings <code class="code">"small"</code> or <code class="code">"large"</code> then small or large cells are shown, the default is <code class="code">"small"</code>.</p>

<p>The argument <var class="Arg">pi</var> is the initial permutation of the faces, the default is a random permutation in the cube group, see <a href="../../../doc/ref/chap14.html#X179730D6517AB219DB"><b>Reference: Random</b></a>.</p>

<p>Supported user inputs are the keys <strong class="button">t</strong>, <strong class="button">l</strong>, <strong class="button">f</strong>, <strong class="button">r</strong>, <strong class="button">b</strong>, and <strong class="button">d</strong> 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 <code class="func">NCurses.attrs.has_colors</code> (<a href="chap2.html#X83ADB4E317C105B8C"><b>2.2-1</b></a>), the input <strong class="button">s</strong> 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.</p>

<p>The return value is a record with the components <code class="code">inputs</code> (a string describing the user inputs), <code class="code">init</code>, and <code class="code">final</code> (the initial and final permutation of the faces, respectively). (The <code class="code">inputs</code> component can be used for the replay feature, see the example below.)</p>

<p>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.</p>


<table class="example">
<tr><td><pre>
gap&gt; choice:= List( [ 1 .. 30 ], i -&gt; Random( [ 1 .. 6 ] ) );;
gap&gt; input:= List( "tlfrbd", INT_CHAR ){ choice };;
gap&gt; BrowseData.SetReplay( Concatenation(
&gt;        input{ [ 1 .. 20 ] },
&gt;        "s",                    # switch to number display
&gt;        input{ [ 21 .. 25 ] },
&gt;        "s",                    # switch to color display
&gt;        input{ [ 26 .. 30 ] },
&gt;        "Q" ) );;               # quit the browse table
gap&gt; BrowseRubiksCube( Product( cubegens{ choice } ) );;
gap&gt; BrowseData.SetReplay( false );
</pre></td></tr></table>

<p><em>Implementation remarks</em>: The cube is implemented via a browse table, without row and column labels, with static header, dynamic footer, and individual <code class="code">minyx</code> 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.</p>

<p>Switching between the two display formats is implemented via a function <code class="code">work.Main</code>, so this relies on <em>not</em> caching the formatted cells in <code class="code">work.main</code>.</p>

<p>Row and column separators of the browse table are whitespace of height and width one. The separating lines are drawn using an individual <code class="code">SpecialGrid</code> function in the browse table. Note that the relevant cells do not form a rectangular array.</p>

<p>Some standard <code class="func">NCurses.BrowseGeneric</code> (<a href="chap4.html#X85FC163D87FAFD12"><b>4.3-1</b></a>) functionality, such as scrolling, selecting, and searching, are not available in this application.</p>

<p>The code can be found in the file <code class="file">app/rubik.g</code> of the package.</p>

<p><a id="X17ADD618186541123" name="X17ADD618186541123"></a></p>

<h4>6.12 <span class="Heading">Changing Sides</span></h4>

<p>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.</p>

<p></p><table class="sudokuin"> <tr><td>X</td><td>X</td><td>X</td><td>X</td><td>X</td></tr> <tr><td>O</td><td>X</td><td>X</td><td>X</td><td>X</td></tr> <tr><td>O</td><td>O</td><td></td><td>X</td><td>X</td></tr> <tr><td>O</td><td>O</td><td>O</td><td>O</td><td>X</td></tr> <tr><td>O</td><td>O</td><td>O</td><td>O</td><td>O</td></tr> </table><p></p>

<p>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.</p>

<p>This game has been part of the MacTutor system <a href="chapBib.html#biBMacTutor">[OR00]</a>.</p>

<p><a id="X17FCFC5858584F46E" name="X17FCFC5858584F46E"></a></p>

<h5>6.12-1 BrowseChangeSides</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; BrowseChangeSides</code>( <var class="Arg"></var> )</td><td class="tdright">( function )</td></tr></table></div>
<p>This function shows the game board in a window.</p>

<p>Each move is encoded as a sequence of three arrow keys; there are 24 admissible inputs.</p>


<table class="example">
<tr><td><pre>
gap&gt; for entry in BrowseChangeSidesSolutions do
&gt;      BrowseData.SetReplay( Concatenation( entry, "Q" ) );
&gt;      BrowseChangeSides();
&gt; od;
gap&gt; BrowseData.SetReplay( false );
</pre></td></tr></table>

<p><em>Implementation remarks</em>: The game board is implemented via a browse table, without row and column labels, with static header, dynamic footer, and individual <code class="code">minyx</code> 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.</p>

<p>The separating lines are drawn using an individual <code class="code">SpecialGrid</code> function in the browse table.</p>

<p>Some standard <code class="func">NCurses.BrowseGeneric</code> (<a href="chap4.html#X85FC163D87FAFD12"><b>4.3-1</b></a>) functionality, such as scrolling, selecting, and searching, are not available in this application.</p>

<p>The code can be found in the file <code class="file">app/knight.g</code> of the package.</p>

<p><a id="X17DDE46668321B5E9" name="X17DDE46668321B5E9"></a></p>

<h4>6.13 <span class="Heading">Sudoku</span></h4>

<p>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 <em>proper Sudoku game</em> is defined as one with a unique solution. Here is an example.</p>

<p></p><table class="sudokuout"> <tr> <td><table class="sudokuin"> <tr> <td></td><td></td><td></td></tr> <tr> <td></td><td>1</td> <td>5</td> </tr> <tr> <td>9</td> <td></td><td></td></tr> </table></td> <td><table class="sudokuin"> <tr> <td></td><td></td><td></td></tr> <tr> <td>4</td> <td></td><td>6</td> </tr> <tr> <td></td><td>5</td> <td></td></tr> </table></td> <td><table class="sudokuin"> <tr> <td>5</td> <td></td><td></td></tr> <tr> <td></td><td>2</td> <td></td></tr> <tr> <td>3</td> <td></td><td></td></tr> </table></td> </tr> <tr> <td><table class="sudokuin"> <tr> <td>6</td> <td></td><td>4</td> </tr> <tr> <td></td><td></td><td></td></tr> <tr> <td>8</td> <td></td><td></td></tr> </table></td> <td><table class="sudokuin"> <tr> <td></td><td></td><td></td></tr> <tr> <td>8</td> <td></td><td></td></tr> <tr> <td>9</td> <td></td><td></td></tr> </table></td> <td><table class="sudokuin"> <tr> <td></td><td></td><td></td></tr> <tr> <td></td><td></td><td></td></tr> <tr> <td></td><td>5</td> <td>3</td> </tr> </table></td> </tr> <tr> <td><table class="sudokuin"> <tr> <td></td><td></td><td></td></tr> <tr> <td></td><td>4</td> <td></td></tr> <tr> <td></td><td></td><td>9</td> </tr> </table></td> <td><table class="sudokuin"> <tr> <td></td><td></td><td>5</td> </tr> <tr> <td></td><td></td><td>7</td> </tr> <tr> <td>1</td> <td></td><td></td></tr> </table></td> <td><table class="sudokuin"> <tr> <td></td><td></td><td></td></tr> <tr> <td></td><td></td><td>2</td> </tr> <tr> <td>8</td> <td></td><td></td></tr> </table></td> </tr> </table><p> The <strong class="pkg">Browse</strong> 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 <code class="func">PlaySudoku</code> (<a href="chap6.html#X17D192244178E86BB4"><b>6.13-7</b></a>) which is implemented using the generic browse functionality described in Chapter <a href="chap4.html#X877E60DE17F53FDEC"><b>4</b></a>.</p>

<p><a id="X1789D3D4C818F4BC2" name="X1789D3D4C818F4BC2"></a></p>

<h5>6.13-1 Sudoku.Init</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; Sudoku.Init</code>( <var class="Arg">[arg]</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p><b>Returns: </b>A record describing a Sudoku board or <code class="keyw">fail</code>.</p>

<p>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 <var class="Arg">arg</var>.</p>


<dl>
<dt><strong class="Mark"><var class="Arg">arg</var> is a string</strong></dt>
<dd><p>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 <code class="code">'1'</code> to <code class="code">'9'</code> or <code class="code">'|'</code> is written in position i of the string. Trailing empty entries can be left out. Afterwards <code class="code">'|'</code>-characters can be inserted in the string (for example to mark line ends). Such strings can be used for <var class="Arg">arg</var>.</p>

</dd>
<dt><strong class="Mark"><var class="Arg">arg</var> is a matrix</strong></dt>
<dd><p>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.</p>

</dd>
<dt><strong class="Mark"><var class="Arg">arg</var> is a list of integers</strong></dt>
<dd><p>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).</p>

</dd>
</dl>

<table class="example">
<tr><td><pre>
gap&gt; game := Sudoku.Init(" 3   68  | 85  1 69|  97   53|      79 |\
&gt;  6  47   |45  2    |89   2 1 | 4   8 7 | ");;
</pre></td></tr></table>

<p><a id="X86A5C6CE179DD67EE" name="X86A5C6CE179DD67EE"></a></p>

<h5>6.13-2 Sudoku.Place</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; Sudoku.Place</code>( <var class="Arg">game, i, n</var> )</td><td class="tdright">( function )</td></tr></table></div>
<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; Sudoku.Remove</code>( <var class="Arg">game, i</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p><b>Returns: </b>The changed <var class="Arg">game</var>.</p>

<p>Here <var class="Arg">game</var> is a record describing a Sudoku board, as returned by <code class="func">Sudoku.Init</code> (<a href="chap6.html#X1789D3D4C818F4BC2"><b>6.13-1</b></a>). The argument <var class="Arg">i</var> is the number of an entry, counted row-wise from 1 to 81, and <var class="Arg">n</var> is an integer from 1 to 9 to be placed on the board. These functions change <var class="Arg">game</var>.</p>

<p><code class="func">Sudoku.Place</code> tries to place number <var class="Arg">n</var> on entry <var class="Arg">i</var>. It is an error if entry <var class="Arg">i</var> is not empty. The number is not placed if <var class="Arg">n</var> is already used in the row, column or subsquare of entry <var class="Arg">i</var>. In this case the component <code class="code">game.impossible</code> is bound.</p>

<p><code class="func">Sudoku.Remove</code> tries to remove the number placed on position <var class="Arg">i</var> of the board. It does not change the board if entry <var class="Arg">i</var> is empty, or if entry <var class="Arg">i</var> was given when the board <var class="Arg">game</var> was created. In the latter case <code class="code">game.impossible</code> is bound.</p>


<table class="example">
<tr><td><pre>
gap&gt; game := Sudoku.Init(" 3   68  | 85  1 69|  97   53|      79 |\
&gt;  6  47   |45  2    |89   2 1 | 4   8 7 | ");;
gap&gt; Sudoku.Place(game, 1, 3);; # 3 is already in first row
gap&gt; IsBound(game.impossible);
true
gap&gt; Sudoku.Place(game, 1, 2);; # 2 is not in row, col or subsquare
gap&gt; IsBound(game.impossible);
false
</pre></td></tr></table>

<p><a id="X8401B31A879F9F9F" name="X8401B31A879F9F9F"></a></p>

<h5>6.13-3 Sudoku.RandomGame</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; Sudoku.RandomGame</code>( <var class="Arg">[seed]</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p><b>Returns: </b>A pair <code class="code">[str, seed]</code> of string and seed.</p>

<p>The optional argument <var class="Arg">seed</var>, if given, must be an integer. If not given some random integer from the current <strong class="pkg">GAP</strong> session is used. This function returns a random proper Sudoku game, where the board is described by a string <code class="code">str</code>, as explained in <code class="func">Sudoku.Init</code> (<a href="chap6.html#X1789D3D4C818F4BC2"><b>6.13-1</b></a>). With the same <var class="Arg">seed</var> the same board is returned.</p>

<p>The games computed by this function have the property that after removing any given entry the puzzle does no longer have a unique solution.</p>


<table class="example">
<tr><td><pre>
gap&gt; Sudoku.RandomGame(5833750);
[ " 1         2     43  2   68   72    8     6 2   1 9 8  8 3   \
9     47 3   7  18  ", 5833750 ]
gap&gt; last = Sudoku.RandomGame(last[2]);
true
</pre></td></tr></table>

<p><a id="X86917AC517C25A68F" name="X86917AC517C25A68F"></a></p>

<h5>6.13-4 Sudoku.SimpleDisplay</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; Sudoku.SimpleDisplay</code>( <var class="Arg">game</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p>Displays a Sudoku board on the terminal. (But see <code class="func">PlaySudoku</code> (<a href="chap6.html#X17D192244178E86BB4"><b>6.13-7</b></a>) for a fancier interface.)</p>


<table class="example">
<tr><td><pre>
gap&gt; game := Sudoku.Init(" 3   68  | 85  1 69|  97   53|      79 |\
&gt;  6  47   |45  2    |89   2 1 | 4   8 7 | ");;
gap&gt; Sudoku.SimpleDisplay(game);
 3 |  6|8  
 85|  1| 69
  9|7  | 53
-----------
   |   |79 
 6 | 47|   
45 | 2 |   
-----------
89 |  2| 1 
 4 |  8| 7 
   |   |   
</pre></td></tr></table>

<p><a id="X17C73C6D08293B3B8" name="X17C73C6D08293B3B8"></a></p>

<h5>6.13-5 Sudoku.OneSolution</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; Sudoku.OneSolution</code>( <var class="Arg">game</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p><b>Returns: </b>A completed Sudoku board that solves <var class="Arg">game</var>, or <code class="keyw">fail</code>.</p>

<p>Here <var class="Arg">game</var> must be a Sudoku board as returned by <code class="func">Sudoku.Init</code> (<a href="chap6.html#X1789D3D4C818F4BC2"><b>6.13-1</b></a>). It is not necessary that <var class="Arg">game</var> 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 <code class="keyw">fail</code> is returned.</p>


<table class="example">
<tr><td><pre>
gap&gt; Sudoku.SimpleDisplay(Sudoku.OneSolution(Sudoku.Init("  3")));
493|876|251
861|542|739
527|193|648
-----------
942|618|573
156|739|482
738|425|916
-----------
289|354|167
375|961|824
614|287|395
</pre></td></tr></table>

<p><a id="X865DDBDC17E16217F" name="X865DDBDC17E16217F"></a></p>

<h5>6.13-6 Sudoku.UniqueSolution</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; Sudoku.UniqueSolution</code>( <var class="Arg">game</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p><b>Returns: </b>A completed Sudoku board that solves <var class="Arg">game</var>, or <code class="keyw">false</code>, or <code class="keyw">fail</code>.</p>

<p>Here <var class="Arg">game</var> must be a Sudoku board as returned by <code class="func">Sudoku.Init</code> (<a href="chap6.html#X1789D3D4C818F4BC2"><b>6.13-1</b></a>). It is not necessary that <var class="Arg">game</var> describes a proper Sudoku game. If it has several solutions, then <code class="keyw">false</code> is returned. If it has no solution, then <code class="keyw">fail</code> is returned. Otherwise a board with the unique solution is returned.</p>


<table class="example">
<tr><td><pre>
gap&gt; s := "      5  | 154 6 2 |9   5 3  |6 4      |   8     |8  9   53\
&gt; |     5   | 4   7  2|  91  8  ";;
gap&gt; sol := Sudoku.UniqueSolution(Sudoku.Init(s));;
gap&gt; Sudoku.SimpleDisplay(sol);
438|219|576
715|436|928
962|758|314
-----------
694|573|281
153|862|749
827|941|653
-----------
281|695|437
546|387|192
379|124|865
</pre></td></tr></table>

<p><a id="X17D192244178E86BB4" name="X17D192244178E86BB4"></a></p>

<h5>6.13-7 PlaySudoku</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; PlaySudoku</code>( <var class="Arg">[arg]</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p><b>Returns: </b>A record describing the latest status of a Sudoku board.</p>

<p>This function allows one to solve Sudoku puzzles interactively. There are several possibilities for the optional argument <var class="Arg">arg</var>. It can either be a string, matrix or list of holes and integers as described in <code class="func">Sudoku.Init</code> (<a href="chap6.html#X1789D3D4C818F4BC2"><b>6.13-1</b></a>), or a board as returned by <code class="func">Sudoku.Init</code> (<a href="chap6.html#X1789D3D4C818F4BC2"><b>6.13-1</b></a>). Furthermore <var class="Arg">arg</var> can be an integer or not be given, in that case <code class="func">Sudoku.RandomGame</code> (<a href="chap6.html#X8401B31A879F9F9F"><b>6.13-3</b></a>) is called to produce a random game.</p>

<p>The usage of this function is self-explanatory, pressing the <strong class="button">?</strong> key displays a help screen. Here, we mention two keys with a particular action: Pressing the <strong class="button">h</strong> 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 <strong class="button">s</strong> key the puzzle is solved by the program or it tells you that there is no or no unique solution.</p>

<p><em>Implementation remarks</em>: The game board is implemented via a browse table, without row and column labels, with static header, dynamic footer, and individual <code class="code">minyx</code> 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.</p>

<p>The separating lines are drawn using an individual <code class="code">SpecialGrid</code> function in the browse table, since they cannot be specified within the generic browse table functions.</p>

<p>Some standard <code class="func">NCurses.BrowseGeneric</code> (<a href="chap4.html#X85FC163D87FAFD12"><b>4.3-1</b></a>) functionality, such as scrolling, selecting, and searching, are not available in this application.</p>

<p>The code can be found in the file <code class="file">app/sudoku.g</code> of the package.</p>

<p><a id="X804D66D617B908F30" name="X804D66D617B908F30"></a></p>

<h5>6.13-8 Sudoku.HTMLGame</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; Sudoku.HTMLGame</code>( <var class="Arg">game</var> )</td><td class="tdright">( function )</td></tr></table></div>
<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; Sudoku.LaTeXGame</code>( <var class="Arg">game</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p><b>Returns: </b>A string with HTML or LaTeX code, respectively.</p>

<p>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.</p>


<div class="chlinkprevnextbot">&nbsp;<a href="chap0.html">Top of Book</a>&nbsp;  &nbsp;<a href="chap5.html">Previous Chapter</a>&nbsp;  &nbsp;<a href="chapA.html">Next Chapter</a>&nbsp;  </div>


<div class="chlinkbot"><span class="chlink1">Goto Chapter: </span><a href="chap0.html">Top</a>  <a href="chap1.html">1</a>  <a href="chap2.html">2</a>  <a href="chap3.html">3</a>  <a href="chap4.html">4</a>  <a href="chap5.html">5</a>  <a href="chap6.html">6</a>  <a href="chapA.html">A</a>  <a href="chapBib.html">Bib</a>  <a href="chapInd.html">Ind</a>  </div>

<hr />
<p class="foot">generated by <a href="http://www.math.rwth-aachen.de/~Frank.Luebeck/GAPDoc">GAPDoc2HTML</a></p>
</body>
</html>