Lists in scheme - list

I'm trying to write a function in scheme that takes a list and squares every item on the list, then returns the list in the form (list x y z). However, I'm not sure how to write a code that will do that. So far, I have
(define (square=list list)
(cond
[(empty? list) false]
[else (list (sqr (first a-list))(square-list (rest a-list)))]))
but it returns the list in the form
(cons x (cons y (cons z empty)))
What can I do to make it return the list just in the form (list x y z)? Thanks!

You're almost there -- make sure you understand the difference between cons and list (the textbook How to Design Programs explains this in Section 13. You can find the online copy here).
cons will take an item as its first element and (usually) a (possibly empty) list for the 'rest' part. As an example, (cons 1 empty) has the number 1 as its first element and the empty list as the 'rest'. (cons 1 (cons 2 empty)) has the number 1 as the first element, and (cons 2 empty) as the 'rest'.
list is just an easy shorthand for making lists, taking an arbitrary number of items. Thus:
(list 1 2 3 4 5)
is the same as...
'(1 2 3 4 5)
which is the same as
(cons 1 (cons 2 (cons 3 (cons 4 (cons 5 empty))))).
But be careful. (list 1 (list 2 (list 3))) is not the same as (cons 1 (cons 2 (cons 3 empty))). In fact, it is (cons 1 (cons 2 (cons 3 empty) empty) empty).
If you're still confused, feel free to post a comment.

The problem is that you're using list in the else statement. You are saying build me a list with this value as the first entry, and a list as the second entry.
You want to cons the first entry onto the list created by recursive call.
(list 'a '(b c d))
; gives you
'(a (b c d))
(cons 'a '(b c d))
; gives you
'(a b c d)

This is probably not what your TA is looking for, but I'll throw it in anyway because it may help you grok a tiny bit more of Scheme. The idiomatic (in Scheme) way to write what you are trying to do is to use map:
> (map (lambda (x) (* x x)) '(1 2 3 66 102 10403))
(1 4 9 4356 10404 108222409)
map applies a function (here, (lambda (x) (* x x)) - a nameless function that returns the square of its input) to each element of a list and returns a new list containing all of the results. Scheme's map basically does the same iteration you are doing in your code, the advantage being that by using map you never have to explicitly write such iterations (and, nominally at least, a Scheme implementation might optimize map in some special way, though that's not really that important in most cases). The important thing about map is that it reduces your code to the important parts - this code squares each element of the list, this other code takes the square root of each element, this code adds one to it, etc, without having to repeat the same basic loop iteration code again and again.

Related

Insert element to circular list using scheme

