Can you write an all-equal? function all-equal? in the following way:
(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:
(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: if the list length is 0, our operator is indefinite, otherwise we fix the first element of the list length (in the 'else' part of the if -clause), put it in the closure defined by let syntactic sugar (actually lambda), and use it to define the function length-equal-to-first? .
Unfortunately, reduce not lazy. We would really like to avoid calculating list lengths if we find that only one is not equal. Thus, to be more effective, 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) ) )))
Please note that all-match? already efficiently defined for you using the MIT scheme (list-search-positive list pred) or (for-all? list pred) or in Racket as andmap
Why write so long?
You are forced to write base case because your acronym does not have a canonical element, since it relies on the first element, and list manipulation in most languages is not very effective. You would have the same problem 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 easier to write in any language, because it reduces this problem by ignoring basic cases.
first method:
if len(listOfLists)<2: return True else: return reduce(lambda a,b: a==b, listOfLists)