<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
		>
<channel>
	<title>Comments on: Porter Stemming</title>
	<atom:link href="http://programmingpraxis.com/2009/09/08/porter-stemming/feed/" rel="self" type="application/rss+xml" />
	<link>http://programmingpraxis.com/2009/09/08/porter-stemming/</link>
	<description>A collection of etudes, updated weekly, for the education and enjoyment of the savvy programmer</description>
	<lastBuildDate>Sat, 11 Feb 2012 09:48:16 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
	<item>
		<title>By: Code katas &#124; Javouhey&#039;s Blog</title>
		<link>http://programmingpraxis.com/2009/09/08/porter-stemming/#comment-2305</link>
		<dc:creator><![CDATA[Code katas &#124; Javouhey&#039;s Blog]]></dc:creator>
		<pubDate>Sat, 15 Jan 2011 13:39:26 +0000</pubDate>
		<guid isPermaLink="false">http://programmingpraxis.com/?p=1268#comment-2305</guid>
		<description><![CDATA[[...] Praxis porter stemming part1 [...]]]></description>
		<content:encoded><![CDATA[<p>[...] Praxis porter stemming part1 [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Martin Porter</title>
		<link>http://programmingpraxis.com/2009/09/08/porter-stemming/#comment-759</link>
		<dc:creator><![CDATA[Martin Porter]]></dc:creator>
		<pubDate>Tue, 10 Nov 2009 16:47:02 +0000</pubDate>
		<guid isPermaLink="false">http://programmingpraxis.com/?p=1268#comment-759</guid>
		<description><![CDATA[A very nice Programming Praxis example, as here presented. I have created a link to it from the Porter Stemmer page.]]></description>
		<content:encoded><![CDATA[<p>A very nice Programming Praxis example, as here presented. I have created a link to it from the Porter Stemmer page.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Gregory Marton</title>
		<link>http://programmingpraxis.com/2009/09/08/porter-stemming/#comment-602</link>
		<dc:creator><![CDATA[Gregory Marton]]></dc:creator>
		<pubDate>Tue, 08 Sep 2009 12:59:12 +0000</pubDate>
		<guid isPermaLink="false">http://programmingpraxis.com/?p=1268#comment-602</guid>
		<description><![CDATA[#lang scheme
;;; The above should have come with the documentation: 

;; The Porter Stemming Algorithm, somewhat mechanically hand translated to Common Lisp by
;; Steven M. Haflich smh@franz.com Feb 2002.  Subsequently translated to Scheme and made
;; wholly inefficient, if more readable, by Gregory Marton in 2009.

;; This port has only been tested with PLT Scheme, though there is little PLT-specific code.  
;; This code is offered in the hope it will be useful, but with no warranty of correctness, 
;; suitability, usability, or anything else.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; This is the Porter stemming algorithm, as presented ins

;; Porter, 1980, An algorithm for suffix stripping, Program, Vol. 14,
;; no. 3, pp 130-137,

;; only differing from it at the points maked --DEPARTURE-- below.

;; See also http://www.tartarus.org/~martin/PorterStemmer

;; The algorithm as described in the paper could be exactly replicated
;; by adjusting the points of DEPARTURE, but this is barely necessary,
;; because (a) the points of DEPARTURE are definitely improvements, and
;; (b) no encoding of the Porter stemmer I have seen is anything like
;; as exact as this version, even with the points of DEPARTURE!

;; Release 1

;; Note that only lower case sequences are stemmed. Forcing to lower case
;; should be done before stem(...) is called.

;; This implementation is not a particularly fast one.
;; In particular, there is a common optimization to make the many ends-with 
;; tests faster by switching on the last or penultimate letter, which I chose
;; not to use here for the sake of readability.
;; I suspect without proof that the many reversals could be ameliorated by just 
;; reversing the string in the first place and pre-reversing the patterns, or
;; by maintaining a last position in the string vector instead of using a list of 
;; characters.

;;; and the tests, which refer to files that can be found at: 
;;; http://tartarus.org/~martin/PorterStemmer/

(require (planet schematics/schemeunit:3:4))
(require (planet schematics/schemeunit:3/text-ui))
(require &quot;files.ss&quot;)
(require &quot;porter-stemmer.ss&quot;)

(define *the-tests*
  (test-suite
   &quot;stemming&quot;
   (let ((count 0))
     (test-case
      &quot;stemming&quot;
      (for-each-line-in-file 
       &quot;porter-test.txt&quot;
       (lambda (line)
         (set! count (+ 1 count)) (when (integer? (/ count 1000)) (display &quot;.&quot;))
         ;;(display line) (newline)
         (let* ((untab (regexp-split #px&quot;\t&quot; (chomp line)))
                (original (first untab))
                (stemmed (second untab))
                (result (stem original)))
           (check-equal? result stemmed original))))))))

(define num-errors (run-tests *the-tests*))
(define (test) (exit num-errors)) 
(provide test)]]></description>
		<content:encoded><![CDATA[<p>#lang scheme<br />
;;; The above should have come with the documentation: </p>
<p>;; The Porter Stemming Algorithm, somewhat mechanically hand translated to Common Lisp by<br />
;; Steven M. Haflich <a href="mailto:smh@franz.com">smh@franz.com</a> Feb 2002.  Subsequently translated to Scheme and made<br />
;; wholly inefficient, if more readable, by Gregory Marton in 2009.</p>
<p>;; This port has only been tested with PLT Scheme, though there is little PLT-specific code.<br />
;; This code is offered in the hope it will be useful, but with no warranty of correctness,<br />
;; suitability, usability, or anything else.</p>
<p>;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;</p>
<p>;; This is the Porter stemming algorithm, as presented ins</p>
<p>;; Porter, 1980, An algorithm for suffix stripping, Program, Vol. 14,<br />
;; no. 3, pp 130-137,</p>
<p>;; only differing from it at the points maked &#8211;DEPARTURE&#8211; below.</p>
<p>;; See also <a href="http://www.tartarus.org/~martin/PorterStemmer" rel="nofollow">http://www.tartarus.org/~martin/PorterStemmer</a></p>
<p>;; The algorithm as described in the paper could be exactly replicated<br />
;; by adjusting the points of DEPARTURE, but this is barely necessary,<br />
;; because (a) the points of DEPARTURE are definitely improvements, and<br />
;; (b) no encoding of the Porter stemmer I have seen is anything like<br />
;; as exact as this version, even with the points of DEPARTURE!</p>
<p>;; Release 1</p>
<p>;; Note that only lower case sequences are stemmed. Forcing to lower case<br />
;; should be done before stem(&#8230;) is called.</p>
<p>;; This implementation is not a particularly fast one.<br />
;; In particular, there is a common optimization to make the many ends-with<br />
;; tests faster by switching on the last or penultimate letter, which I chose<br />
;; not to use here for the sake of readability.<br />
;; I suspect without proof that the many reversals could be ameliorated by just<br />
;; reversing the string in the first place and pre-reversing the patterns, or<br />
;; by maintaining a last position in the string vector instead of using a list of<br />
;; characters.</p>
<p>;;; and the tests, which refer to files that can be found at:<br />
;;; <a href="http://tartarus.org/~martin/PorterStemmer/" rel="nofollow">http://tartarus.org/~martin/PorterStemmer/</a></p>
<p>(require (planet schematics/schemeunit:3:4))<br />
(require (planet schematics/schemeunit:3/text-ui))<br />
(require &#8220;files.ss&#8221;)<br />
(require &#8220;porter-stemmer.ss&#8221;)</p>
<p>(define *the-tests*<br />
  (test-suite<br />
   &#8220;stemming&#8221;<br />
   (let ((count 0))<br />
     (test-case<br />
      &#8220;stemming&#8221;<br />
      (for-each-line-in-file<br />
       &#8220;porter-test.txt&#8221;<br />
       (lambda (line)<br />
         (set! count (+ 1 count)) (when (integer? (/ count 1000)) (display &#8220;.&#8221;))<br />
         ;;(display line) (newline)<br />
         (let* ((untab (regexp-split #px&#8221;\t&#8221; (chomp line)))<br />
                (original (first untab))<br />
                (stemmed (second untab))<br />
                (result (stem original)))<br />
           (check-equal? result stemmed original))))))))</p>
<p>(define num-errors (run-tests *the-tests*))<br />
(define (test) (exit num-errors))<br />
(provide test)</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Gregory Marton</title>
		<link>http://programmingpraxis.com/2009/09/08/porter-stemming/#comment-601</link>
		<dc:creator><![CDATA[Gregory Marton]]></dc:creator>
		<pubDate>Tue, 08 Sep 2009 12:53:21 +0000</pubDate>
		<guid isPermaLink="false">http://programmingpraxis.com/?p=1268#comment-601</guid>
		<description><![CDATA[(module porter-stemmer scheme

  (define or-map ormap)
  (define and-map andmap)

  (define (consonant? str i)
    (let ((char (list-ref str i)))
      (cond ((member char &#039;(#\a #\e #\i #\o #\u)) #f)
            ((equal? char #\y)
             (if (= i 0) #t (not (consonant? str (- i 1)))))
            (else #t))))
  
  ;; m() measures the number of consonant sequences between k0 and j. if c is
  ;; a consonant sequence and v a vowel sequence, and  indicates arbitrary
  ;; presence,
  
  ;;           gives 0
  ;;    vc     gives 1
  ;;    vcvc   gives 2
  ;;    vcvcvc gives 3
  ;;    ....
  
  (define (num-consonant-sequences str)
    (letrec ((helper (λ(str lim i prefix-ends-in-consonant?)
                       (if (&lt;i&gt;0 stem) (1 stem) (cry in step1b
             (has-vowel? (rest str)))))

  (define (ends-in-double-consonant? str)
    (let ((r (reverse str)))
      (and (&lt; 1 (length str))
           (equal? (first r) (second r))
           (consonant? r 0))))

  ;; cvc(i) is TRUE  i-2,i-1,i has the form consonant - vowel - consonant
  ;; and also if the second c is not w,x or y. this is used when trying to
  ;; restore an e at the end of a short word. e.g.

  ;;    cav(e), lov(e), hop(e), crim(e), but
  ;;    snow, box, tray.
  
  (define (cvc? str)
    (let ((last (- (length str) 1)))
      (and (&lt; 1 last)
           (consonant? str last)
           (not (consonant? str (- last 1)))
           (consonant? str (- last 2))
           (not (member (list-ref str last) &#039;(#\w #\x #\y))))))
  
  (define (cvcv? str)
    (let ((nonvowel (memf (λ(x) (not (member x &#039;(#\a #\e #\i #\o #\u)))) (reverse str))))
      (and nonvowel (cvc? (reverse nonvowel)))))
  
  ;; ends(s) is TRUE  k0,...k ends with the string s.

  (define (starts-with str beginning)
    &quot;true iff beginning is a substring of str starting at 0&quot;
    (or (if (empty? beginning) str false)
        (and (not (empty? str))
             (equal? (first str) (first beginning))
             (starts-with (rest str) (rest beginning)))))
  
  (define (ends-with str ending)
    (let ((stem (starts-with (reverse str) (reverse ending))))
      (if stem (reverse stem) #f)))
  (define (ends str ending)
    (ends-with str (string-&gt;list ending)))

  (define (replace-ending-if str condition ending replacement)
    (let ((stem (ends-with str (string-&gt;list ending))))
      (if stem
          (if (condition stem)
              (append stem (string-&gt;list replacement))
              str)
          #f)))

  (define (-&gt;true any) true)
  (define (rules str proc replacements)
    (or (or-map proc replacements) str))
  
  ;; step1ab() gets rid of plurals and -ed or -ing. e.g.
  
  ;;     caresses  -&gt;  caress
  ;;     ponies    -&gt;  poni
  ;;     ties      -&gt;  ti
  ;;     caress    -&gt;  caress
  ;;     cats      -&gt;  cat
  
  ;;     feed      -&gt;  feed
  ;;     agreed    -&gt;  agree
  ;;     disabled  -&gt;  disable
  
  ;;     matting   -&gt;  mat
  ;;     mating    -&gt;  mate
  ;;     meeting   -&gt;  meet
  ;;     milling   -&gt;  mill
  ;;     messing   -&gt;  mess

  ;;     meetings  -&gt;  meet

  (define (step1a str)
    (rules
     str
     (λ(p) (replace-ending-if str -&gt;true (car p) (cdr p)))
     &#039;((&quot;sses&quot; . &quot;ss&quot;)
       (&quot;ies&quot; . &quot;i&quot;)
       (&quot;ss&quot; . &quot;ss&quot;)
       (&quot;s&quot; . &quot;&quot;))))

  (define (step1b str)
    (let ((ed-ing-stem (or (ends str &quot;ed&quot;) (ends str &quot;ing&quot;))))
      (if ed-ing-stem
          (or (replace-ending-if str m&gt;0 &quot;eed&quot; &quot;ee&quot;)
              (if (has-vowel? ed-ing-stem)
                  (or (replace-ending-if str -&gt;true &quot;ated&quot; &quot;ate&quot;)
                      (replace-ending-if str -&gt;true &quot;ating&quot; &quot;ate&quot;)
                      (replace-ending-if str -&gt;true &quot;bled&quot; &quot;ble&quot;)
                      (replace-ending-if str -&gt;true &quot;bling&quot; &quot;ble&quot;)
                      (replace-ending-if str -&gt;true &quot;ized&quot; &quot;ize&quot;)
                      (replace-ending-if str -&gt;true &quot;izing&quot; &quot;ize&quot;)
                      (if (ends-in-double-consonant? ed-ing-stem)
                          (if (member (list-ref ed-ing-stem (- (length ed-ing-stem) 1)) &#039;(#\l #\s #\z))
                              ed-ing-stem
                              (reverse (rest (reverse ed-ing-stem))))
                          #f)
                      (if (and (m=1 ed-ing-stem) (cvc? ed-ing-stem))
                          (append ed-ing-stem &#039;(#\e))
                          ed-ing-stem))
                  str))
          str)))
                
  ;; step1c() turns terminal y to i when there is another vowel in the stem.
  
  (define (step1c str)
    (or (replace-ending-if str has-vowel? &quot;y&quot; &quot;i&quot;) str))

  ;; step2() maps double suffices to single ones. so -ization ( = -ize plus
  ;; -ation) maps to -ize etc.   Call this function only if the string before the 
  ;; suffix has at least one non-initial consonant-sequence.
  
  (define (step2 str)
    (or 
     (or-map
      (lambda (end-pattern)
        (replace-ending-if str m&gt;0 (car end-pattern) (cdr end-pattern)))
      &#039;((&quot;ational&quot; . &quot;ate&quot;)
        (&quot;tional&quot; . &quot;tion&quot;)
        (&quot;enci&quot; . &quot;ence&quot;)
        (&quot;anci&quot; . &quot;ance&quot;)
        (&quot;izer&quot; . &quot;ize&quot;)
        (&quot;bli&quot; . &quot;ble&quot;)
        ;; -DEPARTURE-
        ;; To match the published algorithm, replace prev line with
        ;; (&quot;abli&quot; . &quot;able&quot;)
        (&quot;alli&quot; . &quot;al&quot;)
        (&quot;entli&quot; . &quot;ent&quot;)
        (&quot;eli&quot; . &quot;e&quot;)
        (&quot;ousli&quot; . &quot;ous&quot;)
        (&quot;ization&quot; . &quot;ize&quot;)
        (&quot;ation&quot; . &quot;ate&quot;)
        (&quot;ator&quot; . &quot;ate&quot;)
        (&quot;alism&quot; . &quot;al&quot;)
        (&quot;iveness&quot; . &quot;ive&quot;)
        (&quot;fulness&quot; . &quot;ful&quot;)
        (&quot;ousness&quot; . &quot;ous&quot;)
        (&quot;aliti&quot; . &quot;al&quot;)
        (&quot;iviti&quot; . &quot;ive&quot;)
        (&quot;biliti&quot; . &quot;ble&quot;)
        (&quot;logi&quot; . &quot;log&quot;) ;; DEPARTURE: the published algorithm does not have this line
        ))
     str))

;; step3() deals with -ic-, -full, -ness etc. similar strategy to step2.


  (define (step3 str)
    (or
     (or-map
      (lambda (end-pattern)
        (replace-ending-if str m&gt;0 (car end-pattern) (cdr end-pattern)))
      &#039;((&quot;icate&quot; . &quot;ic&quot;)
        (&quot;ative&quot; . &quot;&quot;) ; huh?
        (&quot;alize&quot; . &quot;al&quot;)
        (&quot;iciti&quot; . &quot;ic&quot;)
        (&quot;ical&quot; . &quot;ic&quot;)
        (&quot;ful&quot; . &quot;&quot;) ; huh?
        (&quot;ness&quot; . &quot;&quot;) ; huh?
        ))
     str))
    
;; step4() takes off -ant, -ence etc., in context vcvc.    
  
  (define (step4 str)
    (or
     (or-map
      (lambda (ending)
        (replace-ending-if str m&gt;1 ending &quot;&quot;))
      &#039;(&quot;al&quot; &quot;ance&quot; &quot;ence&quot; &quot;er&quot; &quot;ic&quot; &quot;able&quot; &quot;ible&quot; &quot;ant&quot; &quot;ement&quot; &quot;ment&quot; &quot;ent&quot;
             &quot;ou&quot; ;; for -ous
             &quot;ism&quot; &quot;ate&quot; &quot;iti&quot; &quot;ous&quot; &quot;ive&quot; &quot;ize&quot;))
     (replace-ending-if str (λ(stem) (m&gt;1 (append stem &#039;(#\s)))) &quot;sion&quot; &quot;s&quot;)
     (replace-ending-if str (λ(stem) (m&gt;1 (append stem &#039;(#\t)))) &quot;tion&quot; &quot;t&quot;)
     str))

  ;; step5 removes a final -e if m() &gt; 1, and changes -ll to -l if m() &gt; 1.
  (define (step5a str)
    (let ((stem-e (ends str &quot;e&quot;)))
      (if (and stem-e 
               (let ((m (num-consonant-sequences stem-e)))
                 (or (1 str)) &quot;ll&quot; &quot;l&quot;) str))

  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  
  (define (puts . stuff)
    (map display stuff)
    (newline)
    (car (reverse stuff)))
  
  (define (steps str)
    (let* ((zero (puts &quot;step0: &quot; (string-&gt;list str)))
           (one-a (puts &quot;step1a: &quot; (step1a zero)))
           (one-b (puts &quot;step1b: &quot; (step1b one-a)))
           (one-c (puts &quot;step1c: &quot; (step1c one-b)))
           (two (puts &quot;step2: &quot; (step2 one-c)))
           (three (puts &quot;step3: &quot; (step3 two)))
           (four (puts &quot;step4: &quot; (step4 three)))
           (five-a (puts &quot;step5a: &quot; (step5a four)))
           (done (puts &quot;step5b: &quot; (step5b five-a)))
           )
      done))
                  
  ;; In stem(p,i,j), p is a char pointer, and the string to be stemmed is from p[i] to p[j]
  ;; inclusive. Typically i is zero and j is the offset to the last character of a string,
  ;; (p[j+1] == &#039;&#039;). The stemmer adjusts the characters p[i] ... p[j] and returns the new
  ;; end-point of the string, k.  Stemming never increases word length, so i &lt;= k &lt;= j. To
  ;; turn the stemmer into a module, declare &#039;stem&#039; as extern, and delete the remainder of
  ;; this file.
  
  (define (stem str)
    (let ((len (string-length str)))
      (if (string 
           (step5b 
            (step5a
             (step4 
              (step3 
               (step2 
                (step1c 
                 (step1b 
                  (step1a
                   (string-&gt;list str)))))))))))))
  (provide stem)
  
  )]]></description>
		<content:encoded><![CDATA[<p>(module porter-stemmer scheme</p>
<p>  (define or-map ormap)<br />
  (define and-map andmap)</p>
<p>  (define (consonant? str i)<br />
    (let ((char (list-ref str i)))<br />
      (cond ((member char &#8216;(#\a #\e #\i #\o #\u)) #f)<br />
            ((equal? char #\y)<br />
             (if (= i 0) #t (not (consonant? str (- i 1)))))<br />
            (else #t))))</p>
<p>  ;; m() measures the number of consonant sequences between k0 and j. if c is<br />
  ;; a consonant sequence and v a vowel sequence, and  indicates arbitrary<br />
  ;; presence,</p>
<p>  ;;           gives 0<br />
  ;;    vc     gives 1<br />
  ;;    vcvc   gives 2<br />
  ;;    vcvcvc gives 3<br />
  ;;    &#8230;.</p>
<p>  (define (num-consonant-sequences str)<br />
    (letrec ((helper (λ(str lim i prefix-ends-in-consonant?)<br />
                       (if (<i>0 stem) (1 stem) (cry in step1b<br />
             (has-vowel? (rest str)))))</p>
<p>  (define (ends-in-double-consonant? str)<br />
    (let ((r (reverse str)))<br />
      (and (&lt; 1 (length str))<br />
           (equal? (first r) (second r))<br />
           (consonant? r 0))))</p>
<p>  ;; cvc(i) is TRUE  i-2,i-1,i has the form consonant &#8211; vowel &#8211; consonant<br />
  ;; and also if the second c is not w,x or y. this is used when trying to<br />
  ;; restore an e at the end of a short word. e.g.</p>
<p>  ;;    cav(e), lov(e), hop(e), crim(e), but<br />
  ;;    snow, box, tray.</p>
<p>  (define (cvc? str)<br />
    (let ((last (- (length str) 1)))<br />
      (and (&lt; 1 last)<br />
           (consonant? str last)<br />
           (not (consonant? str (- last 1)))<br />
           (consonant? str (- last 2))<br />
           (not (member (list-ref str last) &#039;(#\w #\x #\y))))))</p>
<p>  (define (cvcv? str)<br />
    (let ((nonvowel (memf (λ(x) (not (member x &#039;(#\a #\e #\i #\o #\u)))) (reverse str))))<br />
      (and nonvowel (cvc? (reverse nonvowel)))))</p>
<p>  ;; ends(s) is TRUE  k0,&#8230;k ends with the string s.</p>
<p>  (define (starts-with str beginning)<br />
    &#8220;true iff beginning is a substring of str starting at 0&#8243;<br />
    (or (if (empty? beginning) str false)<br />
        (and (not (empty? str))<br />
             (equal? (first str) (first beginning))<br />
             (starts-with (rest str) (rest beginning)))))</p>
<p>  (define (ends-with str ending)<br />
    (let ((stem (starts-with (reverse str) (reverse ending))))<br />
      (if stem (reverse stem) #f)))<br />
  (define (ends str ending)<br />
    (ends-with str (string-&gt;list ending)))</p>
<p>  (define (replace-ending-if str condition ending replacement)<br />
    (let ((stem (ends-with str (string-&gt;list ending))))<br />
      (if stem<br />
          (if (condition stem)<br />
              (append stem (string-&gt;list replacement))<br />
              str)<br />
          #f)))</p>
<p>  (define (-&gt;true any) true)<br />
  (define (rules str proc replacements)<br />
    (or (or-map proc replacements) str))</p>
<p>  ;; step1ab() gets rid of plurals and -ed or -ing. e.g.</p>
<p>  ;;     caresses  -&gt;  caress<br />
  ;;     ponies    -&gt;  poni<br />
  ;;     ties      -&gt;  ti<br />
  ;;     caress    -&gt;  caress<br />
  ;;     cats      -&gt;  cat</p>
<p>  ;;     feed      -&gt;  feed<br />
  ;;     agreed    -&gt;  agree<br />
  ;;     disabled  -&gt;  disable</p>
<p>  ;;     matting   -&gt;  mat<br />
  ;;     mating    -&gt;  mate<br />
  ;;     meeting   -&gt;  meet<br />
  ;;     milling   -&gt;  mill<br />
  ;;     messing   -&gt;  mess</p>
<p>  ;;     meetings  -&gt;  meet</p>
<p>  (define (step1a str)<br />
    (rules<br />
     str<br />
     (λ(p) (replace-ending-if str -&gt;true (car p) (cdr p)))<br />
     &#8216;((&#8220;sses&#8221; . &#8220;ss&#8221;)<br />
       (&#8220;ies&#8221; . &#8220;i&#8221;)<br />
       (&#8220;ss&#8221; . &#8220;ss&#8221;)<br />
       (&#8220;s&#8221; . &#8220;&#8221;))))</p>
<p>  (define (step1b str)<br />
    (let ((ed-ing-stem (or (ends str &#8220;ed&#8221;) (ends str &#8220;ing&#8221;))))<br />
      (if ed-ing-stem<br />
          (or (replace-ending-if str m&gt;0 &#8220;eed&#8221; &#8220;ee&#8221;)<br />
              (if (has-vowel? ed-ing-stem)<br />
                  (or (replace-ending-if str -&gt;true &#8220;ated&#8221; &#8220;ate&#8221;)<br />
                      (replace-ending-if str -&gt;true &#8220;ating&#8221; &#8220;ate&#8221;)<br />
                      (replace-ending-if str -&gt;true &#8220;bled&#8221; &#8220;ble&#8221;)<br />
                      (replace-ending-if str -&gt;true &#8220;bling&#8221; &#8220;ble&#8221;)<br />
                      (replace-ending-if str -&gt;true &#8220;ized&#8221; &#8220;ize&#8221;)<br />
                      (replace-ending-if str -&gt;true &#8220;izing&#8221; &#8220;ize&#8221;)<br />
                      (if (ends-in-double-consonant? ed-ing-stem)<br />
                          (if (member (list-ref ed-ing-stem (- (length ed-ing-stem) 1)) &#8216;(#\l #\s #\z))<br />
                              ed-ing-stem<br />
                              (reverse (rest (reverse ed-ing-stem))))<br />
                          #f)<br />
                      (if (and (m=1 ed-ing-stem) (cvc? ed-ing-stem))<br />
                          (append ed-ing-stem &#8216;(#\e))<br />
                          ed-ing-stem))<br />
                  str))<br />
          str)))</p>
<p>  ;; step1c() turns terminal y to i when there is another vowel in the stem.</p>
<p>  (define (step1c str)<br />
    (or (replace-ending-if str has-vowel? &#8220;y&#8221; &#8220;i&#8221;) str))</p>
<p>  ;; step2() maps double suffices to single ones. so -ization ( = -ize plus<br />
  ;; -ation) maps to -ize etc.   Call this function only if the string before the<br />
  ;; suffix has at least one non-initial consonant-sequence.</p>
<p>  (define (step2 str)<br />
    (or<br />
     (or-map<br />
      (lambda (end-pattern)<br />
        (replace-ending-if str m&gt;0 (car end-pattern) (cdr end-pattern)))<br />
      &#8216;((&#8220;ational&#8221; . &#8220;ate&#8221;)<br />
        (&#8220;tional&#8221; . &#8220;tion&#8221;)<br />
        (&#8220;enci&#8221; . &#8220;ence&#8221;)<br />
        (&#8220;anci&#8221; . &#8220;ance&#8221;)<br />
        (&#8220;izer&#8221; . &#8220;ize&#8221;)<br />
        (&#8220;bli&#8221; . &#8220;ble&#8221;)<br />
        ;; -DEPARTURE-<br />
        ;; To match the published algorithm, replace prev line with<br />
        ;; (&#8220;abli&#8221; . &#8220;able&#8221;)<br />
        (&#8220;alli&#8221; . &#8220;al&#8221;)<br />
        (&#8220;entli&#8221; . &#8220;ent&#8221;)<br />
        (&#8220;eli&#8221; . &#8220;e&#8221;)<br />
        (&#8220;ousli&#8221; . &#8220;ous&#8221;)<br />
        (&#8220;ization&#8221; . &#8220;ize&#8221;)<br />
        (&#8220;ation&#8221; . &#8220;ate&#8221;)<br />
        (&#8220;ator&#8221; . &#8220;ate&#8221;)<br />
        (&#8220;alism&#8221; . &#8220;al&#8221;)<br />
        (&#8220;iveness&#8221; . &#8220;ive&#8221;)<br />
        (&#8220;fulness&#8221; . &#8220;ful&#8221;)<br />
        (&#8220;ousness&#8221; . &#8220;ous&#8221;)<br />
        (&#8220;aliti&#8221; . &#8220;al&#8221;)<br />
        (&#8220;iviti&#8221; . &#8220;ive&#8221;)<br />
        (&#8220;biliti&#8221; . &#8220;ble&#8221;)<br />
        (&#8220;logi&#8221; . &#8220;log&#8221;) ;; DEPARTURE: the published algorithm does not have this line<br />
        ))<br />
     str))</p>
<p>;; step3() deals with -ic-, -full, -ness etc. similar strategy to step2.</p>
<p>  (define (step3 str)<br />
    (or<br />
     (or-map<br />
      (lambda (end-pattern)<br />
        (replace-ending-if str m&gt;0 (car end-pattern) (cdr end-pattern)))<br />
      &#8216;((&#8220;icate&#8221; . &#8220;ic&#8221;)<br />
        (&#8220;ative&#8221; . &#8220;&#8221;) ; huh?<br />
        (&#8220;alize&#8221; . &#8220;al&#8221;)<br />
        (&#8220;iciti&#8221; . &#8220;ic&#8221;)<br />
        (&#8220;ical&#8221; . &#8220;ic&#8221;)<br />
        (&#8220;ful&#8221; . &#8220;&#8221;) ; huh?<br />
        (&#8220;ness&#8221; . &#8220;&#8221;) ; huh?<br />
        ))<br />
     str))</p>
<p>;; step4() takes off -ant, -ence etc., in context vcvc.    </p>
<p>  (define (step4 str)<br />
    (or<br />
     (or-map<br />
      (lambda (ending)<br />
        (replace-ending-if str m&gt;1 ending &#8220;&#8221;))<br />
      &#8216;(&#8220;al&#8221; &#8220;ance&#8221; &#8220;ence&#8221; &#8220;er&#8221; &#8220;ic&#8221; &#8220;able&#8221; &#8220;ible&#8221; &#8220;ant&#8221; &#8220;ement&#8221; &#8220;ment&#8221; &#8220;ent&#8221;<br />
             &#8220;ou&#8221; ;; for -ous<br />
             &#8220;ism&#8221; &#8220;ate&#8221; &#8220;iti&#8221; &#8220;ous&#8221; &#8220;ive&#8221; &#8220;ize&#8221;))<br />
     (replace-ending-if str (λ(stem) (m&gt;1 (append stem &#8216;(#\s)))) &#8220;sion&#8221; &#8220;s&#8221;)<br />
     (replace-ending-if str (λ(stem) (m&gt;1 (append stem &#8216;(#\t)))) &#8220;tion&#8221; &#8220;t&#8221;)<br />
     str))</p>
<p>  ;; step5 removes a final -e if m() &gt; 1, and changes -ll to -l if m() &gt; 1.<br />
  (define (step5a str)<br />
    (let ((stem-e (ends str &#8220;e&#8221;)))<br />
      (if (and stem-e<br />
               (let ((m (num-consonant-sequences stem-e)))<br />
                 (or (1 str)) &#8220;ll&#8221; &#8220;l&#8221;) str))</p>
<p>  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;</p>
<p>  (define (puts . stuff)<br />
    (map display stuff)<br />
    (newline)<br />
    (car (reverse stuff)))</p>
<p>  (define (steps str)<br />
    (let* ((zero (puts &#8220;step0: &#8221; (string-&gt;list str)))<br />
           (one-a (puts &#8220;step1a: &#8221; (step1a zero)))<br />
           (one-b (puts &#8220;step1b: &#8221; (step1b one-a)))<br />
           (one-c (puts &#8220;step1c: &#8221; (step1c one-b)))<br />
           (two (puts &#8220;step2: &#8221; (step2 one-c)))<br />
           (three (puts &#8220;step3: &#8221; (step3 two)))<br />
           (four (puts &#8220;step4: &#8221; (step4 three)))<br />
           (five-a (puts &#8220;step5a: &#8221; (step5a four)))<br />
           (done (puts &#8220;step5b: &#8221; (step5b five-a)))<br />
           )<br />
      done))</p>
<p>  ;; In stem(p,i,j), p is a char pointer, and the string to be stemmed is from p[i] to p[j]<br />
  ;; inclusive. Typically i is zero and j is the offset to the last character of a string,<br />
  ;; (p[j+1] == &#8221;). The stemmer adjusts the characters p[i] &#8230; p[j] and returns the new<br />
  ;; end-point of the string, k.  Stemming never increases word length, so i &lt;= k &lt;= j. To<br />
  ;; turn the stemmer into a module, declare &#039;stem&#039; as extern, and delete the remainder of<br />
  ;; this file.</p>
<p>  (define (stem str)<br />
    (let ((len (string-length str)))<br />
      (if (string<br />
           (step5b<br />
            (step5a<br />
             (step4<br />
              (step3<br />
               (step2<br />
                (step1c<br />
                 (step1b<br />
                  (step1a<br />
                   (string-&gt;list str)))))))))))))<br />
  (provide stem)</p>
<p>  )</i></p>
]]></content:encoded>
	</item>
</channel>
</rss>

