As an example consider the problem of listing the
primes less than or equal to n you might decompose this into
Net
(Define (Primes N) (RemoveComposite(ListNumbers 1 N)))You can input this first... but it won't work until you define the two subfunctions RemoveComposite and ListNumbers. Try this!
(primes 10)
Next step define one of the subfunctions:
(define (ListNumbers I J)
(if (> I J) NIL
(if (= I J) (list I)
(cons I (ListNumbers (+ 1 I) J))
) ) )Input this and test it like this
ListNumbers
(ListNumbers 1 10)
(trace ListNumbers)
(ListNumbers 5 10)
(untrace ListNumbers)Does this fix 'primes'? Test
(primes 10)
Now we need the function RemoveComposite to remove composite numbers.
Decompose this into two steps/functions: A function that tests for
a composite number and one to to remove numbers that we don't want.
Here is the filter to remove the non-primes:
(removecomposite L):
Net
(define (RemoveComposite L)
(if (NULL L) NIL
(if (composite (car L)) (RemoveComposite (cdr L))
(cons (car L) (RemoveComposite (cdr L)))
) ) )
Again you can test this... and find that composite is not defined.
How can you see if a number is composite? You need to find out if it is divisible by any of the numbers from 2 up to some number less than that number.
The word any above is a clue to the need for a new function that doesn't just try numbers from 2 to n, but numbers from I to n for any I. Suppose this function is called (hasdivisor I N) then we can use it like this to define composite
(define (composite n) (hasdivisor 2 N) )
And if N has a divisor between I and N-1 inclusive then it is either I itself or it is a divisor between I+1 and N-1 inclusive. Further if the square of I is greater than N then we know that there can be NO divisors...
(define (hasdivisor I N)
(if (> (* I I) N) NIL
(if (divides I N) T
(hasdivisor (+ 1 I) N)
) ) )Note. perhaps we don't have to do every integer to find a divisor, but I leave this improvement until some one complains about the speed. Again if you test this you may find that divides is not defined... This is a standard hack: divide and multiply and check for lost remainders:
(define (divides I N) (= (* I (/ N I)) N))Again add this definition and test primes.
Note.... If you actually develop code like this, you can easily lose track of what you have defined and what is needed and so on. It is best to use an editor to develop the code in a file name.lsp and use lisp name.lsp to test it as it develops.
Note... You might decompose this problem in a different way and still get a working program. It may be faster, smaller, smarter, longer, shorter, and etc... This decomposition was created solely to demonstrate the decompose/compose for LISP.
Getting and Loading Existing Programs/Functions
Note.... I made three mistakes when I did the original code, and
fixed them above... the complete code is in
[ primes.lsp ]
Download/save this file (as ASCII in file primes.lsp)
and then run
xlisp primes.lspAnd you will load a LISP system with added functions for handling prime numbers...