Taking groups of elements randomly in scheme - functional-programming

How do I implement a program in Scheme taking the elements of a given list and returning a new list where the elements are random gatherings of the previous list? I would like it to work for any length. For example:
Input: '(a e i o u), output: '((a e) (i o) (u)) for length 2.
My attempts (making use of for/list) are being clumsy and based on recursion. I have divided the tasks as suggested by Óscar:
Select n elements randomly from a list l:
(define (pick-n-random l n)
(take (shuffle l) n))
Remove a list l2 from a list l1:
(define (cut l1 l2)
(cond ((null? l1)
'())
((not (member (car l1) l2))
(cons (car l1) (cut (cdr l1) l2)))
(else
(cut (cdr l1) l2))))
Then, and that is my problem: how do I recurse over this process to get the intended program? Should I use for/list to paste all sublists got by this process 1. and 2.?

It's easier if we split the problem into chunks. First, let's write a couple of procedures that will allow us to take or drop n elements from a list, with appropriate results if there are not enough elements left in the list (if not for this, we could have used the built-in take and drop):
(define (take-up-to lst n)
(if (or (<= n 0) (null? lst))
'()
(cons (car lst) (take-up-to (cdr lst) (sub1 n)))))
(define (drop-up-to lst n)
(if (or (<= n 0) (null? lst))
lst
(drop-up-to (cdr lst) (sub1 n))))
With the above two procedures in place, it's easy to create another procedure to group the elements in a list into n-sized sublists:
(define (group lst n)
(if (null? lst)
'()
(cons (take-up-to lst n)
(group (drop-up-to lst n) n))))
Finally, we combine our grouping procedure with shuffle, which randomizes the contents of the list:
(define (random-groups lst n)
(group (shuffle lst) n))
It works as expected:
(random-groups '(a e i o u) 2)
=> '((e a) (u i) (o))

Related

creating a lisp function that gives a list of even number from a list

I would like to create a function for class that would take two arguments L and L1 as lists and put all even numbers from L into L1.
I've tried for several hours to make it work, but unfortunatelly I couldn't.
This is my Scheme code:
(define (pair L L1)
(cond
((and (not (empty? L)) (= (modulo (first L) 2) 0))
(begin (append (list (first L)) L1) (pair (rest L) L1)))
((and (not (empty? L)) (= (modulo (first L) 2) 1))
(pair (rest L) L1))
(else L1)
))
I assume you want to use L1 as an accumulator, and at the end return its content.
About your code:
It's enough to check once in the first clause of cond if L is empty (null?).
append is fine when you want to append a list. In your case you append one element, so cons is much better.
You don't have to take modulo of a number, to check if it's even. There is build in even? predicate.
So, after all this considerations, your code should look something like this:
(define (pair L L1)
(cond ((null? L) L1)
((even? (first L))
(pair (rest L) (cons (first L) L1)))
(else (pair (rest L) L1))))
Now let's test it:
> (pair '(0 1 2 3 4 5 6 7) '())
(6 4 2 0)
As you can see, it returns numbers in reverse order. It's because as we move down the list L from head to tail, we cons new values to the head (and not tail, like append would) of the list L1. To fix it, it's enough to (reverse L1) in the first cond clause instead of simply returning L1.
I highly recommend "Little Schemer" book. After reading it, you will be able to write any kind of recursive functions even in your sleep ;)

Scheme - Recursive cases

I'm finishing up a Scheme assignment and I'm having some trouble with the recursive cases for two functions.
The first function is a running-sums function which takes in a list and returns a list of the running sums i.e (summer '(1 2 3)) ---> (1 3 6) Now I believe I'm very close but can't quite figure out how to fix my case. Currently I have
(define (summer L)
(cond ((null? L) '())
((null? (cdr L)) '())
(else (cons (car L) (+ (car L) (cadr L))))))
I know I need to recursively call summer, but I'm confused on how to put the recursive call in there.
Secondly, I'm writing a function which counts the occurrences of an element in a list. This function works fine through using a helper function but it creates duplicate pairs.
(define (counts L)
(cond ((null? L) '())
(else (cons (cons (car L) (countEle L (car L))) (counts (cdr L))))))
(define (countEle L x)
(if (null? L) 0
(if (eq? x (car L)) (+ 1 (countEle (cdr L) x)) (countEle (cdr L) x))))
The expected output is:
(counts '(a b c c b b)) --> '((a 1) (b 3) ( c 2))
But it's currently returning '((a . 1) (b . 3) (c . 2) (c . 1) (b . 2) (b . 1)). So it's close; I'm just not sure how to handle checking if I've already counted the element.
Any help is appreciated, thank you!
To have a running sum, you need in some way to keep track of the last sum. So some procedure should have two arguments: the rest of the list to sum (which may be the whole list) and the sum so far.
(define (running-sum L)
(define (rs l s)
...)
(rs L 0))
For the second procedure you want to do something like
(define (count-elems L)
(define (remove-elem e L) ...)
(define (count-single e L) ...)
(if (null? L)
'()
(let ((this-element (car L)))
(cons (list this-element (count-single this-element L))
(count-elems (remove-elem this-element (cdr L)))))))
Be sure to remove the elements you've counted before continuing! I think you can fill in the rest.
To your first problem:
The mistake in your procedure is, that there is no recursive call of "summer". Have a look at the last line.
(else (cons (car L) (+ (car L) (cadr L))))))
Here is the complete solution:
(define (summer LL)
(define (loop sum LL)
(if (null? LL)
'()
(cons (+ sum (car LL)) (loop (+ sum (car ll)) (cdr LL)))))
(loop 0 LL))

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.

Sum of values in a list squared in Scheme

I'm trying to have the following program work, but for some reason it keeps telling me that my input doesnt contain the correct amount of arguments, why? here is the program
(define (sum f lst)
(cond
((null? lst)
0)
((pair? (car lst))
(+(f(sum (f car lst))) (f(sum (f cdr lst)))))
(else
(+ (f(car lst)) (f(sum (f cdr lst)))))))
and here is my input: (sum (lambda (x) (* x x)) '(1 2 3))
Thanks!
btw I take no credit for the code, Im just having fun with this one (http://groups.engin.umd.umich.edu/CIS/course.des/cis400/scheme/listsum.htm)
You're indeed passing the wrong number of arguments to the procedures sum and f, notice that the expressions (sum (f car lst)), (sum (f cdr lst)) are wrong, surely you meant (sum f (car lst)), (sum f (cdr lst)) - you don't want to apply f (a single-parameter procedure) to the two parameters that you're passing, and sum expects two arguments, but only one is passed. Try this instead:
(define (sum f lst)
(cond ((null? lst)
0)
((pair? (car lst))
(+ (sum f (car lst)) (sum f (cdr lst))))
(else
(+ (f (car lst)) (sum f (cdr lst))))))
More important: you're calling the f procedure in the wrong places. Only one call is needed in the last line, for the case when (car lst) is just a number and not a list - in the other places, both (car lst) and (cdr lst) are lists that need to be traversed; simply pass f around as a parameter taking care of correctly advancing the recursion.
Let's try the corrected procedure with a more interesting input - as it is, the procedure is capable of finding the sum of a list of arbitrarily nested lists:
(sum (lambda (x) (* x x)) '(1 (2) (3 (4)) 5))
> 55
You should take a look at either The Little Schemer or How to Design Programs, both books will teach you how to structure the solution for this kind of recursive problems over lists of lists.

Resources