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

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)))))

Related

Arity Mismatch: where to put parameter

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.

Scheme: How to merge two streams

I have got these functions
(define force!
(lambda (thunk)
(thunk)))
(define stream-head
(lambda (s n)
(if (zero? n)
'()
(cons (car s)
(stream-head (force! (cdr s))
(1- n))))))
(define make-stream
(lambda (seed next)
(letrec ([produce (lambda (current)
(cons current
(lambda ()
(produce (next current)))))])
(produce seed))))
(define make-traced-stream
(lambda (seed next)
(letrec ([produce (trace-lambda produce (current)
(cons current
(lambda ()
(produce (next current)))))])
(produce seed))))
(define stream-of-even-natural-numbers
(make-traced-stream 0
(lambda (n)
(+ n 2))))
(define stream-of-odd-natural-numbers
(make-traced-stream 1
(lambda (n)
(+ n 2))))
And I need to make a function that merges the last two, so that if I run
(stream-head (merge-streams stream-of-even-natural-numbers stream-of-odd-natural-numbers) 10)
I must get the output (0 1 2 3 4 5 6 7 8 9).. how is this done?
The best idea I had, which is wrong, have been:
(define merge-streams
(lambda (x y)
(cons (car x)
(merge-streams y (cdr x)))))
Here is a suggestion:
(define (merge-streams s1 s2)
(cond
[(empty-stream? s1) s2)] ; nothing to merge from s1
[(empty-stream? s2) s1)] ; nothing to merge from s2
[else (let ([h1 (stream-car s1)]
[h2 (stream-car s2)])
(cons h1
(lambda ()
(cons h2
(stream-merge (stream-rest s1)
(stream-rest s2))))))]))
It uses some helper functions that must be defined first.

Where is the error in this Scheme program?

I am getting "Error: Invalid lambda: (lambda (insert-all))."
(define permutations
(lambda (L)
(let
((insert-all
(lambda (e Ls)
(let
((insert-one
(lambda (L)
(letrec
((helper
(lambda(L R)
(if (null? R)
(list (append L(list e)R))
(helper (append L (list (car R) ) ) (cdr R) )
))))
(helper '() L)))))
(apply append(map insert-one Ls)))))))
(cond ((null? L) '() )
((null?(cdr L)) (list L))
(else (insert-all (car L) (permutations ((cdr L))))))))
It is supposed to return all permutations of a given list.
The form that you have provided in not valid scheme. Specifically, your highest-level let form does not have a body. You might be thinking that the cond clause is the body but owing to your parenthesis it is not part of the let. Honestly, this is the fault of your formatting. Here is a 'properly' formatted Scheme form:
(define (permutations L)
(let ((insert-all
(lambda (e Ls)
(let ((insert-one
(lambda (L)
(let helper ((L '()) (R L))
(if (null? R)
(list (append L (list e) R))
(helper (append L (list (car R)))
(cdr R)))))))
(apply append (map insert-one Ls))))))
(cond ((null? L) '())
((null? (cdr L)) (list L))
(else (insert-all (car L)
(permutations (cdr L)))))))
At least it compiles and runs, although it doesn't produce the right answer (although I don't know what the proper input it):
> (permutations '(a b c))
((c b a))
> (permutations '((a b) (1 2)))
(((1 2) (a b)))
Here is an implementation that works:
(define (permutations L)
(define (insert-all e Ls)
(apply append
(map (lambda (e)
(map (lambda (x) (cons e x)) Ls))
e)))
(cond ((null? L) '())
((null? (cdr L)) (map list (car L)))
(else (insert-all (car L)
(permutations (cdr L))))))
> (permutations '((a b) (1 2) (x y)))
((a 1 x) (a 1 y) (a 2 x) (a 2 y) (b 1 x) (b 1 y) (b 2 x) (b 2 y))
The basic structure of your code was fine; just the implementation of your insert-one and helper were lacking.

Encapsulating Certain Parts of List

I'm trying to write a procedure that "encapsulates" (i.e. puts in a list) elements of a list between a "separator" element.
(my-proc '(1 + 2))
=> ((1) (2))
(my-proc '(x * y + z ^ 2 + 1 + 5))
=> ((x * y) (z ^ 2) (1) (5))
(my-proc '((x + 1) * y + 5))
=> (((x + 1) * y) (5))
In this case the procedure can be hard-coded to define the + symbol as the separator.
Assume that foldr (fold right operation) is defined, I'd prefer that it'd be in terms of it.
I'm not giving a full solution since this looks really homework-y.
(define (split-expr expr)
(foldr (lambda (e es)
(if (eq? e '+)
<???> ; do split
(cons (cons e (car es))
(cdr es))))
<???> ; what should start be?
es))
Just for fun, here's a version in continuation-passing style (no foldr, probably not suitable as a homework answer):
(define split/cps
(λ (sep ls)
(let loop ([ls ls] [k (λ (item acc)
(if item (cons item acc) acc))])
(cond
[(null? ls)
(k #f '())]
[(eq? sep (car ls))
(loop (cdr ls)
(λ (item acc)
(k #f (if item (cons item acc) acc))))]
[else
(loop (cdr ls)
(λ (item acc)
(k (if item
(cons (car ls) item)
(list (car ls)))
acc)))]))))
Here's another way to do it, also without foldr:
(define split/values
(λ (sep ls)
(let loop ([ls ls])
(cond
[(null? ls)
'()]
[else
(let-values ([(a d) (car-to-sep sep ls)])
(if (null? a)
(loop d)
(cons a (loop d))))]))))
(define car-to-sep
(λ (sep ls)
(let loop ([ls ls] [a '()])
(cond
[(null? ls)
(values '() '())]
[(eq? sep (car ls))
(values '() (cdr ls))]
[else
(let-values ([(a d) (loop (cdr ls) a)])
(values (cons (car ls) a) d))]))))

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))

Resources