count elements from within a nested list in scheme - scheme

I am trying to count elements from within a nested list in scheme, and rank them in order of frequency. For example I have a listP which looks like this '((1 3 6)(1 4 7)(1 5 8)(2 5 7)) and I want scheme to tell me that the order of frequency of the elements is (1 5 7 2 3 4 6 8). Actually I just need the three most frequent, so (1 5 7).
I can't find a function that will find the most frequent element, then get the next most frequent, etc. I have tried max, min, map, length and count but couldn't get anything working at all.
I hope someone can point me in the direction of the function I need. I'm happy to play around with the code once I know what function/s I can use, but this has me beat right now. Thanks!

This looks like a job for #ChrisJester-Young's bagify. Here's one possible solution, tested in Racket and using Chris' third implementation of bagify:
(define (frequency lst)
(map car
(sort (hash->list (bagify (append* lst)))
(lambda (x y) (> (cdr x) (cdr y))))))
(frequency '((1 3 6) (1 4 7) (1 5 8) (2 5 7)))
=> '(1 5 7 2 3 4 6 8)

Related

How to represent the following data structure in scheme r5rs

In Python the data structure looks like this: [([1 2 3], [8 9 10])] (a list of tuple, where tuple is of size 2, and each tuple element is a list again)
How would I represent the same in Scheme r5rs?
This is what I tried: (list (cons `(1 2 3) `(8 9 10)))
But running (display (list (cons `(1 2 3) `(8 9 10)))) gives (((1 2 3) 8 9 10)) whereas I want (((1 2 3) (8 9 10)))
Edit
Using only lists (as per #Will Ness answer here):
(list ; a pair of elements,
(list 1 2 3) ; 1 each is itself
(list 8 9 10))) ; 2 a list
works.
And I can access the 2nd element of the tuple by
(cadr (car x)) which gives (8 9 10) (which is correct)
I was just thinking how would I build this up using cons since my tuple will only contain 2 elements and from what I know cons are used to represent a pair in Scheme. Any ideas on how to do this using cons?
[([1 2 3], [8 9 10])] (a list of tuple, where tuple is of size 2, and each tuple element is a list again)
(list ; a list of
(list ; a pair of elements,
(list 1 2 3) ; 1 each is itself
(list 8 9 10))) ; 2 a list
Scheme is untyped, so we can just use lists for tuples. It is simpler that way -- the access is uniform. The first is car, the second cadr.
Your way is correct as well. What really determines whether it is or not is how you can access your data to retrieve its constituents back. And with your way you can indeed, too: the first element will be car and the second -- cdr.
(update to the question edit:) whether you use (cons 1 (cons 2 '())) or (list 1 2) is immaterial. the resulting structure in memory is the same.
There is an infinity of ways to represent data. You have been presented a way. Here is other way:
(define mk/data
(lambda (a b)
(lambda (?)
(cond ((eq? ? 'repr) (list (list a b)))
((eq? ? 'first) a)
((eq? ? 'second) b)))))
(define data/test (mk/data '(1 2 3) '(8 9 10)))
(data/test 'repr)
(data/test 'first)
(data/test 'second)
This is another way how the big systems actually represent data.

Replace list into list of list

How can I build a function that receives a list and builds 2 lists that on the first one are all the even numbers and on the other one are all the odd numbers?
For the input: (fun '(1 2 3 4 5 6))
the output will be: ((2 4 6) (1 3 5)).
There's a built-in for that, simply use partition and provide the right predicate. The rest of the code is just for capturing the returned values and building the output list:
(define (my-partition lst)
(let-values ([(evens odds) (partition even? lst)])
(list evens odds)))
For example:
(my-partition '(1 2 3 4 5 6))
=> '((2 4 6) (1 3 5))

Adding Elements In a List Scheme

In Scheme, I am trying to iterate through a list adding each element from a portion of the list.
For example, if I had ((1 2 5) (1 2) (1 5) (1) (2 5) (2) (5) ()) for a list, I am trying to add the first part ( 1 2 5 ) and then the second part ( 1 2 ) and so on in order to see if each element adds up to a specific number.
Hope this makes sense, tried my best to explain this.
If someone could help me figure this problem out, I would really appreciate it.
To add the numbers of a (small) list you can use apply:
> (apply + '(1 2 3))
6
which is the same as
> (+ 1 2 3)
6
In order to apply this to a list of sublists, use map:
(define (f lst)
(map (lambda (sublst) (apply + sublst))
lst))
> (f '((1 2 5) (1 2) (1 5) (1) (2 5) (2) (5) ()))
'(8 3 6 1 7 2 5 0)
For larger list you might want to replace apply by foldl or equivalent.

Comparing items in a list? scheme

If you have a list ( (1 4 5) 5 (6 2 5) ), and another list (5 1 3 7 5 (9 2 4) ), I need to write a procedure that compares items from the first list and sees if they're in the second. For example, (1 4 5) appears 0 times in (5 1 3 7 5 (9 2 3) ). 5 appears in this list 2 times, and (9 2 4) appears 0 times. So the list will return (0 2 0)
I need help writing a scheme procedure frequency that takes in two lists, the first being the one that has each component compared, and the second being the one that counts the number of occurrences of the first list. The procedure should return a list of the occurrences.
So far I've been told to make two procedures, one that counts the occurrences (counter) for each item and the other that keeps track of it in a list (frequency). I've done this so far:
(define (counter ele lst)
`(cond ((null? lst) `
'())
`((equal? ele lst)`
`(+ 1 (counter ele (cdr lst))))`
`(else`
`(counter ele (cdr lst)))))`
(define (frequency els lst)
`(if (null? els)`
`'()`
`(cons <???>`
`(frequency <???> lst))))`
I'm not sure what to do with the frequency procedure, and how to call the counter procedure from it
Thanks!
For something like this you are going to have to use something like pair? becuase you working with trees which are lists of lists.
For example the car of (list (list 1 2) 3 4) is going to be the list 1 2. So that means if you try to compare values you will get an error. You need to isolate the leaves (the individual numbers) from the pairs to be able to compare.

Scheme quadruples sorting different criteria [duplicate]

This question already has an answer here:
Closed 11 years ago.
Possible Duplicate:
scheme sort list diffent criteria
I have a finite list of quadruples, like
(list (list 1 3 5 5) (list 2 3 4 9) (list 3 4 4 6)(list 4 7 10 3)).
Each of the elements is denoted by (a1 a2 a3 a4).
I have wrote a code which provides the above list and I have stopped
since I have no idea how to continue. I want to write a sorting function
which provides a "increasing" list created according to the following
criteria:
the numbers a2,
later the difference (a3 - a4),
and later the numbers a3.
I kindly ask for your help. Thank you. Debbie.
I can not include my code since it is not accepted in this place.
I wrote a predicate that seems to do what you want. You can plug it into this mergesort to work.
(define <quad
(lambda (l1 l2)
(let
([l1a2 (cadr l1)]
[l1a3 (caddr l1)]
[l1a3 (cadddr l1)]
[l2a2 (cadr l2)]
[l2a3 (caddr l2)]
[l2a3 (cadddr l2)])
(cond
[(< l1a2 l2a2) #t]
[(< (- l1a3 l1a4) (- l2a3 l2a4)) #t]
[(< l1a3 l2a3) #t]))))
If you pass that in for the predicate argument, your sort should work fine:
(merge-sort <quad '((2 3 4 5) (1 2 3 4))) => ((1 2 3 4) (2 3 4 5))

Resources