Knuth-Morris-Pratt algorithm in Scheme - algorithm

This is the code to calculate the failure function (how many steps we have to go back) in Scheme, when we use the Knuth-Morris-Pratt algorithm:
(define (compute-failure-function p)
(define n-p (string-length p))
(define sigma-table (make-vector n-p 0))
(let loop
((i-p 2)
(k 0))
(cond
((>= i-p n-p)
(vector-set! sigma-table (- n-p 1) k))
((eq? (string-ref p k)
(string-ref p (- i-p 1)))
(vector-set! sigma-table i-p (+ k 1))
(loop (+ i-p 1) (+ k 1)))
((> k 0)
(loop i-p (vector-ref sigma-table k)))
(else ; k=0
(vector-set! sigma-table i-p 0)
(loop (+ i-p 1) k))))
(vector-set! sigma-table 0 -1)
(lambda (q)
(vector-ref sigma-table q)))
But I do not understand the part when k > 0. Can someone explain it please?

I see you're confused with the syntax of a named let. This post does a good job explaining how it works, but perhaps an example with more familiar syntax will make things clearer. Take this code in Python, it adds all integers from 1 to 10:
sum = 0
n = 1
while n <= 10:
sum += n
n += 1
print(sum)
=> 55
Now let's try to write it in a recursive fashion, I'll call my function loop. This is completely equivalent:
def loop(n, sum):
if n > 10:
return sum
else:
return loop(n + 1, n + sum)
loop(1, 0)
=> 55
In the above example, the loop function implements an iteration, the parameter n is used to keep track of the current position, and the parameter sum accumulates the answer. Now let's write the exact same code, but in Scheme:
(let loop ((n 1) (sum 0))
(cond ((> n 10) sum)
(else (loop (+ n 1) (+ n sum)))))
=> 55
Now we've defined a local procedure called loop which is then automatically called with the initial values 1 and 0 for its parameters n and sum. When the base case of the recursion is reached, we return sum, otherwise we keep calling this procedure, passing updated values for the parameters. It's exactly the same as in the Python code! Don't be confused by the syntax.
In your algorithm, i-p and k are the iteration variables, which are initialized to 2 and 0 respectively. Depending on which condition is true, the iteration continues when we call loop again with updated values for i-p and k, or it ends when the case (>= i-p n-p) is reached, at this point the loop exits and the computed value is in the variable sigma-table. The procedure ends by returning a new function, referred to as the "failure function".

Related

How would I go about create this function

How would I create an approximate cos function.
What I have so far.
(define k 0)
(define (approx-cos x n)
(cond
[(> 0 n) 0]
[else (* (/ (expt -1 k) (factorial (* 2 k))) (expt x (* 2 k)))]))
Your solution requires a lot of work before it meets the expectations. For starters, your parameters are switched: the first one is the number you want to calculate and the second one is the number of iterations...
Which leads me to the major problem in your solution, you're not iterating at all! You're supposed to call approx-cos at some point, or some helper procedure to do the looping (as I did).
Last but not least, you're not correctly implementing the formula. Where's the -1 part, for instance? Or where are you multiplying by x^2k? I'm afraid a complete rewrite is in order:
; main procedure
(define (approx-cos x n)
; call helper procedure
(loop 0 0 x n))
; define a helper procedure
(define (loop acc k x n)
; loop with k from 0 to n, accumulating result
(cond [(> k n) acc] ; return accumulator
[else
(loop (+ acc ; update accumulator
(* (/ (expt -1.0 k) ; implement the formula
(factorial (* 2.0 k)))
(expt x (* 2.0 k))))
(add1 k) ; increment iteration variable
x n)]))
This will pass all the check expects:
(approx-cos 0 0)
=> 1
(approx-cos (/ pi 2) 0)
=> 1
(approx-cos 0 10)
=> 1
(approx-cos pi 10)
=> -0.9999999999243502
(approx-cos (* 3 (/ pi 2)) 9)
=> -1.1432910825361444e-05
(approx-cos 10 100)
=> -0.8390715290756897
Some final thoughts: your implementation of factorial is very slow, if you plan to do a larger number of iterations, your factorial will freeze the execution at some point.

Scheme Binomial function using Pascal's Triangle

