I have a question on a homework assignment that is as follows:
I have the first part (double-list-elements) complete
(define (double-list-elements s)
(if (null? s)
'()
(cons (* 2 (car s))
(double-list-elements (cdr s)))))
but I honestly have absolutely no idea how to proceed with double-list-elements-one. Any pointers would be greatly appreciated.
Close But No Cigar:
(define (double-list-elements s)
(if (null? s)
'()
(cons (* 2 (car s))
(double-list-elements (cdr s)))))
(define (custom-map proc lst)
(if (null? lst)
'()
(cons (proc lst)
(custom-map proc (cdr lst)))))
(define (double-list-elements-one func s)
(custom-map double-list-elements s))
(double-list-elements-one double-list-elements '(1 2 3 4 5 6))
Output = (list (list 2 4 6 8 10 12) (list 4 6 8 10 12) (list 6 8 10 12) (list 8 10 12) (list 10 12) (list 12))
I need to pass double-list-elements to double-list-elements-one as a parameter as well as the list.
You just have to write your own map, it's very very similar to what you already have, simply pass the part that changes as a procedure parameter, and invoke it on the right place:
(define (mymap proc lst)
(if (null? lst)
'()
(cons <invoke proc on current element>
(mymap proc (cdr lst)))))
(define (double-list-elements-one s)
(mymap <pass a proper lambda> s))
(double-list-elements-one '(1 2 3 4 5))
=> '(2 4 6 8 10)
Related
I am encountering a issue that I need to add up the second number of each list. For example, suppose I have a list of lists like below,
(list (list -4
(list (list -1 4) (list 1 7)))
(list 1 (list (list -2 5) (list 3 3)))
(list 3 12))
Then my job is to add up 4 + 7 + 5 + 3 + 12 = 31. However, the list can have multiple sub lists. But the second item inside a list can either be a number or a list. If it is a list, then we need to dig deeper into this list until we get a number.
Thanks!
Solution
(define (atom? x)
(and (not (null? x))
(not (pair? x))))
(define (my-and x y)
(and x y))
(define (every? l)
(foldr my-and #t l))
(define (flat-list? l)
(cond ((null? l) #t)
((every? (map atom? l)) #t)
(else #f)))
(define (add-only-seconds l)
(define (l-sec-add l acc)
(cond ((null? l) acc)
((atom? l) acc)
((flat-list? l) (+ (second l) acc))
((list? l) (apply + acc (map (lambda (x) (l-sec-add x 0)) l)))))
(l-sec-add l 0))
Example test
(define example-list (list (list -4
(list (list -1 4) (list 1 7)))
(list 1 (list (list -2 5) (list 3 3)))
(list 3 12)))
(add-only-seconds example-list) ;; 31
I used common-lisp-typical functions atom? and every?.
Since and cannot be used in foldr, I defined my-add to make add a function which can be used infoldr`.
What I want to do is define a list such as (define lst '(1 2 3 4 5 6)) and then call (split lst) which will return '((1 3 5) (2 4 6)).
Some examples:
When lst is '(1 2 3 4 5 6) it should return '((1 3 5) (2 4 6))
When lst is '(1 2 3 4 5 6 7) it should return '((1 3 5 7) (2 4 6))
When lst is '("a" "little" "bit" "of" "that" "to" "spice" "things" "up") it should return '(("a" "bit" "that" "spice" "up") ("little" "of" "to" "things"))
It should alternate when building the two lists. So the first index should go in the first list, second index in the second list, third index in the first list, etc.
Here is my current script.
(define (split lst)
(cond ((null? lst) lst)
((null? (cdr lst)) lst)
((cons (cons (car lst) (split (cddr lst))) (cons (cadr lst) (split (cddr lst)))))))
Currently, this is what outputs when I split the list '(1 2 3 4 5 6)
((1 (3 (5) 6) 4 (5) 6) 2 (3 (5) 6) 4 (5) 6)
Lets fix your code step by step:
(define (split lst)
(cond ((null? lst) lst)
((null? (cdr lst)) lst)
((cons (cons (car lst) (split (cddr lst))) (cons (cadr lst) (split (cddr lst)))))))
The first thing I notice is the lack of an else in the last case of the cond. Conds are supposed to look like:
(cond (question-1 answer-1)
(question-2 answer-2)
...
(else else-answer))
With an else inserted your code looks like this:
(define (split lst)
(cond ((null? lst) lst)
((null? (cdr lst)) lst)
(else
(cons (cons (car lst) (split (cddr lst))) (cons (cadr lst) (split (cddr lst)))))))
The next thing is the first base case, or the answer to the (null? lst) cond question. On an empty list what should it return?
It seems like no matter how long the list is, it should always return a list of exactly two inner lists. So when lst is empty the logical answer would be (list '() '()).
(define (split lst)
(cond ((null? lst)
(list '() '()))
((null? (cdr lst)) lst)
(else
(cons (cons (car lst) (split (cddr lst))) (cons (cadr lst) (split (cddr lst)))))))
Next is the second base case, the answer to the (null? (cdr lst)) cond question. Again it should return a list of exactly two inner lists:
(list ??? ???)
The the first index should go in the first list, and then there's nothing to go in the second list.
(list (list (car lst)) '())
In the context of your code:
(define (split lst)
(cond ((null? lst)
(list '() '()))
((null? (cdr lst))
(list (list (car lst)) '()))
(else
(cons (cons (car lst) (split (cddr lst))) (cons (cadr lst) (split (cddr lst)))))))
Now, what is the behavior of this function?
> (split '(1 2 3 4 5 6))
'((1 (3 (5 () ()) 6 () ()) 4 (5 () ()) 6 () ()) 2 (3 (5 () ()) 6 () ()) 4 (5 () ()) 6 () ())
Still not what you want. So what is the last case, recursive case, supposed to do?
Consider what you're "given" and what you need to "produce".
Given:
(car lst) the first element
(cadr lst) the second element
(split (cddr lst)) a list of exactly two inner lists
You should produce:
(list ??? ???)
Where the first ??? hole contains the first element and the first of the two inner lists, and the second ??? hole contains the second element and the second of the two inner lists.
This suggests code like this:
(list (cons (car lst) (first (split (cddr lst))))
(cons (cadr lst) (second (split (cddr lst)))))
Or, since car gets the first and cadr gets the second:
(list (cons (car lst) (car (split (cddr lst))))
(cons (cadr lst) (cadr (split (cddr lst)))))
In the context of your code:
(define (split lst)
(cond ((null? lst)
(list '() '()))
((null? (cdr lst))
(list (list (car lst)) '()))
(else
(list (cons (car lst) (car (split (cddr lst))))
(cons (cadr lst) (cadr (split (cddr lst))))))))
Using it produces what you want:
> (split '(1 2 3 4 5 6))
'((1 3 5) (2 4 6))
> (split '(1 2 3 4 5 6 7))
'((1 3 5 7) (2 4 6))
> (split '("a" "little" "bit" "of" "that" "to" "spice" "things" "up"))
'(("a" "bit" "that" "spice" "up") ("little" "of" "to" "things"))
Now what was the difference between this and what you had before?
Your code before:
(cons (cons (car lst) (split (cddr lst)))
(cons (cadr lst) (split (cddr lst))))
The fixed version:
(list (cons (car lst) (car (split (cddr lst))))
(cons (cadr lst) (cadr (split (cddr lst)))))
The first difference is that your original version uses cons on the outside, while the fixed version uses list instead. This is because (list ??? ???) always returns a list of exactly two elements, while (cons ??? ???) can return a list of any size greater than 1, which has the first thing merged onto an existing second list. (list ??? ???) is what you want here because you specified that it should return a list of exactly two inner lists.
The second difference is in how you use the recursive call (split (cddr lst)).
This has to do with how you interpreted the "given" part of the recursive case. You had assumed that the first call to split would give you the first "inner" list, and the second call to split would give you the second "inner" list. In fact it gives you a list of both of those both times. So for the first one you have to get the "first" or car of it, and for the second one you have get the "second" or cadr of it.
Looks like this might be what you're looking for:
(define (split lst)
(define (loop lst do-odd odds evens)
(if (null? lst)
(list (reverse odds) (reverse evens))
(loop (cdr lst) (not do-odd)
(if do-odd (cons (car lst) odds) odds)
(if (not do-odd) (cons (car lst) evens) evens))))
(loop lst #t '() '()))
In use:
1 ]=> (split '(1 2 3 4 5 6))
;Value 2: ((1 3 5) (2 4 6))
1 ]=> (split '(1 2 3 4 5 6 7))
;Value 3: ((1 3 5 7) (2 4 6))
This uses the variable do-odd in the inner loop function (which is tail-recursive, by the way, so it is fast!) to figure out which list it should add the (car lst) to.
Downsides to this function: the call to reverse in the base case can be expensive if your lists are very long. This may or may not be a problem. Profiling your code will tell you if it's a bottleneck.
UPDATE: You can also use the function reverse!, which destructively modifies the array in question. I did some informal profiling, and it didn't seem to make that much of a difference speed-wise. You will have to test this under your specific circumstances.
Now, if this isn't intended to be performant, use whatever you want! :)
My shortest solution
(define (split l)
(cond ((null? l) '(() ()))
((null? (cdr l)) (list (list (car l)) '()))
(else (map cons (list (car l) (cadr l))
(split (cddr l))))))
Similar but wordier solution
Ensure that split always returns a list of two lists.
Then you can define it quite compactly:
(define (split l)
(cond ((null? l) '(() ()))
((null? (cdr l)) (list (list (car l)) '()))
(else (double-cons (list (car l) (cadr l))
(split (cddr l))))))
with double-cons being:
(define (double-cons l lol)
(list (cons (car l) (car lol))
(cons (cadr l) (cadr lol))))
double-cons:
(double-cons '(a 1) '((b c) (2 3)))
; => '((a b c) (1 2 3))
Other double-cons definitions
This takes more lines but makes it easier to read:
(define (double-cons l lol)
(let ((e1 (car l))
(e2 (cadr l))
(l1 (car lol))
(l2 (cadr lol)))
(list (cons e1 l1) (cons e2 l2))))
Or a double-cons which conses even more elements and lists in parallel:
(define (parallel-cons l lol)
(map cons l lol))
; it is `variadic` and conses as many elements with their lists
; as you want:
(parallel-cons '(1 a A '(a)) '((2 3) (b c d e) (B C) ((b) (c))))
; '((1 2 3) (a b c d e) (A B C) ('(a) (b) (c)))
; this combination of `map` and `cons` is used in the shortest solution above.
I'm working on sorting a list of lists by their first element for example
(sort (list '(2 1 6 7) '(4 3 1 2 4 5) '(1 1))))
expected output => ('(1 1) '(2 1 6 7) '(4 3 1 2 4 5))
The algorithm I used is bubble sort. And I modified it to deal with lists. However, the code doesn't compile. The error is
mcar: contract violation
expected: mpair?
given: 4
Can someone correct my code and explain it. Thank you
(define (bubble L)
(if (null? (cdr L))
L
(if (< (car (car L)) (car (cadr L)))
(list (car L)
(bubble (car (cdr L))))
(list (cadr L)
(bubble (cons (car (car L)) (car (cddr L))))))))
(define (bubble-sort N L)
(cond ((= N 1) (bubble L))
(else
(bubble-sort (- N 1) (bubble L)))))
(define (bubble-set-up L)
(bubble-sort (length L) L))
(define t3 (list '(2 1 6 7) '(4 3 1 2 4 5) '(1 2 3) '(1 1)))
(bubble-set-up t3)
How about (sort (lambda (x y)(< (car x)(car y))) <YOUR_LIST>)?
I have fixed a few mistakes. There is at least one mistake left.
Consider the case where L only contains one element.
#lang r5rs
(define (bubble L)
(if (null? (cdr L))
L
(if (< (car (car L)) (car (cadr L)))
(cons (car L)
(bubble (cdr L)))
(cons (cadr L)
(bubble (cons (car L) (cddr L)))))))
(define (bubble-sort N L)
(cond ((= N 1) (bubble L))
(else
(bubble-sort (- N 1) (bubble L)))))
(define (bubble-set-up L)
(bubble-sort (length L) L))
(define t3 (list '(2 1 6 7) '(4 3 1 2 4 5) '(1 2 3) '(1 1)))
(display (bubble-set-up t3))
(newline)
I'm working on implementing a bubble sorting algorithm in Scheme, and I must say that the functional way of programming is a strange concept and I am struggling a bit to grasp it.
I've successfully created a function that will bubble up the first largest value we come across, but that's about all it does.
(bubbleH '(5 10 9 8 7))
(5 9 8 7 10)
I am struggling with the helper function that is required to completely loop through the list until no swaps have been made.
Here's where I am at so far, obviously it is not correct but I think I am on the right track. I know that I could pass in the number of elements in the list myself, but I am looking for a solution different from that.
(define bubbaS
(lambda (lst)
(cond (( = (length lst) 1) (bubba-help lst))
(else (bubbaS (bubba-help lst))))))
Using the bubble-up and bubble-sort-aux implementations in the possible-duplicate SO question I referenced...
(define (bubble-up L)
(if (null? (cdr L))
L
(if (< (car L) (cadr L))
(cons (car L) (bubble-up (cdr L)))
(cons (cadr L) (bubble-up (cons (car L) (cddr L)))))))
(define (bubble-sort-aux N L)
(cond ((= N 1) (bubble-up L))
(else (bubble-sort-aux (- N 1) (bubble-up L)))))
..., this is simple syntactic sugar:
(define (bubbleH L)
(bubble-sort-aux (length L) L))
With the final bit of syntactic sugar added, you should get exactly what you specified in your question:
(bubbleH '(5 10 9 8 7))
=> (5 7 8 9 10)
You can tinker with everything above in a repl.it session I saved & shared.
Here's my own tail-recursive version.
The inner function will bubble up the largest number just like your bubbleH procedure. But instead of returning a complete list, it will return 2 values:
the unsorted 'rest' list
the largest value that has bubbled up
such as:
> (bsort-inner '(5 1 4 2 8))
'(5 2 4 1)
8
> (bsort-inner '(1 5 4 2 8))
'(5 2 4 1)
8
> (bsort-inner '(4 8 2 5))
'(5 2 4)
8
Now the outer loop just has to cons the second value returned, and iterate on the remaining list.
Code:
(define (bsort-inner lst)
(let loop ((lst lst) (res null))
(let ((ca1 (car lst)) (cd1 (cdr lst)))
(if (null? cd1)
(values res ca1)
(let ((ca2 (car cd1)) (cd2 (cdr cd1)))
(if (<= ca1 ca2)
(loop cd1 (cons ca1 res))
(loop (cons ca1 cd2) (cons ca2 res))))))))
(define (bsort lst)
(let loop ((lst lst) (res null))
(if (null? lst)
res
(let-values (((ls mx) (bsort-inner lst)))
(loop ls (cons mx res))))))
For a recursive version, I prefer one where the smallest value bubbles in front:
(define (bsort-inner lst)
; after one pass, smallest element is in front
(let ((ca1 (car lst)) (cd1 (cdr lst)))
(if (null? cd1)
lst ; just one element => sorted
(let ((cd (bsort-inner cd1))) ; cd = sorted tail
(let ((ca2 (car cd)) (cd2 (cdr cd)))
(if (<= ca1 ca2)
(cons ca1 cd)
(cons ca2 (cons ca1 cd2))))))))
(define (bsort lst)
(if (null? lst)
null
(let ((s (bsort-inner lst)))
(cons (car s) (bsort (cdr s))))))
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 '())
)