Arity Mismatch: where to put parameter - scheme

With my code I need to use multiple functions and combine them into one that will evaluate to the nth prime number between a and b. The functions I need to use are gen-consecutive filter value-at-position.
The problem with my code is that with the function gen-consecutive requires 3 parameters a function (f) and a and b which acts as a range, and I am not sure where to put the f argument in my nth-prime-between function.
I keep getting the error "gen-consecutive: arity mismatch" and that it expected 3 arguments (f a b) instead of just 2 arguments (a b)
Here is my code:
(define (nth-prime-between a b n)
(value-at-position filter prime? (gen-consecutive a b)) n)
Here is the other functions:
(define (gen-consecutive f a b)
(if (> a b)
'()
(cons (f a) (gen-consecutive f (+ a 1) b))))
(define (filter f lst)
(cond ((null? lst) '())
((f (car lst))
(cons (car lst) (filter f (cdr lst))))
(else
(filter f (cdr lst)))))
(define (value-at-position lst k)
(cond ((null? lst) lst)
((= k 1) (car lst))
(else (value-at-position (- k 1) (cdr lst)))))

There are 3 mistakes in your program!
I do NOT have a function prime?, therefore I used odd? instead
(define (nth-prime-between a b n)
;; missing parenthesis for the function filter
;; n is value of the function
;; (value-at-position filter odd? (gen-consecutive a b)) n)
(value-at-position (filter odd? (gen-consecutive a b)) n))
;; kill the parameter f
;;
;; (define (gen-consecutive f a b)
;; (if (> a b)
;; '()
;; (cons (f a) (gen-consecutive f (+ a 1) b))))
(define (gen-consecutive a b)
(if (> a b)
'()
(cons a (gen-consecutive (+ a 1) b))))
(define (filter f lst)
(cond ((null? lst) '())
((f (car lst))
(cons (car lst) (filter f (cdr lst))))
(else
(filter f (cdr lst)))))
(define (value-at-position lst k)
(cond ((null? lst) lst)
((= k 1) (car lst))
;; the sequence of (- k 1) and (cdr lst) is wrong
;; (else (value-at-position (- k 1) (cdr lst)))))
(else (value-at-position (cdr lst) (- k 1)))))
(define (odd? N)
(if (= (remainder N 2) 0)
#f
#t))
(nth-prime-between 1 10 3)
The deeper problem with task is:
When you call (nth-prime-between 1000 10000 2),
you must test 9000 numbers with (prime? n). Probably, it is enough to test 10 numbers.
By the way, there exists intervals of any length with no prime numbers in it.
To test a number N with with prime? you need to know the prime numbers less the (square-root N). Where will you store them?
If it is serious task, you can write a program using the sieve of Eratosthenes with a clever stopping condition.

Related

Scheme insertion sort without using primitive functions (car, cdr, cons)

I'm trying to write function for insertion sort with and without primitive functions.
My code with primitive functions is below.
(define (insert n d)
(cond ((null? n) d)
((null? d) n)
(else (< (car n) (car d)) (cons (car n) (insert (cdr n) d)) (cons (car d) (insert (cdr d) n)))))
(define (sort n)
(cond ((null? n) '())
(else (insert (list (car n)) (sort (cdr n))))))
How should I revise insert and sort to not use car, cdr, and cons?
Edit: I tried to write the insert function. This is what I have so far.
(define (insert n d)
(let ((rest-digit (truncate (/ n 10))))
(if (null? n) 0
(+ rest-digit (insert (- n 1) d)))))
(insert '(3 2 1) '5)
Edit #2: I think I can use the built-in function expt.
Ultimately you will be using primitive functions. To illustrate let me show you a trick that actually uses cons, car, and cdr under the hood:
(define (my-car lst)
(apply (lambda (a . d) a) lst))
(define (my-cdr lst)
(apply (lambda (a . d) d) lst))
(define (my-cons a d)
(apply (lambda l l) a d))
(define test (my-cons 1 '(2 3)))
test ; ==> (1 2 3)
(my-car test) ; ==> 1
(my-cdr test) ; ==> (2 3)
This abuses the fact that apply takes a list as the final arguments and that rest arguments are cons-ed onto a list in order. cons doesn't work for all pairs:
(my-cons 1 2) ; ERROR: expected list?, got 1
You can make cons, car, and cdr such that they adher to the same rules as primitive cons, but that they are not made of pairs at all. Barmar suggested closures:
(define (ccons a d)
(lambda (f) (f a d))
(define (ccar cc)
(cc (lambda (a d) a)))
(define (ccdr cc)
(cc (lambda (a d) d)))
(define test2 (ccons 1 2))
test2 ; ==> #<function...>
(ccar test2) ; ==> 1
(ccdr test2) ; ==> 2
This works since a and d gets closed over in the returned function and that function passes those values and thus the function acts as an object with two attributes. The challenge with this is that you cannot just pass a list since only "lists" made with ccons will work with ccar and ccdr.
A less classical way is to use vectors:
(define vtag (make-vector 0))
(define (vcons a d)
(let ((v (make-vector 3)))
(vector-set! v 0 vtag)
(vector-set! v 1 a)
(vector-set! v 2 d)
v))
(define (vcar vl)
(vector-ref vl 1))
(define (vcdr vl)
(vector-ref vl 2))
(define (vpair? vl)
(eq? vtag (vector-ref vl 0)))
Or you can use records:
(define-record-type :rpair
(rcons a d)
rpair?
(a rcar)
(d rcdr))
(define test (rcons 1 2))
(rpair? test) ; ==> #t
(rcar test) ; ==> 1
(rcdr test) ; ==> 2
Now I think records just syntax sugar and abstractions and that under the hood you are doing exactly the same as the vector version with less code, but that isn't a bad thing.
EDIT
So from the comments if the only restriction is to avoid car, cdr, and cons, but no restrictions on their sisters we might as well implement with them:
(define (sort lst)
(define (insert e lst)
(if (null? lst)
(list e)
(let ((a (first lst)))
(if (>= a e)
(list* e lst)
(list* a (insert e (rest lst)))))))
(foldl insert
'()
lst))
(sort '(1 5 3 8 5 0 2))
; ==> (0 1 2 3 5 5 8)
And of course my first suggestion works in its place:
(define (sort lst)
(define (my-car lst)
(apply (lambda (a . d) a) lst))
(define (my-cdr lst)
(apply (lambda (a . d) d) lst))
(define (my-cons a d)
(apply (lambda l l) a d))
(define (insert e lst)
(if (null? lst)
(my-cons e '())
(let ((a (my-car lst)))
(if (>= a e)
(my-cons e lst)
(my-cons a (insert e (my-cdr lst)))))))
(foldl insert
'()
lst))
And of course, using substitution rules you can make it utterly ridiculous:
(define (sort lst)
;; insert element e into lst in order
(define (insert e lst)
(if (null? lst)
((lambda l l) e)
(let ((a (apply (lambda (a . d) a) lst)))
(if (>= a e)
(apply (lambda l l) e lst)
(apply (lambda l l)
a
(insert e (apply (lambda (a . d) d) lst)))))))
;; main loop of sort
;; insert every element into acc
(let loop ((lst lst) (acc '()))
(if (null? lst)
acc
(loop (apply (lambda (a . d) d) lst)
(insert (apply (lambda (a . d) a) lst)
acc)))))

Functional version of deleting nth element in a list in Racket

I want to get a list which has nth version deleted from the original list. I could manage following code which is imperative:
(define (list-removeN slist n)
(define outl '())
(for ((i (length slist)))
(when (not (= i n))
(set! outl (cons (list-ref slist i) outl))))
(reverse outl))
What can be the functional equivalent of this? I tried for/list, but I have to insert #f or at that position, removing which is not ideal because #f or may occur at other positions in list also.
You can do it recursively with an accumulator. Something like
#lang racket
(define (remove-nth lst n)
(let loop ([i 0] [lst lst])
(cond [(= i n) (rest lst)]
[else (cons (first lst) (loop (add1 i) (rest lst)))])))
(remove-nth (list 0 1 2 3 4 5) 3)
(remove-nth (list 0 1 2 3) 3)
(remove-nth (list 0 1 2) 0)
This produces
'(0 1 2 4 5)
'(0 1 2)
'(1 2)
You could do it with for/list but this version traverses the list twice because of the length call.
(define (remove-nth lst n)
(for/list ([i (length lst)]
[elem lst]
#:when (not (= i n)))
elem))
There's also split-at, but again this may not be as optimal as it creates two lists and appends them.
(define (remove-nth lst n)
(let-values ([(left right) (split-at lst n)])
(append left (rest right))))
A typical roll your own implementation that is recursive and uses O(n) time and O(n) space.
(define (remove-nth lst i)
(let aux ((lst lst) (i i))
(cond ((null? lst) '()) ;; what if (< (length lst) i)
((<= i 0) (cdr lst)) ;; what if (< i 0)
(else (cons (car lst)
(aux (cdr lst) (sub1 i)))))))
A interative version that uses append-reverse from srfi-1. O(n) time and O(1) space.
(define (remove-nth lst i)
(let aux ((lst lst) (i i) (acc '()))
(cond ((null? lst) (reverse acc)) ;; what if (< (length lst) i)
((<= i 0) (append-reverse acc (cdr lst))) ;; what if (< i 0)
(else (aux (cdr lst) (sub1 i) (cons (car lst) acc))))))

Scheme quick-sort with filter

I need to write the function (quick-sort pred lst)
lst is the list of numbers to be sorted
pred is the predicate by which the list is ordered, the signature of this predicate is: (lambda (x y) …)
- (quick-sort < lst) will sort ascending (small to large)
- (quick-sort > lst) will sort descending (large to small)
- (quick-sort (lambda (x y) (< (car x) (car y))) lst) will sort a list
with inner lists according to the first element of the inner list, ascending.
I started with regular quick-sort:
(define (quick-sort lst)
(cond
((null? lst) '())
((= (length lst) 1) lst)
(else (append (quick-sort (filter (lambda (n) (< n (car lst))) lst))
(list (car lst))
(quick-sort (filter (lambda (n) (> n (car lst))) lst))))))
And now I'm trying to do this with pred:
(define (quick-sort pred lst)
(define (quick-sort-help lst)
(cond ((null? lst) ())
((= (length lst) 1) lst)
(else
(append (quick-sort-help (filter (lambda (n) (pred n (car lst))) lst))
(list (car lst))
(quick-sort-help (filter (lambda (n) (not(pred n (car lst)))) lst)))))) (quick-sort-help lst))
And I get an infinite recursion or something.
Can you help me solve this problem please?
Thanks!
First of you don't need the helper function quick-sort-help.
It recurs infinitely because you apply your helper function to lst instead cdr lst. In your regular quicksort you have (filter (lambda (n) (< n (car lst))) and (filter (lambda (n) (> n (car lst))). But then in the one with the predicate you have the problem that (not (pred ...) would cover the cases for <= and not < if the predicate is > and vice versa. So it gets stuck because the first element in the list is always equal with itself.
Here a correct quicksort:
(define (qsort f lst)
(if (null? lst)
null
(let ([pivot (car lst)])
(append (qsort f (filter (λ (n) (f n pivot)) (cdr lst)))
(list pivot)
(qsort f (filter (λ (n) (not (f n pivot))) (cdr lst)))))))

Scheme code cond error in Wescheme

Although the following code works perfectly well in DrRacket environment, it generates the following error in WeScheme:
Inside a cond branch, I expect to see a question and an answer, but I see more than two things here.
at: line 15, column 4, in <definitions>
How do I fix this? The actual code is available at http://www.wescheme.org/view?publicId=gutsy-buddy-woken-smoke-wrest
(define (insert l n e)
(if (= 0 n)
(cons e l)
(cons (car l)
(insert (cdr l) (- n 1) e))))
(define (seq start end)
(if (= start end)
(list end)
(cons start (seq (+ start 1) end))))
(define (permute l)
(cond
[(null? l) '(())]
[else (define (silly1 p)
(define (silly2 n) (insert p n (car l)))
(map silly2 (seq 0 (length p))))
(apply append (map silly1 (permute (cdr l))))]))
Another option would be to restructure the code, extracting the inner definitions (which seem to be a problem for WeScheme) and passing around the missing parameters, like this:
(define (insert l n e)
(if (= 0 n)
(cons e l)
(cons (car l)
(insert (cdr l) (- n 1) e))))
(define (seq start end)
(if (= start end)
(list end)
(cons start (seq (+ start 1) end))))
(define (permute l)
(cond
[(null? l) '(())]
[else (apply append (map (lambda (p) (silly1 p l))
(permute (cdr l))))]))
(define (silly1 p l)
(map (lambda (n) (silly2 n p l))
(seq 0 (length p))))
(define (silly2 n p l)
(insert p n (car l)))
The above will work in pretty much any Scheme implementation I can think of, it's very basic, standard Scheme code.
Use local for internal definitions in the teaching languages.
If you post your question both here and at the mailing list,
remember to write you do so. If someone answers here, there
is no reason why persons on the mailing list should take
time to answer there.
(define (insert l n e)
(if (= 0 n)
(cons e l)
(cons (car l)
(insert (cdr l) (- n 1) e))))
(define (seq start end)
(if (= start end)
(list end)
(cons start (seq (+ start 1) end))))
(define (permute2 l)
(cond
[(null? l) '(())]
[else
(local [(define (silly1 p)
(local [(define (silly2 n) (insert p n (car l)))]
(map silly2 (seq 0 (length p)))))]
(apply append (map silly1 (permute2 (cdr l)))))]))
(permute2 '(3 2 1))

Scheme Factorial (fact* l) Question

I'm a newbie at Scheme, so forgive the question: I have a function that calculates the factorials of a list of numbers, but it gives me a period before the last number in the results. Where am I going wrong?
code:
#lang scheme
(define fact
(lambda (n)
(cond
((= n 0) 1)
((= n 1) 1)
(else (* n (fact (- n 1)))))))
(define fact*
(lambda (l)
(cond
((null? (cdr l)) (fact (car l)))
(else
(cons (fact (car l)) (fact* (cdr l)))))))
output:
> (fact* '(3 6 7 2 4 5))
(6 720 5040 2 24 . 120)
What you have done is create an improper list. Try this:
(define fact*
(lambda (l)
(cond
((null? (cdr l)) (list (fact (car l))))
(else
(cons (fact (car l)) (fact* (cdr l)))))))
The addition of the list in the fourth line should make this work as you expect. Better might be the following:
(define fact*
(lambda (l)
(cond
(null? l) '())
(else
(cons (fact (car l)) (fact* (cdr l)))))))
This allows your fact* function to work on the empty list, as well as reducing the number of places where you make a call to fact.
The other answers have pointed out the reason why you get an improper list as a result of your fact* function. I would only like to point out that you could use the higher-order function map:
(define fact*
(lambda (l)
(map fact l))
(fact* '(3 6 7 2 4 5))
map takes a function and a list as arguments and applies the function to every element in the list, producing a new list.
Use append instead of cons. cons is used to construct pairs, which is why you have the "." that is used to separate the elements of a pair. Here's an example:
(define (factorial n)
(if (<= n 1)
1
(* n (factorial (- n 1)))))
(define (factorial-list l)
(if (null? l)
'()
(append (list (factorial (car l)))
(factorial-list (cdr l)))))

Resources