How to duplicate a list in scheme? - scheme

the following code removes duplicate in a list which I got from abo-abo's answer in this question.
(define (remove-duplicates l)
(cond ((null? l)
'())
((member (car l) (cdr l))
(remove-duplicates (cdr l)))
(else
(cons (car l) (remove-duplicates (cdr l))))))
I am just starting learning scheme, how can I duplicate each item in the list for example (5 6 7 8 9 9 10 11 11) will become (5 5 6 6 7 7 8 8 9 9 9 9 10 10 11 11 11 11)?

Explicit recursion with appendand list, and foldr version just with cons:
(define (dup lst)
(if (empty? lst)
'()
(append (list (car lst) (car lst))
(dup (cdr lst)))))
(define (dup2 lst)
(foldr (λ (x xs) (cons x (cons x xs)))
'()
lst))

if you have a list l you can do the following to have a duplicate of the first item at the beginning of a resulting list,
(cons (car l) l)
or equivalently
(cons (car l) (cons (car l) (cdr l)))
This results in the following solution:
(define (duplicate l)
(cond ((null? l)
'())
(else
(cons (car l) (cons (car l) (duplicate (cdr l)))))))

Related

Create palindrom function without append function in output in scheme

i am trying to create palyndrom function which is doing palyndrom from input string. Something like this: (palindrome '(1 2 3 4)) ==> (1 2 3 4 3 2 1).
I have created this code below but it is returning me (palindrome '(1 2 3 4)) ==> (1 (2 (3 (4) 3) 2) 1)
My code is below. Task is to NOT use append or reverse.
(define (palindrome l)
(cond
((null? (cdr l)) (list (car l)))
((list (car l) (palindrome (cdr l)) (car l)))))
Thanks for help.
As in the comment of Sylwester, you can do your own version of append or reverse. Here is an example in which only the append function (called concatenate) is defined.
(define (palindrome l)
(define (concatenate l1 l2)
(if (null? l1)
l2
(cons (car l1) (concatenate (cdr l1) l2))))
(define (p l)
(cond ((null? l) '())
((null? (cdr l)) l)
(else (cons (car l) (concatenate (p (cdr l)) (list (car l)))))))
(p l))
(palindrome '(1 2 3 4))
'(1 2 3 4 3 2 1)
Here instead is a tail recursive version:
(define (palindrome l)
(define (concatenate l1 l2)
(if (null? l1)
l2
(cons (car l1) (concatenate (cdr l1) l2))))
(define (p l prefix suffix)
(cond ((null? l) (concatenate prefix suffix))
((null? (cdr l)) (concatenate prefix (cons (car l) suffix)))
(else (p (cdr l) (concatenate prefix (list (car l))) (cons (car l) suffix)))))
(p l '() '()))

Rotating a list to the right in scheme

if this is rotating a list to the left:
(define (rotate-left l)
(if (null? l)
'()
(append (cdr l) (cons(car l) '()))))
How would I rotate a list to the right?
If you're ok with writing a helper function to find the last element, it's pretty easy to do a recursive implementation:
(define rotate-right
(lambda (lis full)
(if (null? (cdr lis))
(cons (car lis) (get-all-but-last full))
(rotate-right (cdr lis) full))))
(define get-all-but-last
(lambda (lis)
(if (null? (cdr lis))
'()
(cons (car lis) (get-all-but-last (cdr lis))))))
Here is a short non-recursive solution:
(define (rotate-right l)
(let ((rev (reverse l)))
(cons (car rev) (reverse (cdr rev)))))
And here is a iterative solution:
(define (rotate-right l)
(let iter ((remain l)
(output '()))
(if (null? (cdr remain))
(cons (car remain) (reverse output))
(iter (cdr remain) (cons (car remain) output)))))
(rotate-right '(1 2 3 4 5)) ;==> (5 1 2 3 4)

Scheme: Searching element in a list and sublist

I want to write a function that receives list and returns a list of each element.
For example:
get - (x 3 4 5 (x 4) 3 x (6))) and receive: (x (x) x ())
(define (lookForX lst)
(cond
((null? lst) '())
((eq? (car lst) 'x) (cons (car lst) (lookForX (cdr lst))) )
(else (lookForX (cdr lst)))))
my code result for:
(lookForX '(x 3 4 5 (x 4) 3 x (6)))
-> (x x)
What am I doing wrong?
In you function you are only looking for x as element in the list and you are not doing sub lists:
(define (filter-x lst)
(cond
((null? lst) '())
((eq? (car lst) 'x)
(cons (car lst)
(filter-x (cdr lst))))
((pair? (car lst))
(cons (filter-x (car lst))
(filter-x (cdr lst))))
(else (filter-x (cdr lst)))))
(filter-x '(x 3 4 5 (x 4) 3 x (6)))
; ==> (x (x) x ())
Notice I renamed this to be more lisp like. Lisp code usually don't use camelCase but lisp-case. You can do it more general:
(define (filter-tree predicate? lst)
(cond
((null? lst) '())
((predicate? (car lst))
(cons (car lst)
(filter-tree predicate? (cdr lst))))
((pair? (car lst))
(cons (filter-tree predicate? (car lst))
(filter-tree predicate? (cdr lst))))
(else (filter-tree predicate? (cdr lst)))))
(define (filter-tree-x lst)
(filter-tree (lambda (v) (eq? v 'x)) lst))
(filter-tree-x '(x 3 4 5 (x 4) 3 x (6)))
; ==> (x (x) x ())
(define (filter-tree-numbers lst)
(filter-tree number? lst))
(filter-tree-numbers '(x 3 4 5 (x 4) 3 x (6)))
; ==> (3 4 5 (4) 3 (6))

Show last appearance of element in list

I want to show the last appearance of an element from a given list. For example: For the list '(1 1 2 1 3 3 4 3 5 6), the result will be '(2 1 4 3 5 6)
This is the code I have:
(define (func L res)
(if (not (null? L))
(foldl (lambda (e)
(if (not (member e (cdr L)))
(cons e (remove-duplicates-right (cdr L)))
(remove-duplicates-right (cdr L))))
res L)
res))
(define (show-last-app L)
(func L '()))
The next error occurs: "foldl: given procedure does not accept 2 arguments"
This is how I solved it only with recursion but I want to use only foldl or filter and don't use functions with side effects:
(define (show-last-app L)
(cond
((null? L)
'())
((not (member (car L) (cdr L)))
(append (list (car L)) (show-last-app (cdr L))))
(else (show-last-app (cdr L)))))
I think you misunderstand how folds work in Scheme. This is closer to what you were aiming for:
(define (show-last-app L)
(foldr (lambda (e acc)
(if (not (member e acc))
(cons e acc)
acc))
'()
L))
If you really, really have to use foldl:
(define (show-last-app L)
(foldl (lambda (e acc)
(if (not (member e acc))
(cons e acc)
acc))
'()
(reverse L)))
Either way, it works as expected:
(show-last-app '(1 2 4 1 5 3 1 6 2))
=> (4 5 3 1 6 2)

Removing Duplicates from a list as well as the elements themselves- Racket, Scheme

(define (remove-duplicates l)
(cond ((empty? l)
'())
((member (first l) (rest l))
(remove-duplicates (rest l)))
(else
(cons (first l) (remove-duplicates (rest l))))))
This code has this result.
> (remove-duplicates (list 1 1 2 2 3 4))
(list 1 2 3 4)
Without using filter, I would like the result to be
(remove-duplicates (list 1 1 2 2 3 4)) gives
(list 3 4)
Help would be deeply appreciated. Thanks in advance.
You could use a helper function:
(define helper
(lambda (lst collector dup)
(cond [(null? lst) collector]
[(memq (car lst) (cdr lst)) (helper (cdr lst) collector (cons (car lst) dup))]
[(memq (car lst) dup) (helper (cdr lst) collector dup)]
[else
(helper (cdr lst) (cons (car lst) collector) dup)])))
Maintain two lst, collector for all unique element, and dup for duplicated elements.
(define remove-dup
(lambda (lst)
(reverse (helper lst '() '()))))

Resources