The binom procedure is suppose to return a function such that ((binom n) k a b) is the kth term in the binomial expansion of (a + b)^n.
This is my code.
(define (pascal row col)
(cond ((= col 1) 1)
((= row col) 1)
(else (+ (pascal (- row 1) (- col 1)) (pascal (- row 1) col)))))
(define (binom n)
(lambda (k a b)
(cond ((or (= n 0) (= n k)) 1)
(else (binom (pascal k n)))) 1))
I am trying to fix the binom function. I think the formula is (n k) * a^k * b^(n-k). How should I write it in Scheme?
I think you got confused with the formulas, you're mixing up n, k, row and col.
I'd recommend writing down the formulas you want to program, name the variables on paper, then write the procedure using the same variable names.
With binom though, I'm not sure what your intent was.
Binom returns a lambda, that's all well and good.
But then in that lambda you make a recursive call to binom,
again returning a lambda? And then at the very end you basically ignore
the result you get from this and return 1?
In its current form binom will never return anything other than a lambda or 1.
Here's what I think you want:
(define (pascal n k)
(cond ((< n k) (error "not defined: k > n"))
((= k 1) n)
((= k 0) 1)
((= n k) 1)
(else (+ (pascal (- n 1) (- k 1)) (pascal (- n 1) k)))))
(define (binom n i a b)
(* (pascal n i) (expt a (- n i)) (expt b i)))

Blocked Matrix Multiplication

I am trying to create a function that performs blocked matrix multiplication in AllegroCL, but I keep getting array-index errors. I believe it is due to the indicies being 0-19 for a side of a 20 x 20 block matrix, but I'm unsure of how to fix it.
Error: Array index 20 too big for dimension 20 while accessing
#.
[condition type: type-error]
Any help or direction is much appreciated. Below is my code thus far.
(defun bmmul (A B)
(let* ((m (car (array-dimensions A)))
(n (cadr (array-dimensions A)))
(l (cadr (array-dimensions B)))
(u 0)
(C (make-array `(,m ,l) :initial-element 0)))
(loop for p from 0 to (- m n) do
(loop for i from (+ 0 1) to n do
(setf u (aref C i 0))
(loop for k from p to (- (+ p n) 1) do
(setf u (* (aref A i k) (aref B k 0))))
(setf (aref C i 0) u)))
C))
In general, when looping over an array index, you go :from 0 :below n, where n is the array dimension, so when the dimension is 20, the index goes from 0 up to and including 19.
Another problem seems to be that in the innermost loop, you want to incf, not setf. You also do not need a temporary variable (u) there, just incf the array cell directly.
Finally, I do not feel that you structured your loops correctly, I do not expect to see a hardcoded 0 index there. The innermost loop body should look like (incf (aref c i j) (* (aref a i k) (aref b k j))), regardless of whether you do ordinary or blocked multiplication.

How to decrement a value in Scheme?

I have a procedure that can find the n smallest primes larger than from
(define (primes_range from to n)
(for ([i (in-range from to)])
(if (> n 0)
(cond ((prime? i) (display i)
(- n 1)))
false)))
I add a parameter n to the procedure primes_range and decrement it during the execution only if a prime was found.
But n not changed. How to fix that?
The idiomatic Scheme way to write this function is to use recursion:
(define (primes-range from to n)
(cond ((>= from to) '())
((<= n 0) '())
((prime? from) (cons from (primes-range (+ from 1) to (- n 1))))
(else (primes-range (+ from 1) to n))))
You can easily spell this out in English:
Base cases:
A prime range where the from is equal or greater to to is empty.
A prime range where n is 0 or less is empty.
Recursive cases:
If from is a prime, then the prime range is from, prepended to the result of calling primes-range starting from (+ from 1) and with (- n 1) elements.
Otherwise, the result is calling primes-range starting from (+ from 1) (still with n elements).

Does newtons method run 40 times?

The following is code that I wrote for newtons method:
(define (newtons-method f guess n)
(define (newtons-method-h guess k)
(if(= k n)
guess
(let ((next (- guess (/ (f guess) ((der f 0.1) guess)))))
(newtons-method-h next (+ k 1)))))
(newtons-method-h guess 0))
As well as code that I wrote to find square roots of numbers using newton's method:
(define (sqrt-newt n)
(newtons-method (lambda (x) (- (* x x) n)) 1.0 40))
I am wondering... Does sqrt-newt call newtons-method for 40 interations? I believe the answer is yes, but I am drawing a blank here.
Just add a counter to you code:
(define counter null) ; define a global variable
(define (newtons-method f guess n)
(define (newtons-method-h guess k)
(set! counter (add1 counter)) ; increment it at each call
(if (= k n)
guess
(let ((next (- guess (/ (f guess) ((der f 0.1) guess)))))
(newtons-method-h next (+ k 1)))))
(set! counter 0) ; initialize it before starting
(newtons-method-h guess 0))
(sqrt-newt 2) ; run the procedure
=> 1.4142135623730951
counter ; check the counter's value
=> 41
As you can see, the newtons-method-h procedure got called 41 times - one more than you expected, because the procedure gets invoked one last time when (= k n) and that's when the recursion ends.

Resources