How do I get elements from 2nd to 7th from a list, using only the following three functions:
cons
car
cdr
Example;
> (two-to-seven (list 8 9 5 1 0 3 6 2 4))
> (9 5 1 0 3 6)
Thanks.
> (define (t2s xs)
(cons (car (cdr xs)) (cons (car (cdr (cdr xs))) (cons (car (cdr (cdr (cdr xs)))) (cons (car (cdr (cdr (cdr (cdr xs))))) (cons (car (cdr (cdr (cdr (cdr (cdr xs)))))) (cons (car (cdr (cdr (cdr (cdr (cdr (cdr xs))))))) (list))))))))
> (t2s (list 8 2 5 4 0 3 6 1 1))
(2 5 4 0 3 6)
My solution. You might want to initialize the acumulator ( acum ) with 1, and/or use >= and <=. You provided no output.
(define (test-get start stop tlst)
(define acum 0)
(define (get-elems lst)
(cond ((null? lst) empty)
((and (symbol? (car lst))
(< acum stop)
(> acum start))
(set! acum (+ 1 acum))
(cons (car lst) (get-elems (cdr lst))))
((symbol? (car lst))
(set! acum (+ 1 acum))
(get-elems (cdr lst)))
(else (append (get-elems (car lst)) (get-elems (cdr lst))))))
(get-elems tlst))
Sample output
> (test-get 0 3 '(a (b) (c (d)) e (((f))) (h (i (j))) (k l)))
(b c)
> (test-get 2 6 '(a (b) (c (d)) e (((f))) (h (i (j))) (k l)))
(d e f)
> (test-get 2 7 '(a (b) (c (d)) e (((f))) (h (i (j))) (k l)))
(d e f h)
And if you're bothered by the append showing there you could replace it with your own using cons, cdr, car
(define (my-append l1 l2)
(if (null? l1)
l2
(cons (car l1) (my-append (cdr l1) l2))))
To also get rid of the set! so we'll be more in the bounds of functional programming (not tested):
(define (test-get start stop tlst)
(define (liniarize lst)
(cond ((null? lst) empty)
((symbol? (car lst)) (cons (car lst) (liniarize (cdr lst))))
(else (my-append (liniarize (car lst)) (liniarize (cdr lst))))))
(define (take-elems lst acum)
(cond ((null? lst) empty)
((and (< acum stop)
(> acum start)) (cons (car lst) (take-elems (cdr lst) (+ 1 acum))))
(else (take-elems lst (+ 1 acum)))))
(take-elems (liniarize tlst) 0))
Related
I've just started to learn Racket and I need to create a procedure that merge two list randomly.
This is my code:
#lang racket
(define merge-randomly
(lambda (lst1 lst2)
(cond ((and (null? lst1) (null? lst2)) null)
((null? lst1) lst2)
((null? lst2) lst1)
(else
(cond ((> (random) 0.5) (cons (cons (car lst1) (car lst2)) (merge-randomly (cdr lst1) (cdr lst2))))
(else (cons (cons (car lst2) (car lst1)) (merge-randomly (cdr lst1) (cdr lst2))))
)
)
)
)
)
I need to use with list like these two:
(define l1 '((1 2 3) (7 8 9)))
(define l2 '((4 5 6)))
I need to create a new list like this one:
'((4 5 6) (1 2 3) (7 8 9))
But I get this list:
'(((4 5 6) 1 2 3) (7 8 9))
I'm doing something wrong, probably here, (cons (cons (car lst1) (car lst2)), or here, (cons (cons (car lst2) (car lst1)), at the else instruction in first cond.
How can I get the list I want to get?
Your guess is correct. The format for cons is this:
(cons first-element rest-of-the-list)
So, when you use (const '(4 5 6) '(1 2 3)), it returns ((4 5 6) 1 2 3).
The correct format for what you are trying to do would be:
(cons (car lst1) (cons (car ls2) (merge-randomly (cdr lst1) (cdr lst2))))
and similarly for the second case.
Here's what the final function should look like:
(define merge-randomly
(lambda (lst1 lst2)
(cond ((and (null? lst1) (null? lst2)) null)
((null? lst1) lst2)
((null? lst2) lst1)
(else
(cond ((> (random) 0.5) (cons (car lst1) (cons (car lst2) (merge-randomly (cdr lst1) (cdr lst2)))))
(else (cons (car lst2) (cons (car lst1) (merge-randomly (cdr lst1) (cdr lst2)))))
)
)
)
)
)
The problem is with (cons (cons (car lst1) (car lst2)) ...). Change it to (cons (car lst1) (cons (car lst2) ...).
PS Your closing parentheses are not idiomatically placed.
I want to write a simple function (highest L k), which take a list and interger K>0, return a new list with k highest numbers.
(highest '(6 7 8 5 3 2) 3) give (6 7 8)
(define (highest L k)
(if (= k 0)
'()
(cons (highesthelper (car L) L)
((highest (remove (highesthelper (car L) L) L) (- k 1))))))
(define (remove E L)
(cond
((null? L)'())
((= E (car L)) (cdr L))
(else (cons (car L) (remove E (cdr L))))))
(define (highesthelper Hi L)
(cond
((null? L) Hi)
((> Hi (car L)) highesthelper Hi (cdr L))
(else (highesthelper (car L) (cdr L)))))
(highest '(1 7 4 5 3) 2)
I can run the helper and remove function without problem, but the highest function give me bugs, can someone help me?
Thanks
I fixed a few simple mistakes. Note in particular the (> Hi (car L)) case of highesthelper.
(define (highest L k)
(if (= k 0)
'()
(cons (highesthelper (car L) L)
(highest (remove (highesthelper (car L) L) L) (- k 1)))))
(define (remove E L)
(cond
((null? L) '())
((= E (car L)) (cdr L))
(else (cons (car L) (remove E (cdr L))))))
(define (highesthelper Hi L)
(cond
((null? L) Hi)
((> Hi (car L)) (highesthelper Hi (cdr L)))
(else (highesthelper (car L) (cdr L)))))
(highest '(1 7 4 5 3) 2)
I have a list '(1 2 1 1 4 5) and want output list as '((1 3)(2 1)(4 1)(5 1)). I have written a small code but I am stuck with how to calculate the cardinality for each number and then put it as pair in list. Can anyone please look at my code and give some ideas?
(define set2bags
(lambda (randlist)
(cond ((null? randlist) '())
(else
(sort randlist)
(makepairs randlist)))))
(define makepairs
(lambda (inlist)
(let ((x 0)) ((newlist '()))
(cond ((zero? (car inlist)) '())
(else
(eq? (car inlist)(car (cdr inlist)))
(+ x 1)
(makepairs (cdr inlist))
(append newlist (cons (car inlist) x)))))))
Your current solution is incorrect - it doesn't even compile. Let's start again from scratch, using a named let for traversing the input list:
(define set2bags
(lambda (randlist)
(cond ((null? randlist) '())
(else (makepairs (sort randlist >))))))
(define makepairs
(lambda (inlist)
(let loop ((lst inlist)
(prv (car inlist))
(num 0)
(acc '()))
(cond ((null? lst)
(cons (list prv num) acc))
((= (car lst) prv)
(loop (cdr lst) prv (add1 num) acc))
(else
(loop (cdr lst) (car lst) 1 (cons (list prv num) acc)))))))
Now it works as expected:
(set2bags '(1 2 1 1 4 5))
=> '((1 3) (2 1) (4 1) (5 1))
The trick is keeping a counter for the cardinality (I called it num), and incrementing it as long as the same previous element (I named it prv) equals the current element. Whenever we find a different element, we add a new pair to the output list (called acc) and reset the previous element and the counter.
Your code is fairly hard to read without proper formating.
I notice a two branch cond, which is easier to read as an if.
In your else clause of set2bags, you call (sort randlist) but leave it as is. You actually want to use this in the next s-expression (makepairs (sort randlist))
So far a pretty good idea.
Now in makepairs you should have better abstraction, say let variables like-first and unlike-first. If the inlist is null, then the function should be the null list, else it's the pair with the car being the list of the car of like-first and the length of like-first and the cdr being the result of calling makepairs on the unlike-first list
(define (makepairs inlist)
(let ((like-first (filter (lambda (x) (equal? x (car inlist)) inlist))
(unlike-first (filter (lambda (x) (not (equal? x (car inlist))) inlist)))
(if (null? inlist)
'()
(cons (list (car inlist) (length like-first)) (makepairs unlike-first)))))
more effecient version
(define (makepairs inlist)
(if (null? inlist)
'()
(let loop ((firsts (list (car inlist)))
(but-firsts (cdr inlist)))
(if (or (null? but-firsts)
(not (equal? (car firsts) (car but-firsts))))
(cons (list (car firsts) (length firsts))
(makepairs but-firsts))
(loop (cons (car but-firsts) firsts) (cdr but-firsts))))))
]=> (makepairs (list 1 1 1 2 4 5))
;Value 17: ((1 3) (2 1) (4 1) (5 1))
If you have your own implementation of sort, say a mergesort you could write this right into the merge part for the best effeciency.
(define (set2bags lst)
(mergesort2bags lst <))
(define (mergesort2bags lst pred)
(let* ((halves (divide-evenly lst))
(first-half (car halves))
(other-half (cadr halves)))
(cond ((null? lst) '())
((null? (cdr lst)) (list (list (car lst) 1)))
(else
(merge-bags
(mergesort2bags first-half pred)
(mergesort2bags other-half pred)
pred)))))
(define (divide-evenly lst)
(let loop
((to-go lst)
(L1 '())
(l2 '()))
(if (null? to-go)
(list L1 L2)
(loop (cdr to-go) (cons (car to-go) L2) L1))))
(define (merge-bags L1 L2 pred)
(cond ((null? L1) L2)
((null? L2) L1)
((pred (caar L1) (caar L2))
(cons (car L1) (merge-bags (cdr L1) L2 pred)))
((equal? (caar L1) (caar L2))
(cons (list (caar L1) (+ (cadar L1) (cadar L2)))
(merge-bags (cdr L1) (cdr L2) pred)))
(else (cons (car L2) (merge-bags L1 (cdr L2) pred)))))
(mergesort2bags (list 1 2 1 1 4 5) <)
;Value 46: ((1 3) (2 1) (4 1) (5 1))
I'm thinking for very large datasets with a lot of repetition this method would pay off.
My implementation of flatten looks like this:
(define flatten
(lambda (lst)
(if (null? lst)
lst
(append
(rtn-lst (car lst))
(flatten (cdr lst))))))
(define rtn-lst
(lambda (lst)
(cond
((null? lst)
empty)
((atom? lst)
(list lst))
(else
(flatten lst)))))
While standard implementation is:
(define (flatten lst)
(cond
((null? list)
empty)
((list? (car lst))
(append (flatten (car lst)) (flatten (cdr lst))))
(else
(cons (car lst) (flatten (cdr lst))))))
Apart from the obvious verboseness, what else is wrong with my code?
I'd try this:
(define rtn-lst
(lambda (lst)
(cond
((list? lst)
(if (null? lst)
empty
(flatten-list lst)))
((atom? lst)
(list lst))
(else
(flatten-list lst)))))
Probably we have different implementations of Scheme.
EDIT:
With modified else branch:
(define rtn-lst
(lambda (lst)
(cond
((list? lst)
(if (null? lst)
empty
(flatten-list lst)))
(else
(list lst)))))
I would consider atom? to be wrong. You want to know if the lst is a list, so use list?. atom? can return false on vector or string for some implementations. But i do not know for sure. The rest is quit good.
How about something like this:
(define foo
(lambda (e)
(cond ((pair? e) `(,#(foo (car e)) ,#(foo (cdr e))))
((null? e) '())
(else (list e)))))
Where for example:
> (foo '(((2 3) (4 . 5) 8)))
(2 3 4 5 8)
Does this do what you want?
How about something like this:
(define (flatten x y)
(if (null? x)
y
(if (list? (car x))
(flatten (append (car x) (cdr x)) y)
(flatten (cdr x) (append y (list (car x)))))))
(define (flat x)
(flatten x '()))
> (flat '(1(2(3(4(5)6)7)8)9))
(1 2 3 4 5 6 7 8 9)
and closure version:
(define (flatten x)
(define (flatten x y)
(if (null? x)
y
(if (list? (car x))
(flatten (append (car x) (cdr x)) y)
(flatten (cdr x) (append y (list (car x)))))))
(flatten x '()))
> (flatten '(1(2(3(4(5)6)7)8)9))
(1 2 3 4 5 6 7 8 9)
This is my first experience with Scheme. I have a list with integers and I wanna get the sum of all even number in list.
; sum_even
(define (sum_even l)
(if (null? l) l
(cond ((even? (car l)) 0)
((not(even? (car l))) (car l)))
(+ (sum_even (car l) (sum_even(cdr l))))))
(sum_even '(2 3 4))
(define (sum_even l)
(cond ((null? l) 0)
((even? (car l)) (+ (car l) (sum_even (cdr l))))
(else (sum_even (cdr l)))))
Not tested
You're not exactly asking a question. Are you checking if your solution is correct or looking for an alternate solution?
You can also implement it as follows via
(apply + (filter even? lst))
edit: If, as you mentioned, you can't use filter, this solution will work and is tail-recursive:
(define (sum-even lst)
(let loop ((only-evens lst) (sum 0))
(cond
((null? only-evens) sum)
((even? (car only-evens))
(loop (cdr only-evens) (+ (car only-evens) sum)))
(else (loop (cdr only-evens) sum)))))
(define (sum-even xs)
(foldl (lambda (e acc)
(if (even? e)
(+ e acc)
acc))
0
xs))
Example:
> (sum-even (list 1 2 3 4 5 6 6))
18
Here is another one with higher order functions and no explicit recursion:
(use srfi-1)
(define (sum-even ls) (fold + 0 (filter even? ls)))
Consider using the built-in filter function. For example:
(filter even? l)
will return a list of even numbers in the list l. There are lots of ways to sum numbers in a list (example taken from http://groups.engin.umd.umich.edu/CIS/course.des/cis400/scheme/listsum.htm):
;
; List Sum
; By Jerry Smith
;
(define (list-sum lst)
(cond
((null? lst)
0)
((pair? (car lst))
(+(list-sum (car lst)) (list-sum (cdr lst))))
(else
(+ (car lst) (list-sum (cdr lst))))))