Replace in a list of lists in scheme - functional-programming

So I have a function that replaces an element of a list with the corespondent element in a list o pairs for example if i have this : (i have a list) and ((have not) (list queue)) it will return (i not a queue)
(define replacecoresp
(lambda (ls a-list)
(map (lambda (x)
(let ((lookup (assq x a-list)))
(if lookup
(cadr lookup)
x)))
ls)))
unfortunately it doesn't work for a list of lists of lists etc what I want is to do this :
if I have a list (i have ( a list) of (list ( list and list ))) and ((list queue) (have not)) the result should be (I not (a queue) of (queue (queue and queue))) I hope you got the idea :) thanks a lot!

Try this:
(define (replacecoresp ls a-list)
(cond ((null? ls) '())
((not (list? ls))
(cond ((assq ls a-list) => cadr)
(else ls)))
(else (cons (replacecoresp (car ls) a-list)
(replacecoresp (cdr ls) a-list)))))
It works as expected:
(replacecoresp '(I have (a list) of (list (list and list)))
'((list queue) (have not)))
> (I not (a queue) of (queue (queue and queue)))
Explanation: When traversing a list of lists (say, ls) you need to consider three cases:
ls is empty, return the empty list
ls is an atom not a list, process the element
ls is a list, invoke the recursion on both the car and the cdr
of the list and combine the results
In the particular case of your question, cons is used in the third step for combining the solution; and the second case is the part where we check to see if the current symbol is in the association list, replacing it if it was found or leaving the symbol untouched if not. I used a shortcut for writing less code in this step, but you can replace the inner cond with this snippet of code if it's clearer:
(let ((lookup (assq ls a-list)))
(if lookup
(cadr lookup)
ls))
Another way to express the solution is to use a map on the list like this:
(define(replacecoresp ls a-list)
(if (not (list? ls))
(cond ((assq ls a-list) => cadr)
(else ls))
(map (lambda (l) (replacecoresp l a-list)) ls)))

Related

Racket: Compare elements in list recursively

This function is supposed to take a list (full of strings or ints, which is why it starts with that 'if' statement) and check to see if it is in ascending order.
I haven't been able to figure out how to keep it from crashing, as on the last recursive call, the 'cadr' has nothing to pull from, as the 'car' is the final element.
(define (my-sorted? lst)
(if (number? (car lst))
(if (< (car lst) (cadr lst))
(my-sorted? (rest lst))
#f)
#f)
)
I know that the sorted function exists, but I need to implement this function recursively.
Thanks for any help.
The two most basic lists that you should try are:
(my-sorted? '()) ; ==> #t (empty list is always sorted)
(my-sorted? '(1)) ; ==> #t (one element list is always sorted)
Your current code just does car and cadr on its argument so it will fail at different levels with these two tests.
The there is how to compare a number and something which is not a number. < expects both arguments to be numbers, but your list can be both strings and numbers. What is smaller of "x" and 7? You cannot do (< 7 "x").
Instead of nesting if you might consider cond which is lisps way of doing if-elseif-else. Basically you can do your code with cond like this:
(cond
((not (number? (car lst))) #f)
((< (car lst) (cadr lst)) (my-sorted? (rest lst))
(else #f))
EDIT
Since the list should either be all elements as string or all as number you simply can just determine the comparison function by looking at the first element and do your recursion with a named let and reuse the one based on the first element.
(define (my-sorted lst)
;; determine what comparison function to use, bind it to greater?
(define greater?
(if (and (pair? lst) (number? (car lst)))
>
string>?))
;; main recursive loop uses that one function
;; this can be done with define + call as well
(let loop ((lst lst))
(cond ((or (null? lst) (null? (cdr lst))) ...)
((greater? (car lst) (cadr lst)) ...)
(else (loop ...)))))

Recursive function to calculate the powerset of a set [duplicate]

I'm using the beginning language with list abbreviations for DrRacket and want to make a powerset recursively but cannot figure out how to do it. I currently have this much
(define
(powerset aL)
(cond
[(empty? aL) (list)]
any help would be good.
What's in a powerset? A set's subsets!
An empty set is any set's subset,
so powerset of empty set's not empty.
Its (only) element it is an empty set:
(define
(powerset aL)
(cond
[(empty? aL) (list empty)]
[else
As for non-empty sets, there is a choice,
for each set's element, whether to be
or not to be included in subset
which is a member of a powerset.
We thus include both choices when combining
first element with smaller powerset,
that, which we get recursively applying
the same procedure to the rest of input:
(combine (first aL)
(powerset (rest aL)))]))
(define
(combine a r) ; `r` for Recursive Result
(cond
[(empty? r) empty] ; nothing to combine `a` with
[else
(cons (cons a (first r)) ; Both add `a` and
(cons (first r) ; don't add, to first subset in `r`
(combine ; and do the same
a ; with
(rest r))))])) ; the rest of `r`
"There are no answers, only choices". Rather,
the choices made, are what the answer's made of.
In Racket,
#lang racket
(define (power-set xs)
(cond
[(empty? xs) (list empty)] ; the empty set has only empty as subset
[(cons? xs) (define x (first xs)) ; a constructed list has a first element
(define ys (rest xs)) ; and a list of the remaining elements
;; There are two types of subsets of xs, thouse that
;; contain x and those without x.
(define with-out-x ; the power sets without x
(power-set ys))
(define with-x ; to get the power sets with x we
(cons-all x with-out-x)) ; we add x to the power sets without x
(append with-out-x with-x)])) ; Now both kind of subsets are returned.
(define (cons-all x xss)
; xss is a list of lists
; cons x onto all the lists in xss
(cond
[(empty? xss) empty]
[(cons? xss) (cons (cons x (first xss)) ; cons x to the first sublist
(cons-all x (rest xss)))])) ; and to the rest of the sublists
To test:
(power-set '(a b c))
Here's yet another implementation, after a couple of tests it appears to be faster than Chris' answer for larger lists. It was tested using standard Racket:
(define (powerset aL)
(if (empty? aL)
'(())
(let ((rst (powerset (rest aL))))
(append (map (lambda (x) (cons (first aL) x))
rst)
rst))))
Here's my implementation of power set (though I only tested it using standard Racket language, not Beginning Student):
(define (powerset lst)
(if (null? lst)
'(())
(append-map (lambda (x)
(list x (cons (car lst) x)))
(powerset (cdr lst)))))
(Thanks to samth for reminding me that flatmap is called append-map in Racket!)
You can just use side effect:
(define res '())
(define
(pow raw leaf)
(cond
[(empty? raw) (set! res (cons leaf res))
res]
[else (pow (cdr raw) leaf)
(pow (cdr raw) (cons (car raw) leaf))]))
(pow '(1 2 3) '())

Scheme/Racket: most idiomatic way to append single element to end of list

I want to append the element b to the list a (let's say (a1, a2, ... an)), e.g. appending the number 3 to (1 2) gives (1 2 3)
So far I've been doing
(append a (list b)), which is kind of long and inelegant, so I wonder if there's a "better" way...
Are you building a list piecemeal, an item at a time? If so, the idiomatic way to do this is to build the list backward, using cons, and then reversing the final result:
(define (map-using-cons-and-reverse f lst)
(let loop ((result '())
(rest lst))
(if (null? rest)
(reverse result)
(loop (cons (f (car rest)) (cdr rest))))))
Alternatively, if your list-building is amenable to a "right-fold" recursive approach, that is also idiomatic:
(define (map-using-recursion f lst)
(let recur ((rest lst))
(if (null? rest)
'()
(cons (f (car rest)) (recur (cdr rest))))))
The above code snippets are just for illustrating the solution approach to take in the general case; for things that are directly implementable using fold, like map, using fold is more idiomatic:
(define (map-using-cons-and-reverse f lst)
(reverse (foldl (lambda (item result)
(cons (f item) result))
'() lst)))
(define (map-using-recursion f lst)
(foldr (lambda (item result)
(cons (f item) result))
'() lst))
How frequent do you have to append to the end?
If you want to do it a lot (more than cons'ing to the front), then you are doing it wrong. The right way is to flip things around: think that cons put things to the back, first retrieves the last element, rest retrieves everything but last, etc. Then, you can use list normally.
However, if you want to put things to the end of the list as frequent as to cons things to the front, then this is the best that you can do with one list. You could write a function to wrap what you consider "inelegant". Traditionally it's called snoc (backward cons)
(define (snoc lst e) (append lst (list e)))
Or if you prefer to implement the whole thing by yourself:
(define (snoc lst e)
(cond
[(empty? lst) (list e)]
[(cons? lst) (cons (first lst) (snoc (rest lst) e))]))
Note that both approaches have the same time complexity: O(n) where n is length of the list.
But if you want it to be efficient, you can use a data structure called double-ended queue, which is very efficient (constant time per operation). See http://www.westpoint.edu/eecs/SiteAssets/SitePages/Faculty%20Publication%20Documents/Okasaki/jfp95queue.pdf for more details.

Recursion through nested lists in LISP

I am trying to find the other element in the nested list when querying the first one. Something like this. (findOther 'a '((a b) (b c) (a d)))--> b and d. I have done this so far: The problem is I only get b.
(defun findOther (elem L)
(cond (NIL (null L))
((eq elem (caar L)) (cdar L))
((findOther elem (cdr L)))))
First some comments on the original code:
(defun findOther (elem L)
(cond
;; NIL is always false, so you *never* end up using this
;; case. You probably want something like ((null l) '()),
;; NULL is still pretty common for this, but since you're
;; expecting a list, you could use the slighly more
;; descriptive ENDP.
(NIL (null L))
;; When you find an element, you immediately return its
;; counterpart, and don't collect it and continue on to
;; the rest of the list. It's also easier to read if
;; you use more descriptive names like FIRST and SECOND,
;; as in ((eq elem (first (first l))) (second (first l))).
;; It's worth noting that unless you have a specific reason
;; to use EQ, you might want to use EQL, which is the
;; default comparison in most CL functions.
((eq elem (caar L)) (cdar L))
;; Else, you continue to the rest of the list. In my
;; opinion, REST would be more decriptive than CDR here,
;; but recursing and returning the value *is* what you
;; want to do here.
((findOther elem (cdr L)))))
Taking some of those into consideration, we could do something like this:
(defun others (element list)
(cond
((endp list) '())
((eql element (first (first list)))
(list* (second (first list))
(others element (rest list))))
((others element (rest list)))))
All that said, the functions in the standard library
would make this much easier. E.g. using mapcan:
(defun others (element list)
(mapcan (lambda (sublist)
(when (eql (first sublist) element)
(rest sublist)))
list))
(others 'a '((a b) (b c) (a d)))
;=> (B D)
I am not sure if you are looking for pair of two elements or may be more elements in list as well. Just in case you have more elements and you want all of them as well and also of some of them are not really pairs,
(defun pair-of (elem lis)
(let ((temp nil))
(cond
((and (listp lis) (not (null lis)))
(mapcar
#'(lambda (x)
(cond
((and (listp x) (not (null x)) (eql elem (car x)))
(push (cdr x) temp))))
lis)))
(nreverse temp)))
USAGE:(pair-of 'a '((a b) (b c) (a d w) 1))
OUTPUT: ((B) (D W))
But in case you want them combined in one list,
(reduce #'append (pair-of 'a '((a s) (a 3 8) (2 5 1))):initial-value '())
=> (S 3 8)

how to write a reduce-per-key function in scheme?

"define a procedure 'reduce-per-key' which a procedure reducef and a list of associations in which each key is paired with a list. The output is a list of the same structure except that each key is now associated with the result of applying reducef to its associated list"
I've already written 'map-per-key' and 'group-by-key' :
(define (map-per-key mapf lls)
(cond
[(null? lls) '()]
[else (append (mapf (car lls))(map-per-key mapf (cdr lls)))]))
(define (addval kv lls)
(cond
[(null? lls) (list (list (car kv)(cdr kv)))]
[(eq? (caar lls) (car kv))
(cons (list (car kv) (cons (cadr kv) (cadar lls)))(cdr lls))]
[else (cons (car lls)(addval kv (cdr lls)))]))
(define (group-by-key lls)
(cond
[(null? lls) '()]
[else (addval (car lls) (group-by-key (cdr lls)))]))
how would I write the next step, 'reduce-per-key' ? I'm also having trouble determining if it calls for two arguments or three.
so far, I've come up with:
(define (reduce-per-key reducef lls)
(let loop ((val (car lls))
(lls (cdr lls)))
(if (null? lls) val
(loop (reducef val (car lls)) (cdr lls)))))
however, with a test case such as:
(reduce-per-key
(lambda (kv) (list (car kv) (length (cadr kv))))
(group-by-key
(map-per-key (lambda (kv) (list kv kv kv)) xs)))
I receive an incorrect argument count, but when I try to write it with three arguments, I also receive this error. Anyone know what I'm doing wrong?
Your solution is a lot more complicated than it needs to be, and has several errors. In fact, the correct answer is simple enough to make unnecessary the definition of new helper procedures. Try working on this skeleton of a solution, just fill-in the blanks:
(define (reduce-per-key reducef lls)
(if (null? lls) ; If the association list is empty, we're done
<???> ; and we can return the empty list.
(cons (cons <???> ; Otherwise, build a new association with the same key
<???>) ; and the result of mapping `reducef` on the key's value
(reduce-per-key <???> <???>)))) ; pass reducef, advance the recursion
Remember that there's a built-in procedure for mapping a function over a list. Test it like this:
(reduce-per-key (lambda (x) (* x x))
'((x 1 2) (y 3) (z 4 5 6)))
> '((x 1 4) (y 9) (z 16 25 36))
Notice that each association is composed of a key (the car part) and a list as its value (the cdr part). For example:
(define an-association '(x 3 6 9))
(car an-association)
> 'x ; the key
(cdr an-association)
> '(3 6 9) ; the value, it's a list
As a final thought, the name reduce-per-key is a bit misleading, map-per-key would be a lot more appropriate as this procedure can be easily expressed using map ... but that's left as an exercise for the reader.
UPDATE:
Now that you've found a solution, I can suggest a more concise alternative using map:
(define (reduce-per-key reducef lls)
(map (lambda (e) (cons (car e) (map reducef (cdr e))))
lls))

Resources