Operating on Nested Lists - scheme

I have a nested list structure of arbitrary length, with a depth of three. The first level has arbitrary length, as does the second level, but the third level is guaranteed to have a uniform length across the whole thing. An example of said structure would be '(((A B) (C D)) ((E F) (G H)) ((I J))).
I'm trying to write a function that would apply another function across the different levels of the structure (sorry, I don't really know how to phrase that). An example of the function mapping across the example structure would be in this order:
f A C = AC, f B D = BD, f E G = EG, f F H = FH, f I = I, f J = J,
yielding
'((AC BD) (EG FH) (I J))
but imagining that the third level of the list contains many more elements (say, around 32,000 in the final version).
Essentially, what I'm trying to do would be expressed in Haskell as something like f . transpose. I know I need something like (map car (map flatten (car ...))) to get the first part of the first section, but after that, I'm really lost with the logic here. I'm sorry if this is a really convoluted, poorly explained question. I'm just really lost.
How would I go about applying the function across the structure in this manner?

(define l '(((A B)
(C D))
((E F)
(G H))
((I J)))
)
(define zip (lambda lists (apply map list lists)))
(define (f values) (list 'f values))
(map (lambda (v) (map (lambda values (apply f values)) (apply zip v))) l)
prints
(((f (a c)) (f (b d))) ((f (e g)) (f (f h))) ((f (i)) (f (j))))

It would be much easier to define your f as a function that takes in a list of values. If not, then the last form is easy to add apply to, but it doesn't make it better. (Using a rest argument means that the language will have to create these lists anyway.)
#lang racket
(define data '(((A B) (C D)) ((E F) (G H)) ((I J))))
(define (f xs) (string->symbol (string-append* (map symbol->string xs))))
(map (λ (pairs)
(list (f (map first pairs))
(f (map second pairs))))
data)
(map (λ (pairs) (map f (apply map list pairs)))
data)
(for/list ([pairs (in-list data)])
(for/list ([xs (in-list (apply map list pairs))])
(f xs)))

Related

reverse a general list using scheme

I am trying to reverse a general list using Scheme. How can I reverse a complex list?
I can make a single list like (A B C D) works using my function, but for some complex list inside another list like (F ((E D) C B) A), the result is just (A ((E D) C B) F). How can I improve it?
(define (reverse lst)
(if (null? lst)
lst
(append (reverse (cdr lst)) (list (car lst)))))
Any comments will be much appreciated!
Here is another way that uses a default parameter (r null) instead of the expensive append operation -
(define (reverse-rec a (r null))
(if (null? a)
r
(reverse-rec (cdr a)
(cons (if (list? (car a))
(reverse-rec (car a))
(car a))
r))))
(reverse-rec '(F ((E D) C B) A))
; '(A (B C (D E)) F)
Using a higher-order procedure foldl allows us to encode the same thing without the extra parameter -
(define (reverse-rec a)
(foldl (lambda (x r)
(cons (if (list? x) (reverse-rec x) x)
r))
null
a))
(reverse-rec '(F ((E D) C B) A))
; '(A (B C (D E)) F)
There are several ways of obtaining the expected result. One is to call reverse recursively also on the car of the list that we are reversing, of course taking care of the cases in which we must terminate the recursion:
(define (reverse x)
(cond ((null? x) '())
((not (list? x)) x)
(else (append (reverse (cdr x)) (list (reverse (car x)))))))
(reverse '(F ((E D) C B) A))
'(A (B C (D E)) F)
(A ((E D) C B) F) is the correct result, if your goal is to reverse the input list. There were three elements in the input list, and now the same three elements are present, in reverse order. Since it is correct, I don't suggest you improve its behavior!
If you have some other goal in mind, some sort of deep reversal, you would do well to specify more clearly what result you want, and perhaps a solution will be easier to find then.

Repeat the string list in Scheme language

I'm trying to make a code with Scheme language.I want to input a list and return the string representation of the list where the first element is repeated one time, the second element repeats two times and third element repeats three times like
input is => (c d g)
output is => (c d d g g g)
I wrote a code with duplicating all elements. I should use loop for making repeat all elements from first one to last one with 1 to n times.(n is size of list). But I do not know how.
(define repeat
(lambda (d)
(cond [(null? d) '()]
[(not (pair? (car d)))
(cons (car d)
(cons (car d)
(repeat (cdr d))))]
[else (cons (repeat (car d))
(repeat (cdr d)))])))
(repeat '(a b c d e)) => aa bb cc dd ee
(define size
(lambda (n)
(if (null? n)
0
(+ 1 (size (cdr n))))))
(size '(A B C D)) => 4
You will need to make a few different functions for this.
repeat (as you described) acts like this (repeat '(c d g)) ;=> (c d d g g g)
The best way to implement that is using a helper (repeat-aux n lst) which repeats the first element n times, the second element n+1 times and so on.
Given that you can define:
(define (repeat lst) (repeat-aux 1 lst))
To implement repeat-aux you can use a recursion pattern like this
(define (repeat-aux n lst)
(if (null? lst)
'()
... (repeat-aux (+ n 1) (cdr lst) ...))
I'm just giving a sketch or outline of the function, not the whole thing. So that you can work on it yourself.
To implement repeat-aux I would also recommend making a helping function (replicate n elt tail) which works like this:
(replicate 3 'o '(u v w)) ;=> (o o o u v w)
I hope the idea of breaking it down into simple helper function makes it easier. Have a go and feel free to ask if you get stuck.

Apply procedure on previous result

Given a list of lists as an input, I want to execute a procedure such that the final result would be:
(define (thing . lists) ; list of lists (l1 l2 ... lN)
;returns ...f(f(f(l1 l2) l3) lN)...
)
So for example:
(thing '(a b) '(c d) '(e f))
...would result in f(f((a b) (c d)) (e f))
I am fighting with folding, lambda, apply and map, but I can't figure out right way.
Assuming that the input has at least two lists and that f was previously defined:
(define (thing . lists)
(foldr (lambda (lst acc)
(f acc lst))
(f (car lists) (cadr lists))
(cddr lists)))
For example:
(define f append)
(thing '(a b) '(c d) '(e f))
=> '(a b c d e f)

Y Combinator implementation Scheme

I am really new to scheme functional programming. I recently came across Y-combinator function in lambda calculus, something like this Y ≡ (λy.(λx.y(xx))(λx.y(xx))). I wanted to implement it in scheme, i searched alot but i didn't find any implementation which exactly matches the above given structure. Some of them i found are given below:
(define Y
(lambda (X)
((lambda (procedure)
(X (lambda (arg) ((procedure procedure) arg))))
(lambda (procedure)
(X (lambda (arg) ((procedure procedure) arg)))))))
and
(define Y
(lambda (r)
((lambda (f) (f f))
(lambda (y)
(r (lambda (x) ((y y) x)))))))
As you can see, they dont match with the structure of this Y ≡ (λy.(λx.y(xx))(λx.y(xx))) combinator function. How can I implement it in scheme in exactly same way?
In a lazy language like Lazy Racket you can use the normal order version, but not in any of the applicative order programming languages like Scheme. They will just go into an infinite loop.
The applicative version of Y is often called a Z combinator:
(define Z
(lambda (f)
((lambda (g) (g g))
(lambda (g)
(f (lambda args (apply (g g) args)))))))
Now the first thing that happens when this is applied is (g g) and since you can always substitute a whole application with the expansion of it's body the body of the function can get rewritten to:
(define Z
(lambda (f)
((lambda (g)
(f (lambda args (apply (g g) args))))
(lambda (g)
(f (lambda args (apply (g g) args)))))))
I haven't really changed anything. It's just a little more code that does exactly the same. Notice this version uses apply to support multiple argument functions. Imagine the Ackermann function:
(define ackermann
(lambda (m n)
(cond
((= m 0) (+ n 1))
((= n 0) (ackermann (- m 1) 1))
(else (ackermann (- m 1) (ackermann m (- n 1)))))))
(ackermann 3 6) ; ==> 509
This can be done with Z like this:
((Z (lambda (ackermann)
(lambda (m n)
(cond
((= m 0) (+ n 1))
((= n 0) (ackermann (- m 1) 1))
(else (ackermann (- m 1) (ackermann m (- n 1))))))))
3
6) ; ==> 509
Notice the implementations is exactly the same and the difference is how the reference to itself is handled.
EDIT
So you are asking how the evaluation gets delayed. Well the normal order version looks like this:
(define Y
(lambda (f)
((lambda (g) (g g))
(lambda (g) (f (g g))))))
If you look at how this would be applied with an argument you'll notice that Y never returns since before it can apply f in (f (g g)) it needs to evaluate (g g) which in turn evaluates (f (g g)) etc. To salvage that we don't apply (g g) right away. We know (g g) becomes a function so we just give f a function that when applied will generate the actual function and apply it. If you have a function add1 you can make a wrapper (lambda (x) (add1 x)) that you can use instead and it will work. In the same manner (lambda args (apply (g g) args)) is the same as (g g) and you can see that by just applying substitution rules. The clue here is that this effectively stops the computation at each step until it's actually put into use.

How to construct a tree of particular shape with elements from a list

Given an s-expression '((a . b) . (c . d)) and a list '(e f g h), how can I traverse the s-expression create an s-expression with the same shape, but with elements taken from the list? E.g., for the s-expression and list above, the result would be '((e . f) g . h)?
Traversing a tree of pairs in left to right order isn't particularly difficult, as car and cdr let you get to both sides, and cons can put things back together. The tricky part in a problem like this is that to "replace" elements in the right hand side of a tree, you need to know how many of the available inputs you used when processing the left hand side of the tree. So, here's a procedure reshape that takes a template (a tree with the shape that you want) and a list of elements to use in the new tree. It returns as multiple values the new tree and any remaining elements from the list. This means that in the recursive calls for a pair, you can easily obtain both the new left and right subtrees, along with the remaining elements.
(define (reshape template list)
;; Creates a tree shaped like TEMPLATE, but with
;; elements taken from LIST. Returns two values:
;; the new tree, and a list of any remaining
;; elements from LIST.
(if (not (pair? template))
(values (first list) (rest list))
(let-values (((left list) (reshape (car template) list)))
(let-values (((right list) (reshape (cdr template) list)))
(values (cons left right) list)))))
(reshape '((a . b) . (c . d)) '(e f g h))
;=> ((e . f) g . h)
;=> ()
(reshape '((a . b) . (c . d)) '(e f g h i j k))
;=> ((e . f) g . h)
;=> (i j k) ; leftovers
I'll assume that you want to create a new s-expression with the same shape of the s-expression given as the first parameter, but with the elements of the list from the second parameter.
If that's right, here's one possible solution using a list to save the point where we are in the replacement list and Racket's begin0 to keep the list updated (if that's not available in you interpreter use a let, as suggested by Chris and Joshua in the comments):
(define (transform sexp lst)
(let loop ((sexp sexp)) ; the s-expression list to be traversed
(cond ((null? sexp) '()) ; if it's empty, we're finished
((not (pair? sexp)) ; if it's an atom
(begin0 ; then (alternatively: use a `let`)
(car lst) ; return first element in replacements list
(set! lst (cdr lst)))) ; and update replacements to next element
(else ; otherwise advance recursion
(cons (loop (car sexp)) ; over both the `car` part of input
(loop (cdr sexp))))))) ; and the `cdr` part
For example:
(transform '((a . b) . (c . d)) '(e f g h))
=> '((e . f) g . h)
(transform '((a . b) (c d (x y) . z) . t) '(e f g h i j k m))
=> '((e . f) (g h (i j) . k) . m)
The solution is similar to my previous answer:
(define (transform sxp lst)
(let loop ((sxp sxp))
(cond ((null? sxp) sxp)
((pair? sxp) (cons (loop (car sxp)) (loop (cdr sxp))))
(else (begin0 (car lst) (set! lst (cdr lst)))))))
then
> (transform '((a . b) . (c . d)) '(e f g h))
'((e . f) g . h)

Resources