I have a circular list, eg: #0=(1 2 3 4 . #0#).
What I want to do is to insert a new element (x) into this list so that the outcome is #0=(x 1 2 3 4 . #0#). I have been trying using this code (x is the circular list):
(define (insert! elm)
(let ((temp x))
(set-car! x elm)
(set-cdr! x temp)))
However, I think that set-cdr! is not working like I want it to. What am I missing here? Maybe I am way off?
The easiest way to prepend an element to a list is to modify the car of the list, and set the cdr of the list to a new cons whose car is the original first element of the list and whose cdr is the original tail of the list:
(define (prepend! x list) ; list = (a . (b ...))
(set-cdr! list (cons (car list) (cdr list))) ; list = (a . (a . (b ...)))
(set-car! list x)) ; list = (x . (a . (b ...)))
(let ((l (list 1 2 3)))
(prepend! 'x l)
(display l))
;=> (x 1 2 3)
Now, that will still work with circular lists, because the cons cell (i.e., pair) that is the beginning of the list remains the same, so the "final" cdr will still point back to object that is the beginning. To test this, though, we need some functions to create and sample from circular lists, since they're not included in the language (as far as I know).
(define (make-circular list)
(let loop ((tail list))
(cond
((null? (cdr tail))
(set-cdr! tail list)
list)
(else
(loop (cdr tail))))))
(define (take n list)
(if (= n 0)
'()
(cons (car list)
(take (- n 1)
(cdr list)))))
(display (take 10 (make-circular (list 1 2 3))))
;=> (1 2 3 1 2 3 1 2 3 1)
Now we can check what happens if we prepend to a circular list:
(let ((l (make-circular (list 1 2 3))))
(prepend! 'x l)
(display (take 15 l)))
;=> (x 1 2 3 x 1 2 3 x 1 2 3 x 1 2)
Since you're trying to prepend an element to a circular list, you need to do two things:
Insert a new cons cell at the front of the list containing the additional element. This is easy because you can just perform a simple (cons elm x).
You also need to modify the recursive portion of the circular list to point at the newly created cons cell, otherwise the circular portion will only include the old parts of the list.
To perform the latter, you need a way to figure out where the "end" of the circular list is. This doesn't actually exist, since the list is, of course, circular, but it can be determined by performing an eq? check on each element of the list until it finds an element equal to the head of the list.
Creating a helper function to do this, a simple implementation of insert! would look like this:
(define (find-cdr v lst)
(if (eq? v (cdr lst)) lst
(find-cdr v (cdr lst))))
(define (insert! elm)
(set! x (cons elm x))
(set-cdr! (find-cdr (cdr x) (cdr x)) x))

Scheme - Recursion : Sum consecutive elements of a list

I'm trying to write a function using Scheme that :
take a list of integers with more than two elements as a parameter
sum the n-th-element and (n+1)-th-element
return this list
Result should be as follows :
> (SumNeighbors (list 1 2 3 4))
(3 5 7)
I think I get the way to add elements but my recursion is totally wrong...
(define (SumNeighbors lst)
(if (not (null? (cdr lst)))
(append (list (+ (car lst) (car (cdr lst)))) (SumNeighbors (cdr lst)))))
Any help would be appreciated.
The solution to this problem follows a well-known pattern. I'll give you some hints, it'll be more fun if you find the answer by your own means:
(define (SumNeighbors lst)
(if <???> ; if there's only one element left
<???> ; we're done, return the empty list
(cons ; otherwise call `cons`
(+ <???> <???>) ; add first and second elements
(SumNeighbors <???>)))) ; and advance recursion
Notice the following:
Your solution is lacking the base case - what happens when the list we're traversing only has one element left? it's time to finish the recursion! and because we're building a list as the output, what should be the value returned?
We normally use cons to build an output list, not append. That's the natural way to build a list
The part of this procedure that falls outside the solution template is the fact that we stop when there's a single elment left in the list, not when the list is empty (as is the usual case)
You'll see that many procedures that iterate over an input list and return a list as output follow the same solution template, it's very important that you learn how and why this works, it's the foundation for writing solutions to other similar problems.
#!r6rs
(import (except (rnrs base) map)
(only (srfi :1) map))
(define (sum-neighbors lst)
(map + lst (cdr lst)))
The higher order function map as defined in SRFI-1 supports uneven lenght arguments. It will stop at the shortest list.
If you call (sum-neighbors '(1 2 3 4)) it will become (map + (1 2 3 4) (2 3 4)) which is the same as (cons (+ 1 2) (cons (+ 2 3) (cons (+ 3 4) '())))

Using map and other high order functions

I am still learning about high order functions and going to be quizzed on it soon. I am trying to write a program that takes 2 lists of the same length and subtracts the first from second, item by item, until you get 0 in the first position.
(check-expect (min (list 1 1 1) (list 2 4 6)) (list 2 4))
(check-expect (min (list 1 1) (list 2 3)) (list 1))
I can easily do this without map, but Is there any way I can use map here?
(map - 1 (list ...))
or when I pass it on to the first of a list, or rest.
wont work. I know it takes in a function and passes on to each element of a list. I am confused.
This is not a good example to start learning about map. The map higher-order procedure takes a list as input, and returns another list of the same length as output, where a function was applied to each of the elements in the input. See why this is not such a clear-cut case for using map? the output lists are smaller than the inputs!
Of course, it can be done, but it's not that elegant, and obscures the true purpose of map:
(define (min lst1 lst2)
(if (zero? (first lst2)) ; if the first position in lst2 is zero
(rest lst2) ; then return the rest of it.
(min lst1 ; otherwise advance recursion
(map - lst2 lst1)))) ; ok, here `map` was useful
To understand what's happening in the last line, imagine that the input lists are one on top of the other:
'(2 4 6)
'(1 1 1)
Then, map applies the - function element-wise:
(- 2 1)
(- 4 1)
(- 6 1)
And the result of each operation is collected in a new list:
'(1 3 5)
This is a special case of map: when there's more than one list after the function, it applies the function to the first element of each list before advancing to the next - hence the function must accept as many arguments as there are lists. The usual case with map is that you simply apply the function to each of the elements in a single list, and but the way this is a good place to use lambda:
(map (lambda (x) (* x x))
'(1 2 3 4 5))
=> '(1 4 9 16 25)

functions and lists in scheme/racket

How would you define a function which takes one argument, which should be a list, and returns the elements in the
list which are themselves lists?
(check-expect (find-sublists ’(1 2 () (3) (a b c) a b c))
’(() (3) (a b c)))
Do you have experience designing functions that can filter through a list?
A simpler problem with the same flavor as the original is something like this: design a function that takes a list of numbers and keeps only the even numbers. Would you be able to do that function?
Looking at http://www.ccs.neu.edu/home/matthias/HtDP2e/htdp2e-part2.html and going through its guided exercises may also help.
Two useful tools which should start you on your way:
1) Traversing through a list:
; traverse: takes a list of numbers
; Goes through each element, one-by-one, and alters it
(define traverse
(lambda (the_list)
(if (empty? the_list)
empty
(cons (+ 1 (first the_list))
(traverse (rest the_list))))))
(traverse (cons 3 (cons 4 empty))) returns (cons 4 (cons 5 empty))
2) list?:
(list? (list 1 2 3)) returns #t
(list? 5) returns #f

