Problem:
Write a function (split l) that takes a list and partitions it into two equal-sized (within one) lists, and returns a pair whose car is the first list and whose cdr is the second list.
My code:
(define split list)
(let ((half (/ (length list) 2)
(cons (car half list)
(cdr half list))))
Here's another possible implementation using the tortoise and hare algorithm:
(define (split lst)
(let loop ((tortoise lst) (hare lst) (acc '()))
(if (or (null? hare) (null? (cdr hare)))
(cons (reverse acc) tortoise)
(loop (cdr tortoise)
(cddr hare)
(cons (car tortoise) acc)))))
The above solution has the advantage of traversing the list only once, notice that we don't need to know the length of the list to make the split. It's called "tortoise and hare" because we keep two pointers over the list: one advances slowly, one element at a time (the "tortoise") and the other goes faster, two elements at a time (the "hare"). The algorithm stops when the hare reaches the end of the input list.
Alternatively, we can implement a more idiomatic (albeit slower) solution using built-in procedures. Assuming that the take and drop procedures are available in your interpreter (if not, import them from SRFI-1), this is closer to what you had in mind:
(define (split lst)
(let ((half (quotient (length lst) 2)))
(cons (take lst half)
(drop lst half))))
Either way, it works as expected:
(split '(1 2 3 4))
=> ((1 2) 3 4)
(split '(1 2 3 4 5))
=> ((1 2) 3 4 5)
Try:
(define (splitAt n lst)
(let loop ((acc '()) (n n) (lst lst))
(if (or (= n 0) (null? lst)) (cons (reverse acc) lst)
(loop (cons (car lst) acc) (- n 1) (cdr lst)))))
(define (split lst) (splitAt (quotient (length lst) 2) lst))
It works as follows:
(split '(1 2 3 4)) => ((1 2) 3 4)
(split '(1 2 3 4 5)) => ((1 2) 3 4 5)
Hope this helps.
Related
Suppose, I got a list(s) in Racket of:
`(1 2 3)
`(1 2 3 4)
`((1 2) (3) (4)))
Then when I exchange it (first and third element), it will look like:
`(3 2 1)
`(3 2 1 4)
`((4) (3) (1 2))
Please note: I may only use things such as cons, first, and rest for this.
Here's my current try:
(define new-list
(lambda(list)
(first (rest (rest list))))) ; Get third element.
I cannot replicate the results above. I would like to be shown how it's done.
Just play with it a little:
> '(one)
'(one)
> '(one two three)
'(one two three)
> (first '(one two three four))
'one
> (rest '(one two three four))
'(two three four)
> (define foo (lambda (lst)
(cons (first lst) (rest lst))))
> (foo '(one two three four))
'(one two three four)
> (define bar (lambda (lst)
(cons (first (rest lst))
(cons (first lst) (rest lst)))))
> (bar '(one two three four))
'(two one two three four)
Now you have everything to complete the process.
To write your procedure, we want to take an input list xs, and construct a new list like
(cons (third-element xs)
(cons (second-element xs)
(cons (first-element xs)
(everything-except-the-first-three-elements xs)))
In racket you have car and cdr, but you also have cadr, caddr, cddddr and everything in betweeen.
To get an intuition for them, a reads the head, d reads the tail, so
car gets the head (the first element in a list)
cdr gets the tail (everything except the first element in a list)
cadr gets the head of the tail (the second element in a list)
cddr gets the tail of the tail (everything except the first and second elements in a list)
caddr gets the head of the tail of the tail (the third element in a list)
and so on ...
We can write this easily using our car and cdr helpers
(define (swap xs)
(cons (caddr xs) ; cons the third element ...
(cons (cadr xs) ; onto the second element ...
(cons (car xs) ; onto the first element ...
(cdddr xs))))) ; onto the tail of the third element
(swap '(1 2 3)) ; '(3 2 1)
(swap '(1 2 3 4)) ; '(3 2 1 4)
(swap '((1 2) (3) (4))) ; '((4) (3) (1 2))
(define nth
;; Return nth element of list
(lambda (lst n)
(cond ((null? lst) 'nil)
((zero? n) (car lst))
(else (nth (cdr lst) (- n 1))))))
(define slice
;; Return lst sliced like python
(lambda (lst a b acc)
(cond ((null? lst) (reverse acc))
((< b a) (reverse acc))
((zero? b) (reverse acc))
((zero? a) (slice (cdr lst) 0 (- b 1) (cons (car lst) acc)))
(else (slice (cdr lst) (- a 1) (- b 1) acc)))))
(define swap
;; Return nth and mth element swapped list
(lambda (lst n m)
`(,#(slice lst 0 n '())
,(nth lst m)
,#(slice lst (+ n 1) m '())
,(nth lst n)
,#(slice lst (+ m 1) (length lst) '()))))
This swaps any two given positions m and n and returns the resulting list.
(swap your-list 0 2) ; returns your-list 1st and 3rd elements swapped
I am quite new with Scheme and with StackOverflow as well!
So, for the first contact I would like to do something simple and easy in Scheme.
I want to define a function that substracts the elements of the introduced list.
For example, the inputs should be: (sub '(4 12 6) '(0 6 3))
And the output should be: (4 6 3)
Thanks!!
What you'll need is to have a base case where you check if either list is empty and evaluate it to the empty list or you make a pair with the calculation of the first element of each list and the recursion for the rest of both lists. Basically you end up with:
(cons (- 4 0) (cons (- 12 6) (cons (- 6 3) '()))) ; ==> (4 6 3)
As an example of a recursive list processing function here is one that negates all elements:
(define (negate-list lst)
(if (null? lst)
'()
(cons (- (car lst))
(negate-list (cdr lst)))))
(negate-list '(1 2 3 4)) ; ==> (-1 -2 -3 -4)
Now there are even more fancy ways to do this. Eg,. you can use tail recursion:
(define (negate-list lst)
(let loop ((lst lst) (acc '()))
(if (null? lst)
(reverse acc)
(loop (cdr lst)
(cons (- (car lst)) acc)))))
You can use map:
(define (negate-list lst)
(map - lst))
So there you go. you're half way there.
I want to duplicate every found element in a list. I have the idea but i can't make it right. Sample input is >(pass '(1 2 3 4 4)) will have the output (1 1 2 2 3 3 4 4 4 4). Anyone out there help me. Here is my code ..
(define duplicate
(lambda (mylist n)
(cond ((null? mylist) "Not found")
((< n 2) (cons (car mylist)
(duplicate mylist (+ n 1))))
(else
(duplicate (cdr mylist) 0)))))
(define pass
(lambda (mylist)
(duplicate list 0)))
I will appreaciate all valuable comments.
Just a couple of fixes (see the comments) and we're good to go:
(define duplicate
(lambda (mylist n)
(cond ((null? mylist) '()) ; base case must return the empty list
((< n 2) (cons (car mylist)
(duplicate mylist (+ n 1))))
(else
(duplicate (cdr mylist) 0)))))
(define pass
(lambda (mylist)
(duplicate mylist 0))) ; pass myList, not list
Notice that the procedure can be simplified a bit:
(define (pass lst)
(if (null? lst)
'()
(cons (car lst)
(cons (car lst)
(pass (cdr lst))))))
Or even better, using higher-order procedures for a more idiomatic solution:
(define (pass lst)
(foldr (lambda (ele acc) (list* ele ele acc))
'()
lst))
Yet another alternative:
(define (pass lst)
(append-map (lambda (ele) (list ele ele))
lst))
Anyway, it works as expected:
(pass '(1 2 3 4 4))
=> (1 1 2 2 3 3 4 4 4 4)
I would do it so:
(define (dup l)
(define (iter l co)
(if (null? l)
(co '())
(iter (cdr l)
(lambda (x)
(co (cons (car l) (cons (car l) x)))))))
(iter l (lambda (x) x)))
(dup '(1 2 3))
It may be simpler to treat duplicate as zipping a list with itself. Then flattening the resulting list.
In Scheme or Racket:
(require srfi/1)
(define (duplicate-list-members lox)
(flatten (zip lox lox)))
Though it runs in O(n) time, profiling may indicate that passing through the list twice is a bottleneck and justify rewriting the function. Or it might not.
Try using map and list
(define (duplicate my-list)
(flatten
(map
(lambda (x)
(list x x))
my-list)))`
Gives requested format:
> (duplicate (list 1 2 3 4 4))
'(1 1 2 2 3 3 4 4 4 4)
I'm attempting to make a procedure named median that takes the median value of a list. If the list is even, then I will return the two middle numbers. I have the logic all thought out in my head, but I'm not sure how to complete it. NOTE: I am trying to avoid using list-ref, as it would trivialize the problem.
So far, my code looks like the following.
(define (median lst)
(if (null? lst)
'()
(if (even? lst) ; ends here
Now, my approach to the problem is this.
Odd #- Return the value of the "car#" that's in place of (/ (+ (length lst) 1) 2)
3; 2nd car (1 100 3) => 100
5; 3rd car (1 2 100 4 5) => 100
7; 4th car (1 2 3 100 5 6 7) => 100
Even # - Return the value of the "car#" that's in place of (/ (length lst) 2) AND (+ (/ (length lst) 2) 1)
2; 1st and 2nd car (1 2) => 1 2
4; 2nd and 3rd car (1 20 30 4) => 20 30
However, I cant seem to come up with a way that could recursively implement this pseudocode.
EDIT: Not sure if anyone is still out there willing to help, but I ended up writing an iterative procedure that will take the median index value for any odd list. My trouble now is implementing something that will make the code work for an even list, and also something that doesn't return the value in a list:
(define (median-index-odd lst)
(define (median-index-iter1 lst times_carred)
(if (null? lst)
'()
(if (= times_carred (/ (+ (length lst) 1) 2))
(list (car lst))
(median-index-iter1 (cdr lst) (+ 1 times_carred)))))
(median-index-iter1 lst 0))
I've also came up with a seperate procedure for finding the median index when the list is even:
(define (median-index-even lst)
(define (median-index-iter2 lst times_carred)
(if (null? lst)
'()
(if (= times_carred (/ (length lst) 2))
(list (car lst) (cadr lst))
(median-index-iter2 (cdr lst) (+ 1 times_carred)))))
(median-index-iter2 lst 0))
Seems like homework.
The straightforward solution includes list-sort (rnrs / sorting) unless it's already sorted, length to get the list length, list-tail to get the list from half and car for odd, and an additional cadr for the even list. You use let to do something with intermediate values.
Edit in some code even if you get it right or not. For the latter we can help you more.
(define (median L)
(if (null? L)
(error "No median of empty list")
(let loop ((L1 L) (L2 L))
(cond ((null? (cdr L2)) (car L1))
((null? (cddr L2)) (list (car L1) (cadr L1)))
(else (loop (cdr L1) (cddr L2))))))
split into two lists take the first one at a time, the second two at a time
I'm new to scheme and am having some trouble debugging my code.
; returns number of elements in a list
(define (length L)
(cond ((null? L) 0)
(else (+ (length (cdr L)) 1))))
; split the list in half:
; returns ((first half)(second half))
(define (split L)
(cond
((= (length L) 0) (list L L) )
((= (length L) 1) (list L '() ))
(else
(list (sublist L 1 (/ (length L) 2) 1)
(sublist L (+ (/ (length L) 2) 1) (length L) 1)))))
; extract elements start to end into a list
(define (sublist L start end counter)
(cond ((null? L) L)
((< counter start) (sublist (cdr L) start end (+ counter 1)))
((> counter end) '())
(else (cons (car L) (sublist (cdr L) start end (+ counter 1))))))
To me, this feels like it would split a single list into two sub lists. There may be an easier way to do this, and so I apologize if this seems cumbersome.
Anyway, the results:
Expected: (split '(1 2 3 4 5)) = ('(1 2) '(3 4 5))
Actual: (split '(1 2 3 4 5)) = ('(1 2) '(4 5))
It's clear that the length or split is losing the middle value, but I've checked it again and again and it seems to lose the middle value. It seems like an easy solution would be to get rid of the (+ 1) of (+ (/ (length L) 2) 1) but this seems counter intuitive to me, as:
Assume L = '(1 2 3 4 5), (/ (length L) 2) = 2, and (+ (/ (length L) 2) 1) = 3
(sublist L 1 (2) 1) = '(1 2)
(sublist L (3) 5 1) = '(3 4 5)
** I put parens around the 2 and 3 to indicate that they were length calculations.
Clearly an assumption I am making is false, or I am overlooking something trivial.
Thanks in advance!
Do you know the tortoise-and-hare algorithm? The tortoise walks the list, the hare runs the list at double speed. The split occurs at the position of the tortoise when the hare reaches the end of the list. Here's most of the code; I'll let you figure out the rest:
(define (split xs)
(let loop ((ts xs) (hs xs) (zs (list)))
(if (or (null? hs) (null? (cdr hs)))
(values (reverse zs) ts)
(loop ...))))
Here ts is the remaining list of items to be examined by the tortoise, hs is the remaining list of items to be examined by the hare, and zs is the list of items already examined by the tortoise, in reverse order.
Note that you never need to count the items in the input list.
I'm not going to debug your code for you. Instead, here's a simpler definition of split:
(define (split l)
(let ((n (length l)))
(list (take (/ n 2) l)
(drop (+ (/ n 2) (mod n 2)) l))))
Exercise for the reader: implement take and drop. The latter is just recursion on n while taking the cdr of l in the recursive case; the former takes slightly more effort to get right in the base case (stopping condition).
Here is almost your solution (Racket Scheme):
#lang racket
(define (length lst)
(cond [(empty? lst) 0]
[else (+ (length (rest lst)) 1)]))
(define (first-length lst)
(quotient (length lst) 2))
(define (second-length lst)
(- (length lst) (first-length lst)))
(define (sublist lst start end counter)
(cond [(empty? lst) lst]
[(< counter start) (sublist (rest lst) start end (+ counter 1))]
[(> counter end) '()]
[else (cons (first lst) (sublist (rest lst) start end (+ counter 1)))]))
(define (first-half-of-list lst)
(sublist lst 1 (first-length lst) 1))
(define (second-half-of-list lst)
(sublist lst (second-length lst) (length lst) 1))
(define (split lst)
(cond
[(= (length lst) 0) (list lst lst)]
[(= (length lst) 1) (list lst '())]
[else (list (first-half-of-list lst)
(second-half-of-list lst))]))
(split '(1 2 3 4 5))
=> '((1 2) (3 4 5))
Thank you for good brain exercise.
The key moment is 'second-length'-function.