source: project/levenshtein/levenshtein.html @ 5835

Last change on this file since 5835 was 5835, checked in by Kon Lovett, 12 years ago

Chgs due to syntax-case support of define-inline

File size: 20.3 KB
Line 
1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2<!-- Generated by eggdoc Revision: 1.20  -->
3<html>
4<head>
5<title>Eggs Unlimited - levenshtein</title><style type="text/css"> <!--
6      CODE {
7            color: #666666;
8          }
9/*   DT.definition EM { font-weight: bold; font-style: normal; } */
10
11     DT.definition { 
12                   background: #eee;
13                   color: black;
14                   padding: 0.2em 1em 0.2em 0.7em;
15                   margin-left: 0.2em;
16border: 1px solid #bbc;
17                   font-family: "Andale Mono", monospace;
18                   /* font-size: 1.2em; */
19                   
20                 }
21     DD {
22                   margin-top: 0.8em;
23                   margin-bottom: 0.8em;
24     }
25     DIV.subsection {
26                    border-top: 1px solid #448;
27                    padding-left: 1em;
28                    margin-bottom: 1.2em;
29     }
30     DIV.subsubsection {
31                    border-top: 1px dotted #99c;
32                    /* border-left: 1px solid #99c; */
33                    padding-left: 1em;
34                    margin-bottom: 1.2em;
35     }
36     DIV.subsubsubsection {
37                    border-top: 1px solid #ddf;
38                    padding-left: 1em;
39                    margin-bottom: 1.2em;
40     }
41
42         DIV.section {
43                 margin-bottom: 1.5em;
44         }
45         a:link {
46                 color: #336;
47         }
48         a:visited { color: #666; }
49         a:active  { color: #966; }
50         a:hover   { color: #669; }
51         body { margin: 0; padding: 0; background: #fff; color: #000; font: 9pt "Lucida Grande", "Verdana", sans-serif; }
52         H2 {
53                 background: #336;
54                 color: #fff;
55                 padding-top: 0.5em;
56                 padding-bottom: 0.5em;
57                 padding-left: 16px;
58                 margin: 0 0 1em 0;
59        }
60        UL LI {
61                list-style: none;
62        }
63        TT {
64                font-family: "Andale Mono", monospace;
65                /* font-size: 1.2em; */
66        }
67        H3 {
68                color: #113;
69                margin-bottom: 0.5em;
70        }
71        H4, H5, H6 {
72                color: #113;
73                margin-bottom: 1.0em;
74        }
75        H5 {
76                font-weight: normal;
77                font-style: italic;
78                font-size: 100%;
79                margin-top: 1.2em;
80        }
81        H6 {
82                font-weight: bold;
83                font-size: 85%;
84                margin-top: 1.2em;
85        }
86     DIV#eggheader {
87         text-align: center;
88                 float: right;
89                 margin-right: 2em;
90     }
91     DIV#header IMG {
92            /* display: block; margin-left: auto; margin-right: auto;  */
93            /* float: right; */
94            border: none;  /* firefox */
95     }
96     DIV#footer {
97                background: #bbd;
98                padding: 0.7em ;
99                border-top: 1px solid #cce;
100     }
101     DIV#footer hr {
102                display: none;
103     }
104     DIV#footer a {
105                float: left;
106     }
107     DIV#revision-history {
108         float: right;
109     }
110     
111     DIV#body {
112                 margin: 1em 1em 1em 16px;
113         }
114
115     DIV#examples PRE {
116       background: #eef;
117       padding: 0.1em;
118       border: 1px solid #aac;
119     }
120     PRE#license, DIV#examples PRE {
121       padding: 0.5em;
122     }
123     DIV#examples PRE {
124       /* font-size: 85%; */
125     }
126     PRE { font-family: "Andale Mono", monospace; }
127     TABLE {
128       background: #eef;
129       padding: 0.2em;
130       border: 1px solid #aac;
131       border-collapse: collapse;
132       width: 100%;
133     }
134     TABLE.symbol-table TD.symbol {
135          width: 15em;
136          font-family: "Andale Mono", monospace;
137          /* font-size: 1.2em; */
138     }
139     TH {
140       text-align: left;
141       border-bottom: 1px solid #aac;
142       padding: 0.25em 0.5em 0.25em 0.5em;
143     } 
144     TD { padding: 0.25em 0.5em 0.25em 0.5em; }
145     --></style></head>
146<body>
147<div id="header">
148<h2>levenshtein</h2>
149<div id="eggheader"><a href="index.html">
150<img src="egg.jpg" alt="[Picture of an egg]" /></a></div></div>
151<div id="body">
152<div class="section">
153<h3>Description</h3>
154<p>Levenshtein edit distance</p></div>
155<div class="section">
156<h3>Author</h3><a href="mailto:klovett@pacbell.net">Kon Lovett</a></div>
157<div class="section">
158<h3>Version</h3>
159<ul>
160<li>1.602 Changes for syntax-case support of define-inline</li>
161<li>1.6.1 Missing means source files for syntax-case module</li>
162<li>1.6 Refactoring</li>
163<li>1.5 Needs misc-extn &gt; 2.0</li>
164<li>1.4 Shared code</li>
165<li>1.3 Major changes</li>
166<li>1.2 Switched to array-lib</li>
167<li>1.1 Requirement for srfi-43 was wrong [Thanks to Benedikt Rosenau]</li>
168<li>1.0 Initial release</li></ul></div>
169<div class="section">
170<h3>Requires</h3>
171<ul>
172<li><a href="utf8.html">utf8</a></li>
173<li><a href="numbers.html">numbers</a></li>
174<li><a href="procedure-surface.html">procedure-surface</a></li>
175<li><a href="miscmacros.html">miscmacros</a></li>
176<li><a href="misc-extn.html">misc-extn</a></li>
177<li><a href="syntax-case.html">syntax-case</a></li>
178<li><a href="vector-lib.html">vector-lib</a></li>
179<li><a href="array-lib.html">array-lib</a></li></ul></div>
180<div class="section">
181<h3>Download</h3><a href="levenshtein.egg">levenshtein.egg</a></div>
182<div class="section">
183<h3>Documentation</h3>
184<p>Levenshtein is a collection of procedures providing various forms of the Levenshtein edit distance calculation.</p>
185<p>The Levenshtein edit distance has been used for areas as diverse as soil sample and language dialect analysis. Not just for text strings.</p>
186<div class="subsection">
187<h4>8-bit Characters Only</h4>
188<p>Performs edit distance calculation for byte strings. All return the total edit cost.</p>
189<dl>
190<pre>(require-extension levenshtein-byte)</pre>
191<dt class="definition"><strong>procedure:</strong> (levenshtein-distance/byte SOURCE TARGET)</dt>
192<dd>
193<p>Calculates the edit distance from the <tt>SOURCE</tt> to the <tt>TARGET</tt>. All costs are unitary.</p></dd>
194<pre>(require-extension levenshtein-transpose-byte)</pre>
195<dt class="definition"><strong>procedure:</strong> (levenshtein-distance/transpose-byte SOURCE TARGET)</dt>
196<dd>
197<p>Calculates the edit distance from the <tt>SOURCE</tt> to the <tt>TARGET</tt>, taking into account the Transpose operation. All costs are unitary.</p></dd></dl></div>
198<div class="subsection">
199<h4>Procedure Means</h4>
200<p>Supplies the arithmetic and string operations for the distance algorithms below.</p>
201<p>Should you wish to supply your own 'means' please see the procedure-surface egg documentation, &quot;levenshtein-*-surface.scm&quot;, and &quot;levenshtein-*-means.scm&quot; in this egg for more information.</p>
202<pre>(require-extension levenshtein-utf8-means)</pre>
203<dt class="definition"><strong>procedure-means:</strong> (levenshtein-utf8-means (levenshtein-sequence-surface))</dt>
204<dd>
205<p>Uses procedures from the utf8 egg.</p></dd>
206<pre>(require-extension levenshtein-octet-means)</pre>
207<dt class="definition"><strong>procedure-means:</strong> (levenshtein-octet-means (levenshtein-sequence-surface))</dt>
208<dd>
209<p>Uses procedures from SRFI-13.</p></dd>
210<pre>(require-extension levenshtein-numbers-means)</pre>
211<dt class="definition"><strong>procedure-means:</strong> (levenshtein-numbers-means (levenshtein-numeric-surface))</dt>
212<dd>
213<p>Uses procedures from the numbers egg.</p></dd>
214<pre>(require-extension levenshtein-gennum-means)</pre>
215<dt class="definition"><strong>procedure-means:</strong> (levenshtein-gennum-means (levenshtein-numeric-surface))</dt>
216<dd>
217<p>Uses only fixnum and flonum procedures.</p></dd>
218<pre>(require-extension levenshtein-fixnum-means)</pre>
219<dt class="definition"><strong>procedure-means:</strong> (levenshtein-fixnum-means (levenshtein-numeric-surface))</dt>
220<dd>
221<p>Uses only fixnum procedures.</p></dd></div>
222<div class="subsection">
223<h4>Generic String</h4>
224<p>Performs edit distance calculation for strings.</p>
225<pre>(require-extension levenshtein-generic-string)</pre>
226<dt class="definition"><strong>procedure:</strong> (levenshtein-distance/generic-string SOURCE TARGET [#:insert-cost 1] [#:delete-cost 1] [#:substitute-cost 1] [#:=? char=?] [#:limit-cost #f] [#:numeric-means levenshtein-fixnum-means] [#:string-means levenshtein-octet-means])</dt>
227<dd>
228<p>Calculates the edit distance from the <tt>SOURCE</tt> to the <tt>TARGET</tt>.</p><table class="symbol-table">
229<tr>
230<td class="symbol">SOURCE</td>
231<td>
232<p>A string.</p></td></tr>
233<tr>
234<td class="symbol">TARGET</td>
235<td>
236<p>A string.</p></td></tr>
237<tr>
238<td class="symbol">insert-cost:</td>
239<td>
240<p>A number. The edit cost of an insert.</p></td></tr>
241<tr>
242<td class="symbol">delete-cost:</td>
243<td>
244<p>A number. The edit cost of a delete.</p></td></tr>
245<tr>
246<td class="symbol">substitute-cost:</td>
247<td>
248<p>A number. The edit cost of a substitute.</p></td></tr>
249<tr>
250<td class="symbol">=?:</td>
251<td>
252<p>A procedure; (-&gt; object object boolean). The equality predicate. Probably not useful to override the default predicate.</p></td></tr>
253<tr>
254<td class="symbol">limit-cost:</td>
255<td>
256<p>A number or #f. Limit edit distance calculation to cost. Number type must be compatible with the numeric-means.</p></td></tr>
257<tr>
258<td class="symbol">numeric-means:</td>
259<td>
260<p>A procedure-means. The arithmetic means.</p></td></tr>
261<tr>
262<td class="symbol">string-means:</td>
263<td>
264<p>A procedure-means. The string means.</p></td></tr></table></dd></div>
265<div class="subsection">
266<h4>Generic Sequence</h4>
267<pre>(require-extension levenshtein-generic-sequence)</pre>
268<dt class="definition"><strong>procedure:</strong> (levenshtein-distance/generic-sequence SOURCE TARGET [#:insert-cost 1] [#:delete-cost 1] [#:substitute-cost 1] [#:get-work-vector make-vector] [#:=? eqv?] [#:limit-cost #f] [#:numeric-means levenshtein-fixnum-means] [#:string-means levenshtein-octet-means])</dt>
269<dd>
270<p>Calculates the edit distance from the <tt>SOURCE</tt> to the <tt>TARGET</tt>.</p><table class="symbol-table">
271<tr>
272<td class="symbol">SOURCE</td>
273<td>
274<p>A vector, string, or list.</p></td></tr>
275<tr>
276<td class="symbol">TARGET</td>
277<td>
278<p>A vector, string, or list.</p></td></tr>
279<tr>
280<td class="symbol">insert-cost:</td>
281<td>
282<p>A number. The edit cost of an insert.</p></td></tr>
283<tr>
284<td class="symbol">delete-cost:</td>
285<td>
286<p>A number. The edit cost of a delete.</p></td></tr>
287<tr>
288<td class="symbol">substitute-cost:</td>
289<td>
290<p>A number. The edit cost of a substitute.</p></td></tr>
291<tr>
292<td class="symbol">get-work-vector:</td>
293<td>
294<p>A procedure; (-&gt; number vector). Returns a work vector of length 'number', or larger.</p></td></tr>
295<tr>
296<td class="symbol">=?:</td>
297<td>
298<p>A procedure; (-&gt; object object boolean). The equality predicate. Must handle the types of the source &amp; target elements in either argument position!</p></td></tr>
299<tr>
300<td class="symbol">limit-cost:</td>
301<td>
302<p>A number or #f. Limit edit distance calculation to cost. Number type must be compatible with the numeric-means.</p></td></tr>
303<tr>
304<td class="symbol">numeric-means:</td>
305<td>
306<p>A procedure-means. The arithmetic means.</p></td></tr>
307<tr>
308<td class="symbol">string-means:</td>
309<td>
310<p>A procedure-means. The string means. Used when source and/or target are strings.</p></td></tr></table></dd></div>
311<div class="subsection">
312<h4>Only Vector - Baroque &amp; Slow</h4>
313<p>Performs edit distance calculation for vectors. Allows definition of new edit operations. Will keep track of edit operations performed.</p>
314<dl>
315<pre>(require-extension levenshtein-vector)</pre>
316<dt class="definition"><strong>procedure:</strong> (levenshtein-distance/vector* SOURCE TARGET [EDIT-OPER ...] [#:=? char=?] [#:operations #f] [#:numeric-means levenshtein-fixnum-means])</dt>
317<dd>
318<p>Calculates the edit distance from the source vector <tt>SOURCE</tt> to the target vector <tt>TARGET</tt>. Returns the total edit cost or (values &lt;total edit cost&gt; &lt;performed operations matrix&gt;).</p><table class="symbol-table">
319<tr>
320<td class="symbol">SOURCE</td>
321<td>
322<p>A vector.</p></td></tr>
323<tr>
324<td class="symbol">TARGET</td>
325<td>
326<p>A vector.</p></td></tr>
327<tr>
328<td class="symbol">EDIT-OPER</td>
329<td>
330<p>Edit operation definitions to apply. Defaults are the basic Insert, Delete, and Substitute.</p></td></tr>
331<tr>
332<td class="symbol">=?:</td>
333<td>
334<p>A procedure; (-&gt; object object boolean). The equality predicate.</p></td></tr>
335<tr>
336<td class="symbol">operations:</td>
337<td>
338<p>A boolean. Include the matrix of edit operations performed?</p></td></tr>
339<tr>
340<td class="symbol">numeric-means:</td>
341<td>
342<p>A procedure-means. The arithmetic means.</p></td></tr></table></dd>
343<pre>(require-extension levenshtein-path-iterator)</pre>
344<dt class="definition"><strong>procedure:</strong> (levenshtein-path-iterator MATRIX)</dt>
345<dd>
346<p>Creates an optimal edit distance operation path iterator over the performed operations matrix <tt>MATRIX</tt>. The matrix is usually the result of an invocation of '(levenshtein-distance/vector* ... operations: #t)'.</p>
347<p>Each invocation of the iterator will generate a list of the form: ((cost source-index target-index levenshtein-operator) ...). The last invocation will return #f.</p></dd></dl></div>
348<div class="subsection">
349<h4>Edit operations</h4>
350<p>Edit operation specification. A set of base operations is predefined, but may be overridden. The base set is identified by the keys Insert, Delete, Substitute, and Transpose. A printer and reader are provided for edit operations.</p>
351<pre>(require-extension levenshtein-operators)</pre>
352<dl>
353<dt class="definition"><strong>record:</strong> levenshtein-operator</dt>
354<dd><table class="symbol-table">
355<tr>
356<td class="symbol">key</td>
357<td>
358<p>A symbol. Key for the operation.</p></td></tr>
359<tr>
360<td class="symbol">name</td>
361<td>
362<p>A string. Describes the operation.</p></td></tr>
363<tr>
364<td class="symbol">cost</td>
365<td>
366<p>A number. The cost of the operation.</p></td></tr>
367<tr>
368<td class="symbol">above</td>
369<td>
370<p>A non-negative fixnum. How far back in the source.</p></td></tr>
371<tr>
372<td class="symbol">left</td>
373<td>
374<p>A non-negative fixnum. How far back in the target</p></td></tr></table></dd>
375<dt class="definition"><strong>procedure:</strong> (make-levenshtein-operator KEY NAME COST ABOVE LEFT)</dt>
376<dd>
377<p>Returns a new edit operator.</p></dd>
378<dt class="definition"><strong>procedure:</strong> (levenshtein-operator? OBJECT)</dt>
379<dd>
380<p>Is the <tt>OBJECT</tt> a levenshtein operator?</p></dd>
381<dt class="definition"><strong>procedure:</strong> (clone-levenshtein-operator EDIT-OPERATION [#:key] [#:name] [#:cost] [#:above] [#:left])</dt>
382<dd>
383<p>Returns a duplicate of the <tt>EDIT-OPERATION</tt>, with field values provided by the optional keyword arguments. EDIT-OPERATION may be the key of the already defined edit operation.</p></dd>
384<dt class="definition"><strong>procedure:</strong> (levenshtein-operator-ref KEY)</dt>
385<dd>
386<p>Get the definition of an edit operation.</p></dd>
387<dt class="definition"><strong>procedure:</strong> (levenshtein-operator-set! EDIT-OPERATION)</dt>
388<dd>
389<p>Define an edit operation.</p></dd>
390<dt class="definition"><strong>procedure:</strong> (levenshtein-operator-delete! EDIT-OPERATION)</dt>
391<dd>
392<p>Removes the <tt>EDIT-OPERATION</tt> definition. EDIT-OPERATION may be the key of the already defined edit operation.</p></dd>
393<dt class="definition"><strong>procedure:</strong> (levenshtein-operator-reset)</dt>
394<dd>
395<p>Restore defined edit operations to the base set.</p></dd>
396<dt class="definition"><strong>procedure:</strong> (levenshtein-operator-equal? A B)</dt>
397<dd>
398<p>Are the levenshtein operators <tt>A</tt> &amp; <tt>B</tt> equal for all fields?</p></dd></dl></div>
399<div class="subsection">
400<h4>Version 1.2 Compatibility</h4>
401<pre>(require-extension levenshtein)</pre>
402<p>Warning - The numbers and utf8 eggs will be used!</p>
403<dl>
404<dt class="definition"><strong>macro:</strong> (levenshtein-distance/string SOURCE TARGET [EQ INSERT-COST DELETE-COST SUBSTITUTE-COST])</dt>
405<dd>
406<p>Calculates the edit distance from the source string <tt>SOURCE</tt> to the target string <tt>TARGET</tt>. The default equivalence procedure <tt>EQ</tt> is 'char=?'. The default costs <tt>INSERT-COST</tt>, <tt>DELETE-COST</tt>, and <tt>SUBSTITUTE-COST</tt> are unitary.</p></dd>
407<dt class="definition"><strong>macro:</strong> (levenshtein-distance/list SOURCE TARGET [EQ INSERT-COST DELETE-COST SUBSTITUTE-COST])</dt>
408<dd>
409<p>Calculates the edit distance from the source list <tt>SOURCE</tt> to the target list <tt>TARGET</tt>. The default equivalence procedure <tt>EQ</tt> is 'equal?'. The default costs <tt>INSERT-COST</tt>, <tt>DELETE-COST</tt>, and <tt>SUBSTITUTE-COST</tt> are unitary.</p></dd>
410<dt class="definition"><strong>macro:</strong> (levenshtein-distance/vector SOURCE TARGET [EQ INSERT-COST DELETE-COST SUBSTITUTE-COST])</dt>
411<dd>
412<p>Calculates the edit distance from the source vector <tt>SOURCE</tt> to the target vector <tt>TARGET</tt>. The default equivalence procedure <tt>EQ</tt> is 'equal?'. The default costs <tt>INSERT-COST</tt>, <tt>DELETE-COST</tt>, and <tt>SUBSTITUTE-COST</tt> are unitary.</p></dd>
413<dt class="definition"><strong>macro:</strong> (levenshtein-distance/sequence SOURCE TARGET [EQ INSERT-COST DELETE-COST SUBSTITUTE-COST])</dt>
414<dd>
415<p>Calculates the edit distance from the source sequence <tt>SOURCE</tt> to the target sequence <tt>TARGET</tt>. The default equivalence procedure <tt>EQ</tt> is 'char=?'. The default costs <tt>INSERT-COST</tt>, <tt>DELETE-COST</tt>, and <tt>SUBSTITUTE-COST</tt> are unitary.</p></dd>
416<dt class="definition"><strong>macro:</strong> (levenshtein-distance/scratch SOURCE TARGET [GET-SCRATCH EQ INSERT-COST DELETE-COST SUBSTITUTE-COST])</dt>
417<dd>
418<p>Calculates the edit distance from the source vector <tt>SOURCE</tt> to the target vector <tt>TARGET</tt>. The default equivalence procedure <tt>EQ</tt> is 'equal?'. The default costs <tt>INSERT-COST</tt>, <tt>DELETE-COST</tt>, and <tt>SUBSTITUTE-COST</tt> are unitary. The default get-scratch procedure <tt>GET-SCRATCH</tt> is make-vector.</p>
419<p>Few, if any, programs will use this procedure directly. This is like levenshtein-distance/vector, but allows get-scratch to be specified. get-scratch is a procedure of one term, n, that yields a vector of length n or greater, which is used for record-keeping during execution of the Levenshtein algorithm. make-vector can be used for get-scratch, although some programs comparing a large size or quantity of vectors may wish to reuse a record-keeping vector, rather than each time allocating a new one that will need to be garbage-collected.</p></dd></dl></div></div>
420<div class="section">
421<h3>Examples</h3>
422<div id="examples">
423<pre>(use levenshtein-vector levenshtein-path-iterator)
424
425(define iter
426  (levenshtein-path-iterator
427    (levenshtein-distance/vector* &quot;YWCQPGK&quot; &quot;LAWYQQKPGKA&quot; operations: #t))
428; ignoring interpreter feedback
429(define r0 (iter))
430(define t0 r0)
431(define r1 (iter))
432(define r2 (iter))
433(define r3 (iter))
434(define r4 (iter))
435(define r5 (iter))
436(iter)
437; r0 now has #f, since the iterator finishes by returning to the initial caller, which is the
438; body of '(define r0 (iter))', thus re-binding r0. However, t0 has the original returned value.
439
440; Please see the 'levenshtein*test.scm' files in the levenshtein egg for more examples.</pre></div></div>
441<div class="section">
442<h3>References</h3>
443<p><a href="http://www.uni-bielefeld.de/(en)/ZIF/FG/2002Combinatorics/02-reception.html">Pictures of Pr. Levenstein</a></p>
444<p><a href="http://en.wikipedia.org/wiki/Levenshtein_distance">Levenshtein distance @ Wikipedia</a></p>
445<p><a href="http://www-igm.univ-mlv.fr/~lecroq/seqcomp/node2.html">Levenshtein Distance</a></p>
446<p><a href="http://www.reference.com/browse/wiki/Levenshtein_distance">Levenshtein distance</a></p>
447<p><a href="http://en.wikipedia.org/wiki/Talk:Levenshtein_distance">Talk:Levenshtein distance @ Wikipedia</a></p></div>
448<div class="section">
449<h3>License</h3>
450<pre>Copyright (c) 2005, 2006, Kon Lovett.  All rights reserved.
451
452Permission is hereby granted, free of charge, to any person obtaining a
453copy of this software and associated documentation files (the Software),
454to deal in the Software without restriction, including without limitation
455the rights to use, copy, modify, merge, publish, distribute, sublicense,
456and/or sell copies of the Software, and to permit persons to whom the
457Software is furnished to do so, subject to the following conditions:
458
459The above copyright notice and this permission notice shall be included
460in all copies or substantial portions of the Software.
461
462THE SOFTWARE IS PROVIDED ASIS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
463IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
464FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
465THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
466OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
467ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
468OTHER DEALINGS IN THE SOFTWARE.</pre></div></div>
469<div id="footer">
470<hr /><a href="index.html">&lt; Egg index</a>
471<div id="revision-history">$Revision$ $Date$</div>&nbsp;</div></body></html>
Note: See TracBrowser for help on using the repository browser.