List length in scheme - scheme

Hi I am trying to write a program where given a list of lists check to see if they are equal in size and return #t if they are.
So for example if i were to write (list-counter? '((1 2 3) (4 5 6) (7 8 9))) the program would return #t, and (list-counter? '((1 2 3) (4 5 6) (7 8))) would return #f.
SO far this is what I have done:
(define list-counter?
(lambda (x)
(if (list? x)
(if (list?(car x))
(let (l (length (car x))))
(if (equal? l (length(car x))))
(list-counter?(cdr x))
) ) ) ) )
I think where I am going wrong is after I set the length of l to the length of the first list. Any help would be appreciated.

There are several ways to solve this problem. For instance, by hand and going step-by-step:
(define (all-lengths lists)
(if (null? lists)
'()
(cons (length (car lists))
(all-lengths (cdr lists)))))
(define (all-equal? head lengths)
(if (null? lengths)
true
(and (= head (car lengths))
(all-equal? head (cdr lengths)))))
(define (list-counter? lists)
(let ((lengths (all-lengths lists)))
(all-equal? (car lengths) (cdr lengths))))
Let me explain the above procedures. I'm dividing the problem in two steps, first create a new list with the lengths of each sublist - that's what all-lengths does. Then, compare the first element in a list with the rest of the elements, and see if they're all equal - that's what all-equal? does. Finally, list-counter? wraps it all together, calling both of the previous procedures with the right parameters.
Or even simpler (and shorter), by using list procedures (higher-order procedures):
(define (list-counter? lists)
(apply = (map length lists)))
For understanding the second solution, observe that all-lengths and all-equal? represent special cases of more general procedures. When we need to create a new list with the result of applying a procedure to each of the elements of another list, we use map. And when we need to apply a procedure (= in this case) to all of the elements of a list at the same time, we use apply. And that's exactly what the second version of list-counter? is doing.

You could write an all-equal? function like so:
(define (all-equal? list)
;; (all-equal? '()) -> #t
;; (all-equal? '(35)) -> #t
;; (all-equal? '(2 3 2)) -> #f
(if (or (null? list) (null? (cdr list)))
#t
(reduce equal? list)
))
then do:
(all-equal? (map length listOfLists))
Alternatively you can do:
(define (lists-same-size? list-of-lists)
(if (== (length listOfLists) 0)
#t
(let*
(( firstLength
(length (car listOfLists)) )
( length-equal-to-first?
(lambda (x) (== (length x) firstLength)) )
)
(reduce and #t (map length-equal-to-first? listOfLists))
)
)))
What this says is: if the list length is 0, our statement is vacuously true, otherwise we capture the first element of the list's length (in the 'else' part of the if-clause), put it in the closure defined by let's syntactic sugar (actually a lambda), and use that to define an length-equal-to-first? function.
Unfortunately reduce is not lazy. What we'd really like is to avoid calculating lengths of lists if we find that just one is not equal. Thus to be more efficient we could do:
...
(let*
...
( all-match? ;; lazy
(lambda (pred list)
(if (null? list)
#t
(and (pred (first list)) (all-match? (cdr list)))
;;^^^^^^^^^^^^^^^^^^^ stops recursion if this is false
)) )
)
(all-match? length-equal-to-first? listOfLists)
)
)))
Note that all-match? is already effectively defined for you with MIT scheme's (list-search-positive list pred) or (for-all? list pred), or in Racket as andmap.
Why does it take so long to write?
You are forced to write a base-case because your reduction has no canonical element since it relies on the first element, and list manipulation in most languages is not very powerful. You'd even have the same issue in other languages like Python. In case this helps:
second method:
if len(listOfLists)==0:
return True
else:
firstLength = len(listOfLists[0])
return all(len(x)==firstLength for x in listOfLists)
However the first method is much simpler to write in any language, because it skirts this issue by ignoring the base-cases.
first method:
if len(listOfLists)<2:
return True
else:
return reduce(lambda a,b: a==b, listOfLists)

