Scheme streams and circular lists - list

In Scheme/Lisp I am trying to make a function that converts a list into a circular list. Therefore, I believe I need to construct an infinite stream in which the tail of the list points to the head of the list.
Here is my code so far:
(define (rotate-list l1 l1copy)
(if (null? (force (cdr l1)))
(cons (car l1) (delay l1copy)))
(cons (car l1) (delay (rotate-list (force (cdr l1)) l1copy))))
All help is greatly appreciated.

No, you don't need streams to make a circular list.
There are two approaches to creating circular lists, the standard Scheme approach, and the Racket approach (since Racket's conses are immutable). I will look at examples using SRFI 1's circular-list function. Here's the reference implementation:
(define (circular-list val1 . vals)
(let ((ans (cons val1 vals)))
(set-cdr! (last-pair ans) ans)
ans))
What that does is to find the last pair in the list of given values, and set-cdr!s it back to the beginning of that list. Pretty straightforward, right?
In Racket, conses are immutable, so set-cdr! does not exist. So instead, Racket does it this way:
(define (circular-list val1 . vals)
(let ([ph (make-placeholder #f)])
(placeholder-set! ph
(cons val1 (let loop ([vals vals])
(if (null? vals)
ph
(cons (car vals) (loop (cdr vals)))))))
(make-reader-graph ph)))
This uses Racket's make-reader-graph function to handle the cycles. Very nifty. :-)

Related

scheme iteration of summing in lists

i want to ask if someone wants to help me with a iterative scheme code that gives the sum of two lists. I already have the recursive version of the code.
(define (sum-lists l1 l2)(cond ((and (null? l1) (null? l2)) '())
((null? l1) l2)
((null? l2) l1)
(else (cons (+ (car l1) (car l2)) (sum-lists (cdr l1) (cdr l2))))))
The general "iterative procedure" recipe:
Write a helper function that takes an accumulator parameter.
Create each intermediate result in the accumulator.
When you terminate the recursion, return the accumulator.
Pass it a suitable initial accumulator.
It's common when transforming lists to accumulate the result in reverse and then reverse the result when you're done.
A trivial example, incrementing each list element by one:
(define (add-1 ls)
(if (null? ls)
'()
(cons (+ 1 (car ls)) (add-1 (cdr ls)))))
To make it iterative, create a helper function where you cons to the accumulator instead of the recursive result:
(define (add-one ls acc)
(if (null? ls)
(reverse acc)
(add-one (cdr ls) (cons (+ 1 (car ls)) acc))))
(Note that, except for the introduction of acc, the recursion contains the same parts as before but in a different order.)
Then you start it off with an empty accumulator:
(define (add-1 ls)
(add-one ls '()))
Your case has slightly more involved base cases since you need to accomodate inputs of different lengths.
Finishing it left as an exercise.
(Another exercise: figure out why your first condition, (and (null? l1) (null? l2)), is unnecessary.)

Add elements to existing list in Scheme

Hi i am learning Scheme new.I have question.Lets think I have defined a function which it adds element to list if it is empty.If there is an element in list and new element is added as second to list and goes like this.For example
>(add a) ; here list is empty
'(a)
>(add b) ; here a is in the list
'(a b)
>(add c) ; here a and b is in the list
(a b c)
List is updated like this.How can I write a function like this.I add elements to empty list each time with my code.I mean it is like that with mine.
>(add a)
'(a)
>(add b)
'(b)
>(add c)
'(c)
How can I write the proper code for this purpose ?
here is my code
#lang racket
(define addToList
(lambda (a b)
(cond ((null? a) b)
((null? b) a)
((cons (car a) (addToList (cdr a) b))))))
(addToList '(1 2 3) '())
You can't "add" to an empty list in any Lisp dialect, because in all Lisp dialects, the empty list is a special, immutable value.
In Racket, not only is the empty list immutable, but so are all lists. Code that manipulates lists needs to be written in "functional" style to work properly.
"Adding" to a list in the sense of your add function would mean creating a whole new list with one more element and then binding it to the same variable as before:
;;; This implementation of add would behave just like
;;; the examples at the top of your question.
(define add
(let ((the-list '()))
(lambda (new-item)
(set! the-list
(append the-list (list new-item)))
the-list)))
The above function runs slower the longer the-list is because it has to
copy every element before adding the new one. It is much faster to add to the beginning of a list instead of the end:
(define add
(let ((the-list '()))
(lambda (new-item)
(set! the-list
(cons new-item the-list))
the-list)))
For this reason, most Racket programs build their lists backwards, and then
use reverse as late as possible to create a forward version of the list.
Just like any other language there are two ways to mutate a value. You can mutate what a variable points to (binding) or you can mutate the targeted object by altering parts of the object. The last one requires that the object is not a primitive.
Using variable binding:
#!r6rs
(import (rnrs))
(define lst '())
(define (add element)
(set! lst (append lst (list element))) ; adding to front is much cheaper
lst)
Using mutation:
#!r6rs
(import (rnrs)
(rnrs mutable-pairs))
(define lst (list 'head))
(define tail lst) ; keep the last cons so we can add O(1)
(define (add element)
(set-cdr! tail (list element))
(set! tail (cdr tail))
(cdr lst))
Your procedure looks more like the functional kind since it's not actually mutating anything, but it would work if you kept the result you got back and fixed the fact that it's not extending the list but adding the element to the tail as a dotted list.
(define addToList
(lambda (a b)
(cond ((null? a) (list b)) ; result needs to be a list
((null? b) a)
((cons (car a) (addToList (cdr a) b))))))
(define lst '())
(set! lst (addToList lst 1))
(set! lst (addToList lst 2))
(set! lst (addToList lst 3))
lst ; ==> (1 2 3)
I would have written it like this to make it look more like scheme:
(define (add-to-end lst e)
(if (null? lst)
(list e)
(cons (car lst)
(add-to-end (cdr lst) e)))))
Of course adding to front is much cheaper and is done with plain old cons. If you add some elements and actually wanted to add it to end you get the same effect by reversing the list after adding your elements.

Turning list of atoms into a single list using recursion

I'm looking for an answer that turns a list of atoms into a single list recursively.
An example would be, (slist '(a (b c) (d e (f) g) h)) into (slist (a b c d e f g h))
Any answer will be helpful.
What you're trying to do is called flattening a list. Here are a bunch of options:
; required predicate
(define (atom? x)
(and (not (null? x))
(not (pair? x))))
; naïve version using append
(define (flatten1 lst)
(cond ((null? lst)
'())
((not (pair? lst))
(list lst))
(else
(append (flatten1 (car lst))
(flatten1 (cdr lst))))))
; naïve version using append, map, apply
(define (flatten2 lst)
(if (atom? lst)
(list lst)
(apply append (map flatten2 lst))))
; efficient version using fold-left
(define (flatten3 lst)
(define (loop lst acc)
(if (atom? lst)
(cons lst acc)
(foldl loop acc lst)))
(reverse (loop lst '())))
; very efficient version with no higher-order procedures
(define (flatten4 lst)
(let loop ((lst lst)
(acc '()))
(cond ((null? lst)
acc)
((not (pair? lst))
(cons lst acc))
(else
(loop (car lst) (loop (cdr lst) acc))))))
Any of the above will work as expected. For instance, using flatten4:
(flatten4 '(a (b c) (d e (f) g) h))
=> '(a b c d e f g h)
Depending on the interpreter you're using, it's quite possible that it already includes an implementation. For example, in Racket:
(flatten '(a (b c) (d e (f) g) h))
=> '(a b c d e f g h)
In Lisp, as opposed to Scheme, you have to accept the fact that the atom nil represents an empty list in your list structure. So, strictly speaking, when you flatten a list, you do not obtain all of the atoms from the tree structure; only those ones that do not represent empty lists and list terminators.
You also have to make a design decision: does your code handle improper lists and circular list? That is to say, what should these cases do:
(flatten '(a . b)) ;; (a b), accurate diagnostic or failure?
(flatten '#1=(a . #1#)) ;; (a), accurate diagnostic or failure?
Do you handle the situation and collect the actual non-list atoms that are present in the tree structure, regardless of cycles or improper termination? Or do you detect the situation accurately and report a meaningful diagnostic? Or just ignore the possibility and let the code blow up in lower level functions, or perform runaway recursion?
If you don't care about dealing with improper lists and circular structure, flattening a list is recursively defined like this.
A non-list is flattened by returning a list containing that atom.
A list is flattened by flattening all of its elements and catenating them.
In Lisp it's usually easier and clearer to write the code than the English spec or pseudo-code:
(defun flatten (obj)
"Simple flatten: no handling of improper lists or cycles"
(if (listp obj)
(mapcan #'flatten obj)
(list obj)))
Note that although mapcan is destructive, that doesn't present a problem here, because it only ever catenates list structure that is constructed within our function call and not any incoming list structure. Stated in other words, our output does not share structure with the input.
You've already checked a correct answer, but here is a trivial implementation which clearly indicates the recursion:
(define (slist list)
(if (null? list)
'()
(let ((next (car list))
(rest (cdr list)))
(if (list? next)
(append (slist next) (slist rest))
(cons next (slist rest))))))

Scheme, Check if anything in two lists are the same

Is it possible to check two list against each other if anything is the same in them?
(check-list '(hey cookie monkey) '(apple pizza cookie) ==> #t
I tried something like
(define (check-list list element)
(let ((x list))
(cond ((null? x) #f)
((eq? (car x) (car element)) #t)
(else (check-list (cdr x) element))))
(check-list list (cdr element)))
I know this is not correctly written but don't know how to tackle this problem.
Anyone that can help me?
Sometimes it helps to formulate the process of the solution to a problem in your natural language. Let's simplify the problem a bit.
How do you check if one element is contained in a list? One way to do that would be to compare that one element with each element in the list until you found it - somewhere along the lines you have already done - but not quite. A quick draft would be:
(define (member? e lst)
(cond ((null? lst) #f) ; empty list doesn't contain e
(or (eq? e <??>) ; either the first element is e or
(member? e <??>))) ; the rest of the list contains e
We can use that previous knowledge to solve the real problem at hand. We know how to search for one element in a list, and now we need to search for each element in a list in another list.
(define (check-list lst1 lst2)
(if (or (null? lst1) (null? lst2)) #f ; empty list(s) share no elements
(or (member? <??> <??>) ; first element of lst1 in lst2?
(member? <??> <??>)))) ; rest of lst1 in lst2?
The <??> should be substituded with the appropriate expressions for selecting the parts of the lists.
Similar to a prior answer but exploiting logic primitives:
(define (intersect? list1 list2)
(and (not (null? list1))
(or (member (car list1) list2)
(intersect? (cdr list1) list2))))
If the lists are wicket long you might want to hash the first list and then just iterate through the second. This uses R5RS with srfi-69 and for small lists you'll get a little overhead but
(require srfi/69); alist->hash-table, hash-table-ref/default
(define (intersect? list1 list2)
(let ((hash (alist->hash-table (map (lambda (x) (cons x x)) list2) equal? )))
(let loop ((list list1))
(and (not (null? list))
(or (hash-table-ref/default hash (car list) #f)
(loop (cdr list)))))))
There seems to be a little confusion. The "big" problem here is how to determine if two lists share at least one element in common, let's write a procedure for that called element-in-common?. Before tackling this problem, we need to determine if a single element belongs in one list, that's what check-list should do (notice that in your code check-list receives as a second parameter an element, but you're treating it as if it were a list of elements).
You don't have to write the check-list procedure, it already exists and it's called member. With that knowledge in hand, we can solve the big problem - how to determine if at least one of the elements in one list (let's call it lst1) is in another list (called lst2)?
Simple: we iterate over each of the elements in lst1 using recursion, asking for each one if it belongs in lst2. If just one element of lst1 is a member of lst2, we return #t. If none of the elements in lst1 is in lst2, we return #f. Something like this:
(define (element-in-common? lst1 lst2)
(cond (<???> ; is the first list empty?
<???>) ; then there are no elements in common
((member <???> lst2) ; is the current element of `lst1` in `lst2`?
<???>) ; then there IS an element in common
(else ; otherwise
(element-in-common? <???> lst2)))) ; advance recursion
Don't forget to test your code:
(element-in-common? '(hey cookie monkey) '(apple pizza cookie))
=> #t
(element-in-common? '(hey cookie monkey) '(apple pizza pie))
=> #f
You can use memq to check if first element on the first list is on the second list, and if not then check recursively if something in the rest of the first list is in the second list:
(define (check-list list1 list2)
(cond ((null? list1) #f)
((memq (car list1) list2) #t)
(else (check-list (cdr list1) list2))))
Here's an answer using higher-order functions
in mit-schme
(define (check-list L1 L2)
(apply boolean/or (map (lambda (x) (member? x L2)) L1)))
(define remove-item
(lambda (lst ele)
(if (null? lst)
'()
(if (equal? (car lst) ele)
(remove-item (cdr lst) ele)
(cons (car lst)
(remove-item (cdr lst) ele))))))

Scheme, how to square just negative numbers in a list leaving the rest of the list intact

I have been working on a call to accumulate which goes as follows:
(define (accumulate op initial sequence)
(if (null? sequence)
initial
(op (car sequence)
(accumulate op initial (cdr sequence)))))
However when I try to square something by slecting it through filter the answer doesn't work. What I have so far is this:
(define (f2b items)
(accumulate (lambda (x y)
(cons (append
(map square (filter negative? (filter number? x))) x) y)) () items)
)
The Input I give is:
(f2a '(("sdas" 89) (-53 "sad")))
The output I get is:
((sdas 89) (2809 -53 sad))
I can't seem to get the negative number to go away.
It would be much easier to use filter and map. Filter is predefined but it looks like this.
(define (filter1 predicate sequence)
(cond
((null? sequence) null)
((predicate (car sequence))
(cons (car sequence)
(filter predicate (cdr sequence))))
(else (filter predicate (cdr sequence)))))
map is also predefined, it just runs a function over a list.
This should be pretty simple to write, but incase you need help you should just write a lamdba for the predicate in filter.
Actually, the functionality you describe is not usually the job of an accumulator. Instead, squaring negative numbers in a list seems like the perfect job for something like a map.
First, let's do:
(define (make-positive x)
(if (and (number? x) (negative? x))
(square x)
x))
Now suppose we want to operate on a list called lst. If it was just a flat list, like '(1 "2" -5 -4 6), then we could just
(map make-positive lst)
Since we need to operate on lists which are nested two levels deep, we could do:
(map (lambda (x)
(map make-positive x))
lst)
If we wanted to operate on lists which are nested arbitrarily deep, we could do:
(define (nested-map fn elm)
(if (list? elm)
(map (lambda (x) (nested-map fn x)) elm)
(fn elm)))
(nested-map make-positive lst)
PS - we can define map like this:
(define (map fn lst)
(if (empty? lst)
'()
(cons (fn (car lst))
(map fn (cdr lst)))))