Scheme Loop Through a List - scheme

How would I loop this list in scheme?
(define test-document '(
((h e l l o))
((t h i s)(i s)(t e s t))
))
What I tried it only showed the first column.

car and cdr family of functions are your friends to navigate lists. Here are some examples.
(define test-document '(
((h e l l o))
((t h i s)(i s)(t e s t))
))
(car test-document) ;; `((h e l l o))
(caar test-document) ;; `(h e l l o)
(cadr test-document) ;; `((t h i s) (i s) (t e s t))
(car (cadr test-document) ;; `(t h i s)
(cadr (cadr test-document) ;; `(i s)
(caddr (cadr test-document) ;; `(test )
Define a function that will walk the list and call a function for each item that is not a list.
(define (walk-list lst fun)
(if (not (list? lst))
(fun lst)
(if (not (null? lst))
(begin
(walk-list (car lst) fun)
(walk-list (cdr lst) fun)))))
Call it to print each item.
(walk-list test-document print)

What you have is a list of lists of lists:
(define test-document '(((h e l l o)) ((t h i s) (i s) (t e s t))))
To loop over its elements you must create a loop of a loop of a loop. To do so we can use map and curry as follows:
(map (curry map (curry map
(compose string->symbol string-upcase symbol->string)))
test-document)
This produces the following output:
(((H E L L O)) ((T H I S) (I S) (T E S T)))
If your Scheme interpreter doesn't have a built-in curry function then you can define one as follows:
(define (curry func . args)
(lambda x (apply func (append args x))))
Hope this helped.

Were you thinking of something like this?
(define (walk-list lst)
(define (sub-walk lst)
(if (null? lst)
'()
(let ((x (car lst)))
(if (list? x)
(cons (sub-walk x) (sub-walk (cdr lst)))
(apply string-append (map symbol->string lst))))))
(flatten (sub-walk lst)))
then
(walk-list test-document)
=> '("hello" "this" "is" "test")
which you can process using the usual suspects (map, filter, ...).
If your Scheme has no flatten procedure, you can use this one:
(define (flatten lst)
(reverse
(let loop ((lst lst) (res null))
(if (null? lst)
res
(let ((c (car lst)))
(loop (cdr lst) (if (pair? c) (loop c res) (cons c res))))))))

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

How to use self-compose with sort-step to sort

(define (compose f1 f2)
(lambda (p2) (f1 (f2 p2))))
(define (self-compose f n)
(if (= n 1) (compose f f)
(compose f (self-compose f (- n 1)))))
(define (sort-step l f)
(cond ((eq? l '()) '())
((eq? (cdr l) '()) (list (car l)))
((f (car l) (cadr l)) (cons (car l) (sort-step (cdr l) f)))
(else (cons (cadr l) (sort-step (cons (car l) (cddr l)) f)))))
How to use self-compose with sort-step to sort?
Tried:
(define (sort-f l f)
(self-compose (sort-step l f) (length l)))
test:
(sort-f '(8 4 6 5 3) >) ===> arity mismatch;
the expected number of arguments does not match the given number
expected: 1
given: 0
(sort-step l f) is not a function of one argument as compose expects, it's a list.
Since you probably want to "thread" the list through the composition, you need to compose a function that takes a list and returns a list.
You can get one by rearranging sort-step slightly into a curried function:
(define (sort-step f)
(lambda (l)
(cond ((null? l) '())
((null? (cdr l)) l)
((f (car l) (cadr l)) (cons (car l) ((sort-step f) (cdr l))))
(else (cons (cadr l) ((sort-step f) (cons (car l) (cddr l))))))))
Now (sort-step f) is a function from list to list and you can say
(define (sort-f l f)
((self-compose (sort-step f) (length l)) l))
The l param can also be thread by a lambda in the self-compose without rewriting sort-step:
(define (sort-f l f)
((self-compose (lambda (l) (sort-step l f)) (length l)) l))

Function returns other recursive function in Racket

Suppose we have a function f. This function takes as an argument a list l and returns a function of one argument g.Function g takes as an argument x and looking for the x in the list l. If it finds it returns true, else false.
I'm interested in a solution without using the built-in functions.
My start code:
(define (f l)
(lamda (x)
..........
)))
You could go for this:
(define (f l)
(lambda (x)
(and (member x l) #t)))
(define g (f '(a b c e)))
(g 'a)
=> #t
(g 'd)
=> #f
If you need to avoid the built-in member procedure, you can roll your own member?:
(define (member? e l)
(and (not (null? l))
(or (eq? (car l) e) (member? e (cdr l)))))
(define (f l)
(lambda (x)
(member? x l)))
or have member? as an internal procedure, if you prefer:
(define (f l)
(define (member? e l)
(and (not (null? l))
(or (eq? (car l) e) (member? e (cdr l)))))
(lambda (x)
(member? x l)))

Insert element to start of sublist in list of lists

I'm having a little trouble with an assignment. I have to create a procedure that requests a list of lists and an element and proceeds to add the element to the first position in every sublist. I managed to do that and it looks like this:
(define (add-element lst elem)
(foldr cons lst (list elem)))
(define (insert-first lst1 x)
(cond
[(empty? lst1) empty]
[else (local [(define insert (add-element(first lst1) x))]
(cons insert (insert-first (rest lst1) x)))]))
So if you were to type (insert-first '((a b) (c d)) you'd end up with (list (list 'x 'a 'b) (list 'x 'c 'd))
Only problem is that I'm required to code the procedure using map and local. The latter one I think I accomplished but I can't for the life of me figure out a way to use map.
(define (insert-first elt lst)
(map (lambda (x)
(cons elt x))
lst))
then
(insert-first 'x '((a b) (c d)))
=> '((x a b) (x c d))
(define (insert-first lst elem)
(foldr (lambda (x y) (cons (cons elem x) y)) '() lst))
Close to your solution, but map is more naturally suited to the problem than a fold, since you want to want to do something to each element of a list. Use fold when you want to accumulate a value by successively applying a function to elements of that list.
foldr embodies a certain recursion pattern,
(foldr g init [a,b,c,...,z])
= (g a (foldr g init [b,c,...,z]))
....
= (g a (g b (g c ... (g z init) ...)))
if we manually expand the foldr call in your add-element function definition, we get
(add-element lst elem)
= (foldr cons lst (list elem))
= (cons elem (foldr cons lst '()))
= (cons elem lst)
then, looking at your insert-first function, we see it is too following the foldr recursion pattern,
(insert-first lst1 x)
= (foldr (lambda(a r)(cons (add-element a x) r)) empty lst1)
= (foldr (lambda(a r)(cons (cons x a) r)) empty lst1)
But (foldr (lambda(a r) (cons (g a) r)) empty lst) === (map g lst), because to combine sub-terms with cons is to build a list, which is what map does; and so we get
(insert-first lst1 x) = (map (lambda(a)(cons x a)) lst1)
and so we can write
(define (insert-first lst1 x)
(local [(define (prepend-x a) (cons ... ...))]
(map ... ...)))

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.

Resources