This might sound a bit weird, but I think it is easy.
Run down the list, building a new list containing the length of each (contained) list, i.e. map length.
Run down the constructed list of lengths, comparing the head to the rest, return #t if they are all the same as the head. Return false as soon as it fails to match the head.

Related

Implementing powerset in scheme

I am trying to implement a powerset function in Scheme in two ways.
One way is using tail recursion, and I did it like this:
(define (powerset list)
(if (null? list) '(()) ;; if list is empty, its powerset is a list containing the empty list
(let ((rest (powerset (cdr list)))) ;; define "rest" as the result of the recursion over the rest of list
(append (map (lambda (x) (cons (car list) x)) rest) ;; add the first element of list to the every element of rest (which is a sublist of rest)
rest)))) ;; and append it to rest itself (as we can either use the current element (car list), or not
Which works fine.
Another way is using foldr, and this is where I face some issues.
My current implementation is as follows:
(define (powerset-fr list)
(foldr (lambda (element result) ;; This procedure gets an element (and a result);
(if (null? result) ;; if starting with the empty list, there is nothing to "fold over".
(cons '() (cons element result))
(foldr (lambda (inner-element inner-result)
(append (cons element result) inner-result))
'(())
result)))
'() ;; The result is initialized to the empty list,
list)) ;; and the procedure is being applied for every element in the first list (list1)
Which yields a poor result.
I'll try to explain shortly how did I approach this problem so far:
foldr runs over every element in the given set. For each such element, I should add some new elements to the powerset.
Which elements should these be? One new element for each existing element in the powerset, where is append the current element in list to the existing element in powerset.
This is why I thought I should use foldr twice in a nested way - one to go over all items in given list, and for each item I use foldr to go over all items in "result" (current powerset).
I faced the problem of the empty list (nothing is being added to the powerset), and thus added the "if" section (and not just foldr), but it doesn't work very well either.
I think that's it. I feel close but it is still very challenging, so every help will be welcomed.
Thanks!
The solution is simpler, there's no need to use a double foldr, try this:
(define (powerset-fr lst)
(foldr (lambda (e acc)
(append (map (lambda (x) (cons e x))
acc)
acc))
'(())
lst))
If your interpreter defines append-map or something equivalent, then the solution is a bit shorter - the results will be in a different order, but it doesn't matter:
(define (powerset-fr lst)
(foldr (lambda (e acc)
(append-map (lambda (x) (list x (cons e x)))
acc))
'(())
lst))
Either way, it works as expected:
(powerset-fr '(1 2 3))
=> '((1 2 3) (1 2) (1 3) (1) (2 3) (2) (3) ())

Implementing sublist? using accumulate in Racket

I need to implement sublist? as a one-liner function that uses accumulate.
It is suppose to return true if set1 is in set2.
Something like this:
(define subset?
(lambda (set1 set2)
(accumulate member? (car set1) (lambda (x) x) set2)))
Honestly I think I'm just confused on how accumulate is suppose to work with member, or if member is even the right choice for the operator.
My accumulate function is:
(define accumulate
(lambda (op base func ls)
(if (null? ls)
base
(op (func (car ls))
(accumulate op base func (cdr ls))))))
and member?:
(define member?
(lambda (item ls)
(cond ((null? ls) #f)
((equal? item (car ls)) #t)
(else (member? item (cdr ls))))))
To give the correct definition of subset? first we must understand how the function accumulate works and the meaning of its parameters.
If we “unfold” the recursive definition, we can see that accumulate applies the binary operator op to all the results of applying func to the elements of list ls. And since the list can be empty, in these cases the function is defined to give back the value base.
So, for instance, assuming the recursive execution of the function, the following expression
(accumulate + 0 sqr '(1 2 3))
produces 14, since it is equivalent to:
(+ (sqr 1) (+ (sqr 2) (+ (sqr 3) 0)))
that is 1 + 4 + 9 + 0.
To solve your problem, you have to define a call to accumulate that applies the same operator to a list of elements and then combine the results. In you case, the operation to be applied is a test if an element is member of a list (member?), and you can apply it to all the elements of set1. And you should know, from the definition of the subset, that a set s1 is subset of another set s2 if and only if all the elements of s1 are contained in s2. So the operator that must be applied to combine all the results of the test is just the and boolean operator, so that it will be true if all the elements of s1 are member of s2 and false otherwise. The last thing to decide is the base value: this should be true, since an empty set is always contained in another set.
So this is a possible definition of subset?:
(define (subset? set1 set2)
(accumulate
(lambda (x y) (and x y)) ;; the combination operator
#t ;; the value for the empty list
(lambda(x) (member x set2)) ;; the function to be applied to all the elements of
set1)) ;; the set set1

Mirror in scheme returns nested list w/o helper functions [duplicate]

For my programming languages class I'm supposed to write a function in Scheme to reverse a list without using the pre-made reverse function. So far what I got was
(define (reverseList lst)
(COND
((NULL? lst) '())
(ELSE (CONS (reverseList(CDR lst)) (CAR lst)))
))
The problem I'm having is that if I input a list, lets say (a b c) it gives me (((() . c) . b) . a).
How am I supposed to get a clean list without multiple sets of parenthesis and the .'s?
The problem with your implementation is that cons isn't receiving a list as its second parameter, so the answer you're building isn't a proper list, remember: a proper list is constructed by consing an element with a list, and the last list is empty.
One possible workaround for this is to use a helper function that builds the answer in an accumulator parameter, consing the elements in reverse - incidentally, this solution is tail recursive:
(define (reverse lst)
(reverse-helper lst '()))
(define (reverse-helper lst acc)
(if (null? lst)
acc
(reverse-helper (cdr lst) (cons (car lst) acc))))
(reverse '(1 2 3 4 5))
=> '(5 4 3 2 1)
You are half way there. The order of the elements in your result is correct, only the structure needs fixing.
What you want is to perform this transformation:
(((() . c) . b) . a) ; input
--------------------
(((() . c) . b) . a) () ; trans-
((() . c) . b) (a) ; for-
(() . c) (b a) ; mation
() (c b a) ; steps
--------------------
(c b a) ; result
This is easy to code. The car and cdr of the interim value are immediately available to us. At each step, the next interim-result is constructed by (cons (cdr interim-value) interim-result), and interim-result starts up as an empty list, because this is what we construct here - a list:
(define (transform-rev input)
(let step ( (interim-value input) ; initial set-up of
(interim-result '() ) ) ; the two loop variables
(if (null? interim-value)
interim-result ; return it in the end, or else
(step (car interim-value) ; go on with the next interim value
(cons ; and the next interim result
(... what goes here? ...)
interim-result )))))
interim-result serves as an accumulator. This is what's known as "accumulator technique". step represents a loop's step coded with "named-let" syntax.
So overall reverse is
(define (my-reverse lst)
(transform-rev
(reverseList lst)))
Can you tweak transform-rev so that it is able to accept the original list as an input, and thus skip the reverseList call? You only need to change the data-access parts, i.e. how you get the next interim value, and what you add into the interim result.
(define (my-reverse L)
(fold cons '() L)) ;;left fold
Step through the list and keep appending the car of the list to the recursive call.
(define (reverseList lst)
(COND
((NULL? lst) '())
(ELSE (APPEND (reverseList(CDR lst)) (LIST (CAR lst))))
))
Instead of using cons, try append
(define (reverseList lst)
(if (null? lst)
'()
(append (reverseList (cdr lst)) (list (car lst)) )
)
)
a sample run would be:
1]=> (reverseList '(a b c 1 2 + -))
>>> (- + 2 1 c b a)
car will give you just one symbol but cdr a list
Always make sure that you provide append with two lists.
If you don't give two lists to the cons it will give you dotted pair (a . b) rather than a list.
See Pairs and Lists for more information.

Scheme: a good set function

I need to write a good set function that checks whether its argument lst is a properly represented set, i.e. it is a list consisting only of integers, with no duplicates, and returns true #t or false #f. For example:
(good-set? (1 5 2)) => #t
(good-set? ()) => #t
(good-set? (1 5 5)) => #f
(good-set? (1 (5) 2)) => #f
so I have began writing the function as:
(define (good-set? lst)
so I don't know how to proceed after this. Can anybody help?
One option would be to use andmap and sets, as has been suggested by #soegaard:
(define (good-set? lst) ; it's a good set if:
(and (andmap integer? lst) ; all its elements are integers and
(= (length lst) ; the list's length equals the size
(set-count (list->set lst))))) ; of a set with the same elements
But if you can't use sets or other advanced procedures, then traverse the list and test if the current element is an integer and is not present somewhere else in the list (use member for this), repeating this test for each element until there are no more elements in the list. Here's the general idea, fill-in the blanks:
(define (good-set? lst)
(cond (<???> ; if the list is empty
<???>) ; then it's a good set
((or <???> ; if the 1st element is not an integer or
<???>) ; the 1st element is in the rest of the list
<???>) ; then it's NOT a good set
(else ; otherwise
(good-set? <???>)))) ; advance recursion
Sets are built into the Racket standard library: I would recommend not reimplementing them in terms of lists unless you really need to do something customized.
If we need to treat this as a homework assignment, I would recommend using a design methodology to systematically attack this problem. In this case, see something like How to Design Programs with regards to designing functions that work on lists. As a brief sketch, we'd systematically figure out:
What's the structure of the data I'm working with?
What tests cases do I consider? (including the base case)
What's the overall shape of the function?
What's the meaning of the natural recursion?
How do I combine the result of the natural recursion in order to compute a solution to the total?
For this, check if the first number is duplicated, if it is not, then recurse by checking the rest. As such:
(define (good-set? list)
(or (null? list) ; nothing left, good!
(let ((head (car list)))
(rest (cdr list)))
(and (number? head) ; a number
(not (member = head rest)) ; not in the rest
(good-set? rest))))) ; check the rest
If you need member, then
(define (member pred item list)
(and (not (null? list))
(or (pred item (car list))
(member pred item (cdr list)))))

Find whether element in list integer?

I was wondering, how do you check if every element in a list is an integer or not? I can check the first element by using (integer? (car list), but if I do (integer? (cdr list), it always returns false (#f) because the whole of the last part of the list is not an integer as a group.
In this case let's say list is defined as.
(define list '(1 2 5 4 5 3))
(define get-integers
(lambda (x)
(if (null? x)
"All elements of list are integers"
(if (integer? (car x))
(get-integers (cdr x))
"Not all elements are an integer"))))
Practical Schemes provide functions for doing tests across whole sequences. An application of the andmap function, for example, would be appropriate. Racket provides a for/and to do something similar. If you really needed to write out the loop by hand, you'll be using recursion.
What you need to do is test each element in the list to see if it satisfies a condition (being an integer, in this case). When you evaluate (integer? (car list)) on a list of integers, you're checking if the first element in the list is an integer, and that's fine. But the expression (integer? (cdr list)) tests if a list is an integer (because cdr returns a list), and that won't work - you need to test the next element in the list, and the next, and so on until the list is empty.
There are several ways to do the above, the most straightforward would be to recur on the list testing each element in turn, returning false if a non-integer element was found or true if all the list was consumed without finding a non-integer element, like this:
(define (all-integers? lst)
(cond ((null? lst) #t)
((not (integer? (car lst))) #f)
(else (all-integers? (cdr lst)))))
A more practical approach would be to use a built-in procedure, like this:
(andmap integer? lst)
andmap will check if all the elements in lst evaluate to true for the given predicate. For example:
(andmap integer? '(1 2 3))
> #t
(andmap integer? '(1 "x" 3))
> #f
SRFI-1 uses the terms every and any rather than andmap and ormap. match can also be used:
(define list-of-integers?
(lambda (lst)
(match lst
(((? number?) ..1) #t)
(_ #f))))

Resources