Assume (list "apple" "orange" "apple" "grape" "orange")and produce (list (list 2 "apple") (list 2 "orange") (list 1 "grape")).
The most common fruit will occur first in the produced list.
In the case of ties, order the tied pairs with the fruit in increasing alphabetical order.
use abstract list function such as map,filter, foldr and quicksort in local. no recursion.
i'm not sure how to do it without recursion.
i wrote like this:
(define (function list)
(cond
[(empty? list) empty]
[else
(local
(define (helper1 a b)
(cond
[(equal? a b) a]
[else b]))
(define T (foldr helper1 (first list) (rest list)))
(define (count a)
(cond
[(equal? a T) true]
[else false]))
(define new-list (quicksort (length (filter count list)) >))]
The most efficient way is to use a (mutable) hash table:
(define (count-by-type lst)
; create hash
(define h (make-hash))
; update hash, creating entries if needed, otherwise adding 1 to existing entry
(map (lambda (e) (hash-update! h e add1 0)) lst)
; create list of (count key) elements from hash and sort accordingly
(sort (map (lambda (e) (list (cdr e) (car e))) (hash->list h))
(lambda (x y) (or (> (car x) (car y))
(and (= (car x) (car y)) (string<? (cadr x) (cadr y)))))))
testing:
> (count-by-type (list "apple" "orange" "apple" "grape" "orange"))
'((2 "apple") (2 "orange") (1 "grape"))
I just rehashed my own answer from a previous question. This seems to be a similar assignment, but without struct
Using a hash you could do it with only one pass through the unsorted list, then produced a list that then was sorted with a special <-function that sorts by count, then fruit.
These hints are for a functional solution. First sort the argument (sort list-of-fruits string>?). that the in descending order and oposite of your result. .
Given the list has at least one element:
(let rec ((cur (car sorted-fruits)) (cnt 1) (lst (cdr sorted-fruits)) (acc '()))
(cond ((equal? cur (car lst)) (rec cur (add1 cnt) (cdr lst) acc))
(else (rec (car lst) 1 (cdr lst) (cons (list cnt cur) acc)))))
This will produce a list in ascending order with counts.
If you sort again:
(sort list-of-counts-and-fruit (lambda (x y) (>= (car x) (car y)))
sort in Racket is stable. That means if you have two with equal counts in the list they will end up in their original order. The original order was the ascending animal order so the result is ordered by count descending, then name ascending.
I guess your procedure can be made by chaining these together, perhaps using let to store intermediates to make expressions shorter and more readable.
Related
I'm new to Scheme and I'm trying to write a procedure which combines n list into a list of n-tuples. If the lists are of different size, the tuples should contain the empty list () when the corresponding list ran out of elements.
My current implementation is the following:
(define (comb list1 list2)
(cond [(empty? list1) empty]
[(empty? list2) empty]
[else (cons (list (first list1) (first list2))
(comb (rest list1) (rest list2)))]))
However, this program doesn't produce another tuple when there are no more items in the list to combine. For instance, (comb '(1 2 3 ) '(3 4)) produces only ((1 3) (2 4))
How do I solve it?
This is a bit tricky, and I believe it's not an appropriate exercise for someone who is just learning the basics of the language. Anyway, here's my proposed solution, in terms of higher-order procedures:
; helper procedure for filling a list with arbitrary values at the end
(define (fill lst val num)
(append lst
(build-list num (const val))))
; helper procedure for transposing a list of lists
(define (transpose lsts)
(apply map list lsts))
; main procedure
(define (list-tuples lsts)
(let* ((lengths (map length lsts)) ; obtain the length of each sublist
(max-length (apply max lengths))) ; find out the maximum length
(transpose ; build new sublists element-wise
(map (lambda (lst len) ; build sublists of the right length
(fill lst '() (- max-length len))) ; fill sublists with '()
lsts
lengths))))
The trick was to find the maximum length of the lists and then build new lists with that length, filling them with '() at the end. After that, it's a simple matter of building the answer by taking one element from each sublist. It works as expected:
(list-tuples '((m n o) (1) (x y)))
=> '((m 1 x) (n () y) (o () ()))
You need to specifically deal with the situation where one of the lists is empty. The following does what I think you want with two lists.
(define (comb l1 l2)
(cond
((empty? l1)
(cond
((empty? l2) '())
(else (cons (list '() (car l2)) (comb l1 (cdr l2))))))
(else
(cond
((empty? l2) (cons (list (car l1) '()) (comb (cdr l1) l2)))
(else (cons (list (car l1) (car l2)) (comb (cdr l1) (cdr l2))))))))
Let's split the problem into 2 parts.
First let's assume a procedure that will take a list, and return the following results:
a list containing the first items of each sublist
a list containing the remainder of each sublist
the number of non-empty lists encountered
An example implementation could be:
(define (split-tuples lst)
(let loop ((lst lst) (fst null) (rst null) (cnt 0))
(if (null? lst)
(values (reverse fst) (reverse rst) cnt)
(let ((c (car lst)))
(if (null? c)
(loop (cdr lst) (cons c fst) (cons c rst) cnt)
(loop (cdr lst) (cons (car c) fst) (cons (cdr c) rst) (add1 cnt)))))))
Testing:
> (split-tuples '((m n o) (1) (x y)))
'(m 1 x)
'((n o) () (y))
3
> (split-tuples '((n o) () (y)))
'(n () y)
'((o) () ())
2
> (split-tuples '((o) () ()))
'(o () ())
'(() () ())
1
> (split-tuples '(() () ()))
'(() () ())
'(() () ())
0
Now using this procedure we create the main procedure that will just loop until all sublists are empty:
(define (list-tuples lst)
(let loop ((lst lst) (res null))
(let-values (((fst rst cnt) (split-tuples lst)))
(if (zero? cnt)
(reverse res)
(loop rst (cons fst res))))))
Testing:
> (list-tuples '((m n o) (1) (x y)))
'((m 1 x) (n () y) (o () ()))
> (list-tuples '())
'()
I`m trying to implement a function that given an argument and a list, find that argument in the first element of the pair in a list
Like this:
#lang scheme
(define pairs
(list (cons 1 2) (cons 2 3) (cons 2 4) (cons 3 1) (cons 2 5) (cons 4 4)))
;This try only gets the first element, I need to runs o every pair on pairs
((lambda (lst arg)
(if (equal? (car (first lst)) arg) "DIFF" "EQ"))
pairs 2)
;This try below brings nok for every element, because Its not spliting the pairs
(define (arg) (lambda (x)2))
(map
(lambda (e)
(if (equal? arg (car e)) "ok" "nok"))
pairs)
The idea is simple, I have pair elements, and a given number. I need to see if the first element of the pairs (they are in a list) starts with that number
Thanks in advance
In Racket, this is easy to implement in terms of map. Simply do this:
(define (find-pair lst arg)
(map (lambda (e)
(if (equal? (car e) arg) "ok" "nok"))
lst))
Alternatively, you could do the same "by hand", basically reinventing map. Notice that in Scheme we use explicit recursion to implement looping:
(define (find-pair lst arg)
(cond ((null? lst) '())
((equal? (car (first lst)) arg)
(cons "ok" (find-pair (rest lst) arg)))
(else
(cons "nok" (find-pair (rest lst) arg)))))
Either way, it works as expected:
(find-pair pairs 2)
=> '("nok" "ok" "ok" "nok" "ok" "nok")
(find-pair pairs 7)
=> '("nok" "nok" "nok" "nok" "nok" "nok")
In Scheme, you should usually approach algorithms with a recursive mindset - especially when lists are involved. In your case, if you find the element in the car of the list then you are done; if not, then you've got the same problem on the cdr (rest) of the list. When the list is empty, you've not found the result.
Here is a solution:
(define (find pred list)
(and (not (null? list)) ; no list, #f result
(or (pred (car list)) ; pred on car, #t result
(find pred (cdr list))))) ; otherwise, recurse on cdr
With this your predicate function 'match if car of argument is n' is:
(define (predicate-if-car-is-n n)
(lambda (arg)
(eq? n (car arg))))
The above stretches your understanding; make sure you understand it - it returns a new function that uses n.
With everything together, some examples:
> (find (predicate-if-car-is-n 2) '((1 . 2) (2 . 3) (4 . 5)))
#t
> (find (predicate-if-car-is-n 5) '((1 . 2) (2 . 3) (4 . 5)))
#f
I need to write a function that determines if the given list is a pair of elements. The program will simply respond #t if the list contains exactly two elements or #f if it does not, such that:
(zipper? '((a 1)(b 2))) => #t
and
(zipper? '((foo 100)(bar 2 3))) => #f
I'm still fairly new to Scheme so any help would be much appreciated!
Thanks!
It isn't clear if the "correct" input for the procedure is an arbitrary list or a two-element list. If it's strictly a two-element list, this will work:
(define (is-two-element-list? lst)
(and (list? lst)
(= (length lst) 2)))
(define (zipper? lst)
(and (is-two-element-list? lst)
(is-two-element-list? (first lst))
(is-two-element-list? (second lst))))
… And if it's an arbitrary-length list whose elements we want to check, this will work in Racket, using andmap:
(define (zipper? lst)
(andmap is-two-element-list? lst))
If you are not using Racket, then this solution using every will work in any interpreter with SRFIs:
(require srfi/1)
(define (zipper? lst)
(every is-two-element-list? lst))
Either way, notice that the trick was defining the is-two-element-list? procedure, which verifies the two-element-list property, after that we can apply it as needed.
Think of it this way. If the zipper list is '() then the answer is #t. If the zipper list is not '() then if the first element is two elements and the rest is another zipper?, then return #t.
(define (zipper? list)
(or (null? list)
(and (= 2 (length (car list)))
(zipper? (cdr list)))))
or maybe you mean:
(define (zipper? list)
(or (not (pair? list))
(and (= 2 (length list))
(zipper? (list-ref list 0))
(zipper? (list-ref list 1)))))
every element, at any level, has two elements.
> (zipper? '((a 1 2) '(b)))
#f
> (zipper? '(a b))
#t
> (zipper? '(((a (b b)) c) (1 2)))
#t
im trying to write a function in Scheme where i accept a list and return all the different derangements (look below for definition) as a list of lists
derangement: A list where no item is in the same place as the original list
ex: '(a b c) -> '(cab)
any help is appreciated!
Compute all of the permutations of the input list and then filter out the ones that have an element in the same position as the input list. If you need more detail, leave a comment.
Edit 1:
Define (or maybe it's defined already? Good exercise, anyway) a procedure called filter that takes as its first argument a procedure p and a list l as its second argument. Return a list containing only the values for which (p l) returns a truthy value.
Define a procedure derangement? that tests if a list l1 is a derangement of l2. This will be handy when paired with filter.
The most obvious solution would be something like this:
(define filtered-permutations
(lambda (lst)
(filter
(lambda (permuted-list)
(deranged? permuted-list lst))
(permute lst))))
Since the number of derangements is considerably lower than then number of permutations, however, this is not very efficient. Here is a solution that mostly avoids generating permutations that are not derangements, but does use filter once, for the sake of simplicity:
(define deranged?
(lambda (lst1 lst2)
(if (null? lst1)
#t
(if (eq? (car lst1) (car lst2))
#f
(deranged? (cdr lst1) (cdr lst2))))))
(define derange
(lambda (lst)
(if (< (length lst) 2)
;; a list of zero or one elements can not be deranged
'()
(permute-helper lst lst))))
(define derange-helper
(lambda (lst template)
(if (= 2 (length lst))
(let ((one (car lst))
(two (cadr lst)))
(filter
(lambda (x)
(deranged? x template))
(list (list one two) (list two one))))
(let ((anchor (car template)))
(let loop ((todo lst)
(done '())
(result '()))
(if (null? todo)
result
(let ((item (car todo)))
(if (eq? item anchor)
;; this permutation would not be a derangement
(loop (cdr todo)
(cons item done)
result)
(let ((permutations
(map
(lambda (x)
(cons item x))
(derange-helper (append (cdr todo) done)
(cdr template)))))
(loop (cdr todo)
(cons item done)
(append result permutations)))))))))))
How to reverse a list such that every sublist is also reversed? This is what I have so far:
(defun REV (L)
(cond
((null L) nil)
((listp L)
(append
(REV (cdr L))
(list (car L))))
(t
(append
(REV (cdr L))
(list (car L))))))
You are on the right track, but your last two conditions have the same action, which should give an indication that one of them is not doing what it should. Indeed, the second condition, the listp case, is not right, because when it's a list, you need to append the reverse of that list instead of the unmodified list. A possible solution:
(defun my-reverse (l)
(cond ((null l) nil)
((listp (car l)) (append (my-reverse (cdr l))
(list (my-reverse (car l)))))
(t
(append (my-reverse (cdr l))
(list (car l))))))
> (my-reverse '((1 2 3) (4 5 6)))
((6 5 4) (3 2 1))
As you can see, the only difference is that you test if the first element is a list, and if it is, you reverse the first element before appending it.
I'd write it this way:
(defun reverse-all (list)
(loop
with result = nil
for element in list
if (listp element)
do (push (reverse-all element) result)
else do (push element result)
finally (return result)))
Sounds like a homework problem :)
Looks like you started by writing the regular reverse code. I'll give you a hint: The second condition (listp L) isn't quite right (it'll always be true). You want to be checking if something else is a list.
dmitry_vk's answer (which probably is faster in most lisps than using append in the previous examples) in a more lispish way:
(defun reverse-all (list)
(let ((result nil))
(dolist (element list result)
(if (listp element)
(push (reverse-all element) result)
(push element result)))))
Or even:
(defun reverse-all (list)
(let ((result nil))
(dolist (element list result)
(push
(if (listp element) (reverse-all element) element)
result))))