The Following Code:
(define (rcons val lst)
(if (not (null? lst))
(cons (car lst) (rcons val (cdr lst)))
(cons lst (list val)))))
(rcons 'E '(A B C D))
Should produce (A B C D E) but instead gives a result of (A B C D () E)
What' wrong with my recursive step ?
I can't run this locally, but you should be returning the end of the list on the final recursion (and not the entire list like you're trying to do, which is always null there by the way...):
(define (rcons val lst)
(if (not (null? lst))
(cons (car lst) (rcons val (cdr lst)))
(cons val '()))) ; recursion ends here - only return end of list cons
Remember proper lists end in null ('()).
List structure:
What you get if you think of the recursion unfolding is (look at the last cons):
(cons #1 (cons #2 (cons #3 (cons .... (cons val '()))))
#1, #2, #3 etc describe the members of the original lst as well as the frame number (1 being the first).
More visualising - the recursion unfolds:
; {x} - x marks frame as well as location in original 'lst'
; frame 1
(cons (car lst {1}) (rcons val (cdr lst)))
; frame 2
(cons (car lst {1}) (cons (car lst {2}) (rcons val (cdr lst))))
; frame 3 ...
(cons (car lst {1}) (cons (car lst {2}) (cons (car lst {3}) (rcons val (cdr lst)))))
If you look back at List structure, it's easy to see we want val to be the car of the last cons, and '() to be it's cdr - to form a proper list. This is exactly what I fixed in your code.
You are so close!
List structure is iterated from beginning to end and built from end to beginning. If you want to make the list (1 2 3) you first have to make (2 3) then cons the first 1 to the finished constructed list (2 3). Your rcons do that as you see (cons (car lst) (rcons val (cdr lst))) which makes a list with the current value to the rcons of the rest of the list. The cons is done after both expressions has been evaluated. So for a 3 element list it will recurse 3 times. (cons first-value (cons second-value (cons third-value (rcons val-value '()))))
So if val is 4 (rcons 4 '()) should produce (cons 4 '()) or just (list 4) which is the same. This should work nicely.
(define (rcons val lst)
(if (not (null? lst))
(cons (car lst) (rcons val (cdr lst)))
(list val)))
(rcons 4 '()) ; ==> (4)
(rcons 4 '(1 2 3)) ; ==> (1 2 3 4)
Related
I'm currently working on building a function that returns a row of Pascal's triangle. My function passes in a list that contains a row in Pascal's triangle and returns the next row depending on which row was passed in.
ex. pass in '(1 2 1) and it should return '(1 3 3 1).
However I cannot seem to get the beginning 1 in the list.
(define build-next
(lambda(thisRow)
(cond
[(null? thisRow) '(1)]
[(null? (cdr thisRow)) (cons 1 (cdr thisRow))]
[else (cons (+ (car thisRow) (car (cdr thisRow))) (build-next(cdr thisRow)))])))
(build-next '(1 2 1))
Running this code will give me the output
'(3 3 1)
without the leading 1
Your functions works if the input row has a zero as first element.
Renaming your original function to build-next-helper and introducing
a new build-next that simply calls your existing function after prefixing a zero works fine:
(define build-next-helper
(lambda (thisRow)
(cond
[(null? thisRow) '(1)]
[(null? (cdr thisRow)) (cons 1 (cdr thisRow))]
[else (cons (+ (car thisRow) (car (cdr thisRow)))
(build-next-helper (cdr thisRow)))])))
(define (build-next thisRow)
(build-next-helper (cons 0 thisRow)))
(build-next '(1 2 1))
You can also use a named let to write build-next as follows:
(define (build-next row)
(let loop ([row row]
[acc 0])
(cond
[(zero? acc)
(cons 1 (loop row (add1 acc)))]
[(null? row) empty]
[(null? (cdr row)) (list 1)]
[else
(cons (+ (car row) (cadr row))
(loop (cdr row) acc))])))
The loop parameter acc is used as an accumulator to add the leading 1 in the next row (ie. first cond case).
For example,
(build-next '()) ;;=> '(1)
(build-next '(1)) ;;=> '(1 1)
(build-next '(1 1)) ;;=> '(1 2 1)
(build-next '(1 2 1)) ;;=> '(1 3 3 1)
(build-next '(1 3 3 1)) ;;=> '(1 4 6 4 1)
(build-next '(1 4 6 4 1)) ;;=> '(1 5 10 10 5 1)
Here is a possible solution:
(define build-next
(lambda(thisRow)
(define helper-build-next
(lambda (lst prev)
(if (null? lst)
(list prev)
(cons (+ prev (car lst)) (helper-build-next (cdr lst) (car lst))))))
(if (null? thisRow)
(list 1)
(cons (car thisRow) (helper-build-next (cdr thisRow) (car thisRow))))))
The recursion is performed through a helper function, that gets the rest of the row and the previous element of the row. Initially the function checks if the parameter is the empty list, so that the first row of the triangle is returned. Otherwise, the helper function is called with the initial parameters.
I'm trying to teach myself functional language thinking and have written a procedure that takes a list and returns a list with duplicates filtered out. This works, but the output list is sorted in the order in which the last instance of each duplicate item is found in the input list.
(define (inlist L n)
(cond
((null? L) #f)
((= (car L) n) #t)
(else (inlist (cdr L) n))
))
(define (uniquelist L)
(cond
((null? L) '())
((= 1 (length L)) L)
((inlist (cdr L) (car L)) (uniquelist (cdr L)))
(else (cons (car L) (uniquelist (cdr L))))
))
So..
(uniquelist '(1 1 2 3)) => (1 2 3)
...but...
(uniquelist '(1 2 3 1)) => (2 3 1)
Is there a simple alternative that maintains the order of the first instance of each duplicate?
The best way to solve this problem would be to use Racket's built-in remove-duplicates procedure. But of course, you want to implement the solution from scratch. Here's a way using idiomatic Racket, and notice that we can use member (another built-in function) in place of inlist:
(define (uniquelist L)
(let loop ([lst (reverse L)] [acc empty])
(cond [(empty? lst)
acc]
[(member (first lst) (rest lst))
(loop (rest lst) acc)]
[else
(loop (rest lst) (cons (first lst) acc))])))
Or we can write the same procedure using standard Scheme, as shown in SICP:
(define (uniquelist L)
(let loop ((lst (reverse L)) (acc '()))
(cond ((null? lst)
acc)
((member (car lst) (cdr lst))
(loop (cdr lst) acc))
(else
(loop (cdr lst) (cons (car lst) acc))))))
The above makes use of a named let for iteration, and shows how to write a tail-recursive implementation. It works as expected:
(uniquelist '(1 1 2 3))
=> '(1 2 3)
(uniquelist '(1 2 3 1))
=> '(1 2 3)
I have a requirement to return the last negative number in a list, using a recursive procedure. Right now I have a recursive procedure that returns all negative numbers in the list.
(define returnLastNeg
(lambda (lst)
(if (null? lst)
'()
(if (positive? (car lst))
(returnLastNeg (cdr lst))
(cons (car lst) (returnLastNeg (cdr lst)))))))
calling it with (returnLastNeg'(1 -2 -3 4 -5 6)) returns
Output:
'(-2 -3 -5)
I need it to only return -5 though. I tried to modify my procedure to check to see if the last element in the list is positive. If it is, I want to remove the last element and then call the procedure again. But when I do that I get an error (below)
Modified procedure:
(define returnLastNeg-modified
(lambda (lst)
(if (null? lst)
'()
(if (positive? (last lst))
(remove (last lst) (lst))
(cons (car lst) (returnLastNeg-modified (cdr lst)))))))
ERROR:
application: not a procedure;
expected a procedure that can be applied to arguments
given: '(1 -2 -3 4 -5 6)
arguments...: [none]
>
A simpler approach would be with a helper procedure (called "sub") in this example:
(define returnLastNeg
(lambda (lst)
(define sub
(lambda (lst last-neg)
(if (null? lst)
last-neg
(let ((c (car lst)))
(sub (cdr lst)
(if (negative? c) c last-neg))))))
(sub lst null)))
EDIT
Knowing that
(define <procedureName> (lambda (<params>) ... )
is the same as
(define (<procedureName> <params>) ... )
and reformatting a little, this becomes:
(define (returnLastNeg lst)
(define (sub lst last-neg)
(if (null? lst)
last-neg
(let ((c (car lst)))
(sub (cdr lst) (if (negative? c) c last-neg)))))
(sub lst null))
I hope it's clearer
last-neg gets set to null by the very last expression
the recursive call to sub has 2 parameters (split on 2 lines in the initial version, but newlines don't matter).
This is the same as the even shorter version
(define (returnLastNeg lst)
(let sub ((lst lst) (last-neg null))
(if (null? lst)
last-neg
(let ((c (car lst)))
(sub (cdr lst) (if (negative? c) c last-neg))))))
using a so-called "named let".
I'm trying to reverse a list, here's my code:
(define (reverse list)
(if (null? list)
list
(list (reverse (cdr list)) (car list))))
so if i enter (reverse '(1 2 3 4)), I want it to come out as (4 3 2 1), but right now it's not giving me that. What am I doing wrong and how can I fix it?
The natural way to recur over a list is not the best way to solve this problem. Using append, as suggested in the accepted answer pointed by #lancery, is not a good idea either - and anyway if you're learning your way in Scheme it's best if you try to implement the solution yourself, I'll show you what to do, but first a tip - don't use list as a parameter name, that's a built-in procedure and you'd be overwriting it. Use other name, say, lst.
It's simpler to reverse a list by means of a helper procedure that accumulates the result of consing each element at the head of the result, this will have the effect of reversing the list - incidentally, the helper procedure is tail-recursive. Here's the general idea, fill-in the blanks:
(define (reverse lst)
(<???> lst '())) ; call the helper procedure
(define (reverse-aux lst acc)
(if <???> ; if the list is empty
<???> ; return the accumulator
(reverse-aux <???> ; advance the recursion over the list
(cons <???> <???>)))) ; cons current element with accumulator
Of course, in real-life you wouldn't implement reverse from scratch, there's a built-in procedure for that.
Here is a recursive procedure that describes an iterative process (tail recursive) of reversing a list in Scheme
(define (reverse lst)
(define (go lst tail)
(if (null? lst) tail
(go (cdr lst) (cons (car lst) tail))))
(go lst ())))
Using substitution model for (reverse (list 1 2 3 4))
;; (reverse (list 1 2 3 4))
;; (go (list 1 2 3 4) ())
;; (go (list 2 3 4) (list 1))
;; (go (list 3 4) (list 2 1))
;; (go (list 4) (list 3 2 1))
;; (go () (list 4 3 2 1))
;; (list 4 3 2 1)
Here is a recursive procedure that describes a recursive process (not tail recursive) of reversing a list in Scheme
(define (reverse2 lst)
(if (null? lst) ()
(append (reverse2 (cdr lst)) (list (car lst)))))
(define (append l1 l2)
(if (null? l1) l2
(cons (car l1) (append (cdr l1) l2))))
Using substitution model for (reverse2 (list 1 2 3 4))
;; (reverse2 (list 1 2 3 4))
;; (append (reverse2 (list 2 3 4)) (list 1))
;; (append (append (reverse2 (list 3 4)) (list 2)) (list 1))
;; (append (append (append (reverse2 (list 4)) (list 3)) (list 2)) (list 1))
;; (append (append (append (append (reverse2 ()) (list 4)) (list 3)) (list 2)) (list 1))
;; (append (append (append (append () (list 4)) (list 3)) (list 2)) (list 1))
;; (append (append (append (list 4) (list 3)) (list 2)) (list 1))
;; (append (append (list 4 3) (list 2)) (list 1))
;; (append (list 4 3 2) (list 1))
;; (list 4 3 2 1)
Tail recursive approach using a named let:
(define (reverse lst)
(let loop ([lst lst] [lst-reversed '()])
(if (empty? lst)
lst-reversed
(loop (rest lst) (cons (first lst) lst-reversed)))))
This is basically the same approach as having a helper function with an accumulator argument as in Oscar's answer, where the loop binding after let makes the let into an inner function you can call.
Here's a solution using build-list procedure:
(define reverse
(lambda (l)
(let ((len (length l)))
(build-list len
(lambda (i)
(list-ref l (- len i 1)))))))
This one works but it is not a tail recursive procedure:
(define (rev lst)
(if (null? lst)
'()
(append (rev (cdr lst)) (car lst))))
Tail recursive solution:
(define (reverse oldlist)
(define (t-reverse oldlist newlist)
(if (null? oldlist)
newlist
(t-reverse (cdr oldlist) (cons (car oldlist) newest))))
(t-reverse oldlist '()))
Just left fold the list using cons:
(define (reverse list) (foldl cons null list))
This is also efficient because foldl is tail recursive and there is no need for append. This can also be done point-free (using curry from racket):
(define reverse (curry foldl cons null))
(define reverse?
(lambda (l)
(define reverse-aux?
(lambda (l col)
(cond
((null? l) (col ))
(else
(reverse-aux? (cdr l)
(lambda ()
(cons (car l) (col))))))))
(reverse-aux? l (lambda () (quote ())))))
(reverse? '(1 2 3 4) )
One more answer similar to Oscar's. I have just started learning scheme, so excuse me in case you find issues :).
There's actually no need for appending or filling the body with a bunch of lambdas.
(define (reverse items)
(if (null? items)
'()
(cons (reverse (cdr items)) (car items))))
I think it would be better to use append instead of cons
(define (myrev l)
(if (null? l)
'()
(append (myrev (cdr l)) (list (car l)))
)
)
this another version with tail recursion
(define (myrev2 l)
(define (loop l acc)
(if (null? l)
acc
(loop (cdr l) (append (list (car l)) acc ))
)
)
(loop l '())
)
Given a list of numbers, say, (1 3 6 10 0), how do you compute differences (xi - xi-1), provided that you have x-1 = 0 ?
(the result in this example should be (1 2 3 4 -10))
I've found this solution to be correct:
(define (pairwise-2 f init l)
(first
(foldl
(λ (x acc-data)
(let ([result-list (first acc-data)]
[prev-x (second acc-data)])
(list
(append result-list (list(f x prev-x)))
x)))
(list empty 0)
l)))
(pairwise-2 - 0 '(1 3 6 10 0))
;; => (1 2 3 4 -10)
However, I think there should be more elegant though no less flexible solution. It's just ugly.
I'm new to functional programming and would like to hear any suggestions on the code.
Thanks.
map takes multiple arguments. So I would just do
(define (butlast l)
(reverse (cdr (reverse l))))
(let ((l '(0 1 3 6 10)))
(map - l (cons 0 (butlast l)))
If you want to wrap it up in a function, say
(define (pairwise-call f init l)
(map f l (cons init (butlast l))))
This is of course not the Little Schemer Way, but the way that avoids writing recursion yourself. Choose the way you like the best.
I haven't done scheme in dog's years, but this strikes me as a typical little lisper type problem.
I started with a base definition (please ignore misplacement of parens - I don't have a Scheme interpreter handy:
(define pairwise-diff
(lambda (list)
(cond
((null? list) '())
((atom? list) list)
(t (pairwise-helper 0 list)))))
This handles the crap cases of null and atom and then delegates the meat case to a helper:
(define pairwise-helper
(lambda (n list)
(cond
((null? list) '())
(t
(let ([one (car list)])
(cons (- one n) (pairwise-helper one (cdr list))))
))))
You could rewrite this using "if", but I'm hardwired to use cond.
There are two cases here: null list - which is easy and everything else.
For everything else, I grab the head of the list and cons this diff onto the recursive case. I don't think it gets much simpler.
After refining and adapting to PLT Scheme plinth's code, I think nearly-perfect solution would be:
(define (pairwise-apply f l0 l)
(if (empty? l)
'()
(let ([l1 (first l)])
(cons (f l1 l0) (pairwise-apply f l1 (rest l))))))
Haskell tells me to use zip ;)
(define (zip-with f xs ys)
(cond ((or (null? xs) (null? ys)) null)
(else (cons (f (car xs) (car ys))
(zip-with f (cdr xs) (cdr ys))))))
(define (pairwise-diff lst) (zip-with - (cdr lst) lst))
(pairwise-diff (list 1 3 6 10 0))
; gives (2 3 4 -10)
Doesn't map finish as soon as the shortest argument list is exhausted, anyway?
(define (pairwise-call fun init-element lst)
(map fun lst (cons init-element lst)))
edit: jleedev informs me that this is not the case in at least one Scheme implementation. This is a bit annoying, since there is no O(1) operation to chop off the end of a list.
Perhaps we can use reduce:
(define (pairwise-call fun init-element lst)
(reverse (cdr (reduce (lambda (a b)
(append (list b (- b (car a))) (cdr a)))
(cons (list init-element) lst)))))
(Disclaimer: quick hack, untested)
This is the simplest way:
(define (solution ls)
(let loop ((ls (cons 0 ls)))
(let ((x (cadr ls)) (x_1 (car ls)))
(if (null? (cddr ls)) (list (- x x_1))
(cons (- x x_1) (loop (cdr ls)))))))
(display (equal? (solution '(1)) '(1))) (newline)
(display (equal? (solution '(1 5)) '(1 4))) (newline)
(display (equal? (solution '(1 3 6 10 0)) '(1 2 3 4 -10))) (newline)
Write out the code expansion for each of the example to see how it works.
If you are interested in getting started with FP, be sure to check out How To Design Program. Sure it is written for people brand new to programming, but it has tons of good FP idioms within.
(define (f l res cur)
(if (null? l)
res
(let ((next (car l)))
(f (cdr l) (cons (- next cur) res) next))))
(define (do-work l)
(reverse (f l '() 0)))
(do-work '(1 3 6 10 0))
==> (1 2 3 4 -10)