Functional version of deleting nth element in a list in Racket - scheme

I want to get a list which has nth version deleted from the original list. I could manage following code which is imperative:
(define (list-removeN slist n)
(define outl '())
(for ((i (length slist)))
(when (not (= i n))
(set! outl (cons (list-ref slist i) outl))))
(reverse outl))
What can be the functional equivalent of this? I tried for/list, but I have to insert #f or at that position, removing which is not ideal because #f or may occur at other positions in list also.

You can do it recursively with an accumulator. Something like
#lang racket
(define (remove-nth lst n)
(let loop ([i 0] [lst lst])
(cond [(= i n) (rest lst)]
[else (cons (first lst) (loop (add1 i) (rest lst)))])))
(remove-nth (list 0 1 2 3 4 5) 3)
(remove-nth (list 0 1 2 3) 3)
(remove-nth (list 0 1 2) 0)
This produces
'(0 1 2 4 5)
'(0 1 2)
'(1 2)
You could do it with for/list but this version traverses the list twice because of the length call.
(define (remove-nth lst n)
(for/list ([i (length lst)]
[elem lst]
#:when (not (= i n)))
elem))
There's also split-at, but again this may not be as optimal as it creates two lists and appends them.
(define (remove-nth lst n)
(let-values ([(left right) (split-at lst n)])
(append left (rest right))))

A typical roll your own implementation that is recursive and uses O(n) time and O(n) space.
(define (remove-nth lst i)
(let aux ((lst lst) (i i))
(cond ((null? lst) '()) ;; what if (< (length lst) i)
((<= i 0) (cdr lst)) ;; what if (< i 0)
(else (cons (car lst)
(aux (cdr lst) (sub1 i)))))))
A interative version that uses append-reverse from srfi-1. O(n) time and O(1) space.
(define (remove-nth lst i)
(let aux ((lst lst) (i i) (acc '()))
(cond ((null? lst) (reverse acc)) ;; what if (< (length lst) i)
((<= i 0) (append-reverse acc (cdr lst))) ;; what if (< i 0)
(else (aux (cdr lst) (sub1 i) (cons (car lst) acc))))))

Related

How to write a function that computes the maximum and minimum of a list of integers using Scheme

I am new to scheme. I am trying to find max and min of a list using scheme. Using "loop" I was able get the answer. Now I am trying different way to implement the same thing. I made some changes and for some reason I can't find what I am doing wrong.
;non working version
(define (min-max list1)
(let (ls list1) (max (car list1)) (min(car list1))
(cond
((null? ls)
(list "max: " max "min: " min))
((> (car ls) max)
(let ((car ls) max))
(min-max (cdr ls)))
((< (car ls) min)
(let ((car ls) min))
(min-max (cdr ls)))
(else
(min-max (cdr ls))))))
(define list1(list 1 2 3 4 ))
(display list1)
(newline)
(min-max list1)
;working version
(define (min list1)
(let loop((ls list1) (max (car list1)) (min(car list1)))
(cond
((null? ls)
(list "max: " max "min: " min))
((> (car ls) max)
(loop (cdr ls)(car ls) min))
((< (car ls) min)
(loop (cdr ls) max (car ls) ))
(else
(loop (cdr ls) max min)))))
(define list1(list 1 2 3 4 ))
(display list1)
(newline)
(min list1)
This isn't Code Review but I'll start with the "working" version of your procedure first. As is stands that procedure doesn't work for empty lists, so you should add a test for that. Then, no need to re-compare the first element of the list to min and max. Then, you seem to think that loop is a keyword, so I've changed the name to helper. Finally, I've modified it to be less repetitive:
(define (min-max lst)
(if (null? lst)
'()
(let helper ((lst (cdr lst)) (min (car lst)) (max (car lst)))
(if (null? lst)
(list min max)
(let ((c (car lst)))
(helper (cdr lst)
(if (< c min) c min)
(if (> c max) c max)))))))
which is the same as
(define (min-max lst)
(define (helper lst min max)
(if (null? lst)
(list min max)
(let ((c (car lst)))
(helper (cdr lst)
(if (< c min) c min)
(if (> c max) c max)))))
(if (null? lst)
'()
(helper (cdr lst) (car lst) (car lst))))
Testing:
> (min-max '(1 2 3 4))
'(1 4)
> (min-max '(1 8 2 3 4))
'(1 8)
> (min-max '())
'()
Your first procedure doesn't work because at each recursive call you re-initialize min and max. Also, since there is no test for the empty list, inevitably you end up taking the car of the empty list, which is not allowed in Scheme. Finally, it looks like you want to change the value of min and max outside the recursive call, which means you have to use set!. Here's a working version of that:
(define (min-max lst)
(if (null? lst)
'()
(let ((min (car lst)) (max (car lst)))
(define (helper lst)
(if (null? lst)
(list min max)
(let ((c (car lst)))
(when (< c min) (set! min c))
(when (> c max) (set! max c))
(helper (cdr lst)))))
(helper lst))))
This yields the same results, but you can see how much less elegant the code looks with set! as compared to the recursive call to helper.

List order after duplicate filtering

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)

Bubble Sorting with Scheme

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))))))

How to sort disorder list of numbers in scheme

What it the proper way to sort a list with values in Scheme? For example I have the values which are not ordered:
x1, x5, x32 .... xn
or
3, 4, 1, 3, 4, .. 9
First I want to for them by increase number and display them in this order:
x1, xn, x2, xn-1
or
1, 6, 2, 5, 3, 4
Any help will be valuable.
This is the same question you posted before, but with a small twist. As I told you in the comments of my answer, you just have to sort the list before rearranging it. Here's a Racket solution:
(define (interleave l1 l2)
(cond ((empty? l1) l2)
((empty? l2) l1)
(else (cons (first l1)
(interleave l2 (rest l1))))))
(define (zippy lst)
(let-values (((head tail) (split-at
(sort lst <) ; this is the new part
(quotient (length lst) 2))))
(interleave head (reverse tail))))
It works as expected:
(zippy '(4 2 6 3 5 1))
=> '(1 6 2 5 3 4)
This R6RS solution does what Chris Jester-Young proposes and it really is how to do it the bad way. BTW Chris' and Óscar's solutions on the same question without sorting is superior to this zippy procedure.
#!r6rs
(import (rnrs base)
(rnrs sorting)) ; list-sort
(define (zippy lis)
(let loop ((count-down (- (length lis) 1))
(count-up 0))
(cond ((> count-up count-down) '())
((= count-up count-down) (cons (list-ref lis count-down) '()))
(else (cons (list-ref lis count-down)
(cons (list-ref lis count-up)
(loop (- count-down 1)
(+ count-up 1))))))))
(define (sort-rearrange lis)
(zippy (list-sort < lis)))
Here is a simple, tail-recursive approach that uses a 'slow/fast' technique to stop the recursion when half the list is traversed:
(define (interleave l)
(let ((l (list-sort < l)))
(let merging ((slow l) (fast l) (revl (reverse l)) (rslt '()))
(cond ((null? fast)
(reverse rslt))
((null? (cdr fast))
(reverse (cons (car slow) rslt)))
(else
(merging (cdr slow) (cddr fast) (cdr revl)
(cons (car revl) (cons (car slow) rslt))))))))
So, you don't mind slow and just want a selection-based approach, eh? Here we go....
First, we define a select1 function that gets the minimum (or maximum) element, followed by all the other elements. For linked lists, this is probably the simplest approach, easier than trying to implement (say) quickselect.
(define (select1 lst cmp?)
(let loop ((seen '())
(rest lst)
(ext #f)
(extseen '()))
(cond ((null? rest)
(cons (car ext) (append-reverse (cdr extseen) (cdr ext))))
((or (not ext) (cmp? (car rest) (car ext)))
(let ((newseen (cons (car rest) seen)))
(loop newseen (cdr rest) rest newseen)))
(else
(loop (cons (car rest) seen) (cdr rest) ext extseen)))))
Now actually do the interweaving:
(define (zippy lst)
(let recur ((lst lst)
(left? #t))
(if (null? lst)
'()
(let ((selected (select1 lst (if left? < >))))
(cons (car selected) (recur (cdr selected) (not left?)))))))
This approach is O(n²), whereas the sort-and-interleave approach recommended by everybody else here is O(n log n).

Scheme: All Possible Shifts from Front of List to Back

I need to write a Scheme function that takes a list as an argument and returns a list of lists where every list is a cycle of the original list.
By a cycle, I mean shifting the first element to the last position.
I have the following functions:
(define (cycle lst)
(cond ((null? lst) '())
((null? (cdr lst)) lst)
(else (append (cdr lst) (list (car lst))))))
(define (shift lst)
(define (iter l cycles result)
(cond ((= cycles 0) (cons lst result))
((< cycles 1) result)
(else (iter (cycle-1 l) (- cycles 1) (cons result (cycle-1 l))))))
(iter lst (- (length lst) 1) '()))
Now, when I do:
(shift '(1 2 3))
I get:
'((1 2 3) (() 2 3 1) 3 1 2)
I should get:
'((1 2 3) (2 3 1) (3 1 2))
(define (shift lst)
(define (iter l cycles result)
(cond ((= cycles 0)
(cons lst result))
((< cycles 0) result)
(else (let ((cycled (cycle l)))
(iter cycled (- cycles 1) (cons cycled result))))))
(iter lst (- (length lst) 1) '()))
First, I've made a simple improvement to prevent calculate cycled form of the list twice(added let). Second, you need to cons cycled to result since you need to append result list, not cycled list. In your code, you're adding last result to old results and then passing this wrongly appended results list to iter functions as result parameter.
Update: To get the results in your order you can simple just append result with cycled list, instead of adding cycled list to head of the result:
(define (shift lst)
(define (iter l cycles result)
(cond ((= cycles 0)
(cons lst result))
((< cycles 0) result)
(else (let ((cycled (cycle l)))
(iter cycled (- cycles 1) (append result (list cycled)))))))
(iter lst (- (length lst) 1) '()))

Resources