Multiplying each element of a list with each element of another list in Scheme programming

i am trying to do the following in Scheme:
List<int> list = new List<int>();
List<int> list1 = new List<int>();
List<int> list2 = new List<int>();
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);
list1.Add(2);
list1.Add(4);
list1.Add(6);
list1.Add(8);
for (int i = 0; i < list.Count; i++)
{
for (int p = 0; p < list1.Count; p++)
{
list2.Add(list[i] * list1[p]);
}
}
as seen in the code above, I am trying to multiply each element of the first list with every element in the second list. So 1*2, 1*4, 1*6, 1*8, then going to the next element, 2*2,2*4.. etc.
I am having trouble implementing this into Scheme. I tried using the map function but this doesn't seem to work the way I want it to. Any ideas?
We start by defining the two input lists, I renamed them since list is a built-in procedure in Scheme and is not a good idea to overwrite it):
(define l '(1 2 3 4))
(define l1 '(2 4 6 8))
I'm assuming that you want your result list to be "flat" - e.g., it doesn't contain lists of elements, only elements (if you're ok with having a list of lists in l2, simply delete the call to flatten below). For that, we need to define the flatten procedure:
(define (atom? x)
(and (not (pair? x)) (not (null? x))))
(define (flatten lst)
(cond ((null? lst) empty)
((atom? lst) (list lst))
(else (append (flatten (car lst))
(flatten (cdr lst))))))
Finally, the problem at hand. It's simple once you understand how to nest two map procedures - take a look at the nested mappings section in the book SICP.
(define l2
(flatten
(map (lambda (i)
(map (lambda (j)
(* i j))
l1))
l)))
At this point, l2 contains the expected answer:
(2 4 6 8 4 8 12 16 6 12 18 24 8 16 24 32)
Óscar has given a very complete answer to this question, but I wanted to add two minor notes:
The Scheme dialect Racket has a nice built-in form called for*/list which does exactly this sort of thing:
(for*/list ([i '(1 2 3 4)]
[j '(2 4 6 8)])
(* i j))
Also, instead of using your own or the library's flatten function in the nested-maps solution, you could replace the outer map with append-map from SRFI-1. There are plenty of other ways too, of course ;-)
I can't believe nobody has given the most straightforward answer: nested uses of map:
(append-map (lambda (x)
(map (lambda (y) (* x y))
(list 2 4 8 6)))
(list 1 2 3 4))
append-map is a simple variant of map that assumes that the mapping function returns a list, so it concatenates all the result lists. This is a library function in most serious Scheme systems (it's in the SRFI-1 library), but here's a simple, incomplete definition (a complete definition would handle multiple argument lists):
(define (append-map f xs)
(concat (map f xs)))
;;;
;;; Turns a list of lists into a list by appending all the top-level sublists.
;;; This is also a common library function.
;;;
(define (concat lists)
(if (null? lists)
'()
(append (car lists)
(concat (cdr lists)))))