Scheme rotation function - functional-programming

I am trying to write a function in Scheme that returns all rotations of a given list. For example, (rotate '(a b c d e)) should return ((a b c d e) (b c d e a) (c d e a b) (d e a b c) (e a b c d)) (in some order).
I am not sure this would work:
(define (make-rotate alphabet) (lambda (x) (+ x alphabet)))
(define (same-arg-twice fn) (lambda (arg) (fn arg arg)))
(define (flip fn) (lambda (a b c d e) (fn b c d e a) (fn c d a e b) (fn d e a b c) (fn e a b c d)
(define (flip fn)
(lambda (3 9 5 8 2 4 7) (fn 9 4 3 2 4 7 8) (fn 3 2 4)

Start with a function that rotates a list once.
That is, it takes the list's first element and puts it at the back instead.
(define (rotate-once ls)
(append (cdr ls) (list (car ls))))
Test:
> (rotate-once '(a b c))
'(b c a)
Looks good.
Now we can use this on an already rotated list to produce the next rotation.
> (rotate-once (rotate-once '(a b c)))
'(c a b)
We could almost write this recursive procedure
(define (rotate ls)
(if (...)
'()
(cons ls (rotate (rotate-once ls)))))
but there is no useful condition for terminating the recursion.
We could depend on the length of the list, but I did this instead: make a helper function and pass it the list of elements that haven't been moved around yet.
When that list is empty, we're done.
(define (rotate-helper ls remaining)
(if (null? remaining)
'()
(cons ls (rotate-helper (rotate-once ls) (cdr remaining)))))
and now we can define
(define (rotate ls) (rotate-helper ls ls))
and
> (rotate '(a b c d e))
'((a b c d e) (b c d e a) (c d e a b) (d e a b c) (e a b c d))

(define (rotate lst)
(for/list ((_ lst))
(let ((tmp lst))
(set! lst (append (cdr lst) (list (car lst))))
tmp)))
> (rotate '(a b c d e))
'((a b c d e) (b c d e a) (c d e a b) (d e a b c) (e a b c d))
or:
(define (one-rotate lst)
(append (cdr lst) (list (car lst))))
(define (rotate lst)
(for/list ((_ lst))
(let ((tmp lst))
(set! lst (one-rotate lst))
tmp)))

Related

Function that returns the union(in alphabetic order) of two sets in Lisp

The procedure below takes two lists and returns their union as an ordered list.
(defun stable-union (lst1 lst2)
(cond ((null lst1) lst2)
((null lst2) lst1)
((and (null lst1) (null lst2)) nil)
(t
(let ((el1 (car lst1))
(el2 (car lst2)))
(cond ((string= el1 el2)
(cons el1
(stable-union (cdr lst1) (cdr lst2))))
((string< el1 el2)
(cons el1
(stable-union (cdr lst1) lst2)))
(t
(cons el2
(stable-union lst1 (cdr lst2)))))))))
It works for some examples and fails for others. For example:
STABLE-UNION: (STABLE-UNION '(A B C) '(B A D)) failed:
Expected (A B C D) but saw (A B A C D)
STABLE-UNION: (STABLE-UNION '(A B C) '(A D B E)) failed:
Expected (A B C D E) but saw (A B C D B E)
STABLE-UNION: (STABLE-UNION '(C B A) '(A E B D)) failed:
Expected (C B A E D) but saw (A C B A E B D)
Can you guide me as to where I am making mistakes in my code? Thank you so much.
The above function works only for lists that are composed by symbols already lexicographically ordered. So, for instance, it works correctly for '(A B C) '(A B D), but not for '(A B C) '(B A D).
There are several ways of correcting it. The simplest one is to call it by sorting (with stable-sort) the two arguments, for instance:
(defun stable-union-general (lst1 lst2)
(stable-union (stable-sort lst1 #'string<) (stable-sort lst2 #'string<)))
(stable-union-general '(A B C) '(B A D))
(A B C D)
Another, less efficient, way is to change the algorithm by taking into account unordered lists.
Finally note that the third branch of the outer conditional is never statisfied: ((and (null lst1) (null lst2)) nil)
This is because, in this case, the first branch is true and the function returns nil.

How to look for an element in a list of lists in racket

I'm trying to find an element in a list of lists and print the lists that contain that element.
For the test: (search-table '((1 2 3) (4 2) (3 3 4) (5 3 2 1)) 1), the output is:
'((1 2 3) (5 3 2 1))
This is my code in DrRacket so far:
(define (search-table table item)
(if(equal? table null)
'()
(cons(search-table first table item))(search-table rest table item)))
But this code is giving me an error message which says:
if: bad syntax;
has 4 parts after keyword in: (if (equal? table null) (quote ()) (cons (search-table first table item)) (search-table rest table item))
Please help me with this as I am very new to Racket.
If the value is a member of the list, cons the list onto the result
(define (search-table lists value)
(cond ((null? lists) '())
((member value (car lists))
(cons (car lists) (search-table (cdr lists) value)))
(else (search-table (cdr lists) value))))
(search-table '((a b c d) (b c) (c d e f) (a b c)) 'a)
;; '((a b c d) (a b c))
You tagged this with tail-recursion tho, so let's do it with constant space
(define (search-table lists value)
(let loop ((lists lists) (acc null))
(cond ((null? lists) acc)
((member value (car lists))
(loop (cdr lists) (cons (car lists) acc)))
(else (loop (cdr lists) acc)))))
(search-table '((a b c d) (b c) (c d e f) (a b c)) 'a)
;; '((a b c) (a b c d))
But that result is in reverse order; according to your question anyway – we can "fix" that using a continuation as our accumulator instead of a list
(define (search-table lists value)
(let loop ((lists lists) (acc identity))
(cond ((null? lists)
(acc null))
((member value (car lists))
(loop (cdr lists) (lambda (rest)
(acc (cons (car lists) rest)))))
(else
(loop (cdr lists) acc)))))
(search-table '((a b c d) (b c) (c d e f) (a b c)) 'a)
;; '((a b c d) (a b c))
You tagged this with functional-programming tho, so let's do it using higher order functions
(define (search-table lists value)
(filter (lambda (list) (member value list))
lists))
(search-table '((a b c d) (b c) (c d e f) (a b c)) 'a)
;; '((a b c d) (a b c))

Lisp recursion for split-list

(defun split-list (L)
(if (endp L)
'(nil nil)
(let ((x (split-list (cdr L))))
(list (cons (car L) (cadr x))(car X))
)))
This is the code which I have. It works fine:
(split-list '(1 2 3 4 5 6))
((1 3 5) (2 4 6))
But I need an explanation on the recursion part.
When we call the function (split-list (cdr L)) I am sure that it goes from 123456 to 23456. (car L) is 1
and (cadr X) is 3 but how did 5 came there ?
when function did
(split-list (cdr L)) didn't the x became 3456 and (cadr x) should be 4 ? which is wrong and same with other half. (car x) should be 3 now which is wrong.
Could anyone please explain ?
I would rewrite a recursive split-list as this:
(defun split-list (list)
(if (endp list)
(values nil nil)
(multiple-value-bind (split1 split2)
(split-list (rest list))
(values (cons (first list) split2)
split1))))
Above uses multiple values. The function returns the split result as two values. We also replace car with first and cdr with rest. The are just better names, but have the same functionality. multiple-value-bind binds the the two values of the recursive split-list call to the variables split1 and split2. The function values returns its two arguments as two values.
In the example below, you can see that the function indeed returns two values:
CL-USER 20 > (split-list '(a b c d e f))
(A C E)
(B D F)
You can trace its execution:
CL-USER 21 > (trace split-list)
(SPLIT-LIST)
CL-USER 22 > (split-list '(a b c d e f))
0 SPLIT-LIST > ((A B C D E F))
1 SPLIT-LIST > ((B C D E F))
2 SPLIT-LIST > ((C D E F))
3 SPLIT-LIST > ((D E F))
4 SPLIT-LIST > ((E F))
5 SPLIT-LIST > ((F))
6 SPLIT-LIST > (NIL)
6 SPLIT-LIST < (NIL NIL)
5 SPLIT-LIST < ((F) NIL)
4 SPLIT-LIST < ((E) (F))
3 SPLIT-LIST < ((D F) (E))
2 SPLIT-LIST < ((C E) (D F))
1 SPLIT-LIST < ((B D F) (C E))
0 SPLIT-LIST < ((A C E) (B D F))
(A C E)
(B D F)

Group the elements of a set into disjoint subsets using iteration instead of recursion

I came across Pascal Bourguignon's solutions of the 99 Lisp problems and was wondering if his recursive solution of problem 27 using a nested mapcan-mapcar-construct could also be written using nested loops.
His solution is definitely very elegant:
(defun group (set sizes)
(cond
((endp sizes)
(error "Not enough sizes given."))
((endp (rest sizes))
(if (= (first sizes) (length set))
(list (list set))
(error "Cardinal mismatch |set| = ~A ; required ~A"
(length set) (first sizes))))
(t
(mapcan (lambda (combi)
(mapcar (lambda (group) (cons combi group))
(group (set-difference set combi) (rest sizes))))
(combinations (first sizes) set)))))
The function combinations is defined here as:
(defun combinations (count list)
(cond
((zerop count) '(())) ; one combination of zero element.
((endp list) '()) ; no combination from no element.
(t (nconc (mapcar (let ((item (first list)))
(lambda (combi) (cons item combi)))
(combinations (1- count) (rest list)))
(combinations count (rest list))))))
I started with a simple approach:
(defun group-iter (set sizes)
(loop :with size = (first sizes)
:for subgroup :in (combination size set)
:for remaining = (set-difference set subgroup)
:collect (list subgroup remaining) :into result
:finally (return result)))
which results in:
> (group-iter '(a b c d e f) '(2 2 2))
(((A B) (F E D C)) ((A C) (F E D B)) ((A D) (F E C B)) ((A E) (F D C B))
((A F) (E D C B)) ((B C) (F E D A)) ((B D) (F E C A)) ((B E) (F D C A))
((B F) (E D C A)) ((C D) (F E B A)) ((C E) (F D B A)) ((C F) (E D B A))
((D E) (F C B A)) ((D F) (E C B A)) ((E F) (D C B A)))
But now I am totally failing to implement the nesting which takes care of the further processing of remaining. As far as I understood there is always a way to express a recursion with a iteration but how does it look like here?

Scheme - binary tree iteration recursion appends () as an empty Node instead of nothing

I'm trying to write a simple code which returns a list of the tree nodes values in a "pre-order" way.
(define pre-iter (lambda (tree)
(if (not (pair? tree))
(list tree)
(append (list (car tree)) (pre-iter (cadr tree)) (pre-iter (caddr tree)))
)))
I can't find out why the following happens:
(iter-tree (quote (F (B A (D C E)) (G () (I H ())))) pre-iter): expected '(F B A D C E G I H), got '(F B A D C E G () I H ())
Thank for your help.
You just have to handle an extra case when a subtree is null. Try this:
(define pre-iter
(lambda (tree)
(cond ((null? tree) '())
((not (pair? tree)) (list tree))
(else
(append (list (car tree))
(pre-iter (cadr tree))
(pre-iter (caddr tree)))))))
It works as requested:
(pre-iter '(F (B A (D C E)) (G () (I H ()))))
=> '(F B A D C E G I H)

Resources