An iterative program for appending lists in scheme - linked-list

I am reading Section 2.2 in SICP where the book introduced the procedure for appending two lists. I am trying to implement the append using iteration.
This is my code:
(define (append list1 list2)
(define (append-iter item1 reversed-item1 result)
(if (null? item1)
(if (null? reversed-item1)
result
(append-iter item1
(cdr reversed-item1)
(cons (car reverse) result)))
(append-iter (cdr item1)
(cons (car item1) reversed-item1)
result)))
(append-iter list1 '() list2))
Though it works, but noting the number of the iterations is double the length of list1. Is there a solution whose number of the iterations equals to the length of list1. (without using any fold function)?

Basically how your procedure works is like this:
(define (append l1 l2)
(define (reverse-append rev app)
(if (null? rev)
app
(reverse-append (cdr rev)
(cons (car rev) app))))
(reverse-append (reverse l1) l2))
It's O(N) but it wastes some memory since (reverse l1) space is just used for iteration. If you really need to fix that you need to use mutation:
(define (append-iter . rest)
(let ((result (list 1)))
(let loop ((p result) (lst '()) (rest rest))
(cond
((not (null? lst))
(set-cdr! p (list (car lst)))
(loop (cdr p) (cdr lst) rest))
((null? rest) (cdr result))
((null? (cdr rest))
(set-cdr! p (car rest))
(cdr result))
(else (loop p (car rest) (cdr rest)))))))

Related

SICP 3.52 delayed cdr

Exercise 3.52,
(define sum 0)
(define (accum x)
(set! sum (+ x sum))
sum)
;1: (define seq (stream-map accum (stream-enumerate-interval 1 20)))
;2: (define y (stream-filter even? seq))
;3: (define z (stream-filter (lambda (x) (= (remainder x 5) 0))
; seq))
;4: (stream-ref y 7)
;5: (display-stream z)
Step 1:
;1: ==> (cons-stream 1 (stream-map proc (stream-cdr s)) (Assume stream-cdr is evaluated only when we force the cdr of this stream)
sum is now 1
Step 2:
1 is not even, hence (also memoized so not added again), it calls (stream-filter pred (stream-cdr stream)).
This leads to
evaluation of cdr hence materializing 2 which is even, hence it should call: (cons-stream 2 (stream-cdr stream)).
According to this answer should be 1+2 = 3 , but it is 6
Can someone help with why the cdr's car is materialized before the current cdr is called?
Using Daniel P. Friedman's memoizing tail
#lang r5rs
(define-syntax cons-stream
(syntax-rules ()
((_ h t) (cons h (lambda () t)))))
(define (stream-cdr s)
(if (and (not (pair? (cdr s)))
(not (null? (cdr s))))
(set-cdr! s ((cdr s))))
(cdr s))
we observe:
> sum
0
> (define seq (stream-map accum (stream-enumerate-interval 1 20)))
> sum
1
> seq
(mcons 1 #<procedure:friedmans-tail.rkt:21:26>)
> (define y (stream-filter even? seq))
> sum
6
> seq
(mcons
1
(mcons
3
(mcons 6 #<procedure:friedmans-tail.rkt:21:26>)))
> y
(mcons 6 #<procedure:friedmans-tail.rkt:21:26>)
>
stream-filter? needs to get to the first element of the stream it is constructing in order to construct it. A stream has its head element already forced, calculated, so it must be already present.
In the list of accumulated sums of the enumerated interval from 1 to 20, the first even number is 6:
1 = 1
1+2 = 3
1+2+3 = 6
...

Trouble with streams in Scheme

I'm trying to write a stream that takes as arguments an infinite stream S, and two integers m and n, and returns the stream whose elements are elements of S that are multiples of either m or n.
Unfortunately, my stream only works until I find the first multiple, then it won't progress past that. I'm calling the cdr when invoking the stream, so I'm not sure why I'm not looking at the next element.
(define stream-car car)
(define (stream-cdr s)
((cadr s)))
(define (divisible? n x)
(zero? (remainder n x)))
(define (stream-cons x s)
(list x (lambda () s)))
;should loop to find the next multiple in the parameter stream
(define (findnext s m n)
(if (or (divisible? (stream-car s) m)
(divisible? (stream-car s) n))
(stream-car s)
(findnext (stream-cdr s) m n)))
;this is my stream
(define (multiples s m n)
(let ((h (findnext s m n)))
;first need to make sure h is a multiple of
;either m or n, THEN create the list
(list h
(lambda ()
(multiples (stream-cdr s) m n)))))
;below is for testing
(define (even-nums-from n)
(list n
(lambda ()
(even-nums-from (+ 2 n)))))
(define even-integers
(even-nums-from 0))
;test cases
(multiples even-integers 4 6);should be a stream with car = 0
(stream-car (multiples even-integers 4 6));should be 0
(stream-cdr (multiples even-integers 4 6));should be a stream with car = 4
(stream-car (stream-cdr (multiples even-integers 4 6))) ;should be 4
(stream-cdr (stream-cdr (multiples even-integers 4 6))) ;should be a stream
;starting with 6-not moving past when we find a multiple
(stream-car (stream-cdr (stream-cdr (multiples even-integers 4 6))))
;should be 6
My output for the above tests is:
(list 0 (lambda () ...))
0
(list 4 (lambda () ...))
4
(list 4 (lambda () ...))
4
I'm using DrRacket (advanced student language) and just not sure why my stream is stuck on that first multiple (4). I'm calling stream-cdr when I invoke multiples again, so I don't understand where I'm going wrong. Any ideas would be much appreciated.
Solved it, the problem was I was not updating the passed stream as I found the next multiple. Below is the corrected code (where I now pass a stream with the multiple in the car that will be used in my multiples function):
;returns the stream with car a multiple of either m or n
(define (findnext s m n)
(cond ((divisible? (stream-car s) m) s)
((divisible? (stream-car s) n) s)
(else (findnext (stream-cdr s) m n))))
(define (multiples s m n)
(let ((h (findnext s m n))) ;h is now an updated stream
;with car a multiple of one of m or n
(list (stream-car h)
(lambda ()
(multiples (stream-cdr h) m n)))))

Recursion in a stream

I have the code
(define (add-ten s)
(let ([f (lambda(s) ((cons 10 (car (s))) (cdr (s))))])
(f s)))
s could be a stream like powers
(define powers (letrec ([f (lambda (x) (cons x (lambda () (f (* x 2)))))])
(lambda () (f 2))))
My function
(result-for-n-times powers 5)
gives '(2 4 8 16 32).
Now, i want to define a stream (add-ten) that can take the stream powers and gives another stream.So, if i call it
(result-for-n-times (add-ten powers) 5)
would give '((10. 2) (10. 4) (10. 8) (10. 16) (10. 32)).
Try this:
(define powers
(letrec ([f (lambda (x)
(cons x
(lambda () (f (* x 2)))))])
(f 2)))
(define (result-for-n-times s n)
(if (zero? n)
'()
(cons (car s)
(result-for-n-times ((cdr s)) (sub1 n)))))
(define (add-ten s)
(letrec ([f (lambda (x)
(cons (cons 10 (car x))
(lambda () (f ((cdr x))))))])
(f s)))
Notice that the add-ten procedure receives a stream as a parameter, but also it must return a stream. So letrec must be used for defining a procedure that conses each element taken from the original stream, with a promise that keeps on building the stream.
Also notice that you're not actually calling the procedure that defines powers, you either call it at the end of powers' definition or you call it like this: (powers) before passing it to add-ten. Fixing this, it works as expected:
(result-for-n-times (add-ten powers) 5)
=> '((10 . 2) (10 . 4) (10 . 8) (10 . 16) (10 . 32))

Parsing strings with Scheme

I am trying to write a simple parser which creates a sxml-expression from a string, e. g.
"This is a [Test]" ===> (item "This is a" (subitem "Test"))
Anybody who is wondering about the square brackets within the given example may have a look at the so called Leiden conventions.
This is the code I have written so far:
(define my-sequence '("this" "[" "is" "a" "]" "test"))
(define (left-square-bracket? item)
(or (equal? item "[")
(eq? item #\x005b)))
(define (right-square-bracket? item)
(or (equal? item "]")
(eq? item #\x005d)))
(define (parse-sequence sequence)
(cond ((null? sequence) '())
((left-square-bracket? (car sequence))
(let ((subsequence (get-subsequence (cdr sequence))))
(list subsequence)))
(else
(cons (car sequence)
(parse-sequence (cdr sequence))))))
(define (get-subsequence sequence)
(if (right-square-bracket? (car sequence))
'()
(cons (car sequence)
(get-subsequence (cdr sequence)))))
Evaluating (parse-sequence my-sequence) yields ("this" ("is" "a")). A nested expression has been created, but the program finished without having evaluated the last item "test". The question is, how do I return from get-subsequence to parse-sequence?
Any help is appreciated, many thanks in advance! :)
To address your initial questions, how to return multiple values: use the "values" form. Here is an example implementation where the inner procedure returns both the remaining list to be processed and the result so far. It recurses on opening brackets.
(define (parse-sequence lst)
(define (parse-seq lst)
(let loop ((lst lst) (res null))
(cond
((null? lst) (values null res))
((string=? (car lst) "[")
(let-values ([(lst2 res2) (parse-seq (cdr lst))])
(loop lst2 (append res (list res2)))))
((string=? (car lst) "]")
(values (cdr lst) res))
(else
(loop (cdr lst) (append res (list (car lst))))))))
(let-values ([(lst res) (parse-seq lst)])
res))
then
(parse-sequence '("this" "is" "a" "test"))
(parse-sequence '("this" "[" "is" "a" "]" "test"))
(parse-sequence '("this" "[" "is" "[" "a" "]" "]" "test"))
will yield
'("this" "is" "a" "test")
'("this" ("is" "a") "test")
'("this" ("is" ("a")) "test")
I made some progress by using open-input-string in combination with read-char:
(define my-sequence (open-input-string "this [is a] test"))
(define (parse-sequence sequence)
`(item
,#(let loop ((next-char (read-char sequence)))
(cond ((eof-object? next-char) '())
((left-square-bracket? next-char)
(let ((subsequence (get-subsequence sequence)))
(cons subsequence
(loop (read-char sequence)))))
(else
(cons next-char
(loop (read-char sequence))))))))
(define (get-subsequence sequence)
`(subitem
,#(let loop ((next-char (read-char sequence)))
(if (right-square-bracket? next-char)
'()
(cons next-char
(loop (read-char sequence)))))))
(parse-sequence my-sequence)
===> (item #\t #\h #\i #\s #\space (subitem #\i #\s #\space #\a) #\space #\t #\e #\s #\t)
Now work goes on, step by step. :)
Any comments and suggestions are still appreciated. :)

Creating a linked-list of variable length

I have a list of ((a)(b)(f(x))). What i would like to get is a linked list structure of((a)(b)(f(x1))(a)(b)(f(x2))(a)(b)(f(x3)))). That is, repeatively appending the list the on the basis of requirement of the user and the value of the variable is chaning so that its value will be unique from each other. How can i implement it in LISP?
? (let ((list '((a) (b) (f (x))))
(n 3))
(flet ((copier (l n)
(setf l (copy-tree l))
(let ((sym (first (second (third l)))))
(setf (first (second (third l)))
(intern (format nil "~a~a"
(symbol-name sym)
n))))
l))
(loop for i from 1 upto n
nconc (copier list i))))
((A) (B) (F (X1)) (A) (B) (F (X2)) (A) (B) (F (X3)))

Resources