Adding Elements In a List Scheme - 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.

Related

Matrix Manipulation in Racket

I need to write a function that produces the nth column of a matrix in Racket without using recursion. For example (list (list 1 2 3) (list 2 3 4) (list 6 7 9)) if I wanted the 2nd column I would receive (list 2 3 7).
I tried (append (map (lambda (n) (list-ref (list-ref M) n) n)) M)), but it keeps showing me an error.
The attempted solution uses list-ref twice, which is not needed, and one of those calls does not have enough arguments: (list-ref M) has the function taking only one argument, but it requires two arguments -- a list and an integer.
The list-ref function will return an indexed element from an input list, so (list-ref '(1 2 3) 1) will return 2. Consider what map will do here: the matrix is represented as a list of lists (a list of rows), i.e., as ((1 2 3) (2 3 4) (6 7 9)). The map function will act on the members of the input list, which are the lists (1 2 3), (2 3 4), and (6 7 9). By mapping the list-ref function over that input, you can take whichever element you want from the sublists. So, (map (lambda (row) (list-ref row 1)) '((1 2 3) (2 3 4) (6 7 9))) would evaluate to (2 3 7), as desired.
Here is a function that lets you take any column from a matrix:
(define (nth-column M n)
(map (lambda (row) (list-ref row n)) M))
Sample interactions:
scratch.rkt> (define M '((1 2 3)
(2 3 4)
(6 7 9)))
scratch.rkt> (nth-column M 1)
'(2 3 7)
scratch.rkt> (nth-column M 0)
'(1 2 6)
scratch.rkt> (nth-column M 2)
'(3 4 9)

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))

Counting adjacent duplicates in scheme and prolog

I am new to scheme and prolog and have done only a few basic problems.
I need to write a function in scheme and prolog for counting adjacent recurrences in a list.
Example: (Count '(1, 1, 1, 2, 3, 3, 1)) gives ((3 1) (1 2) (2 3) (1 1))
I do not want the code as this is homework but any hints or how to think about this problem would be appreciated as I don't know where to start.
Let's look at a hypothetical function loop:
(loop todo done)
that rewrites the list in todo to you wanted format
and done contains the part already handled.
(loop '(1 1 1 2 3 3 1) '())
(loop '(1 1 2 3 3 1) '((1 1))
(loop '(1 2 3 3 1) '((1 2))
(loop '(2 3 3 1) '((1 3))
(loop '(3 3 1) '((2 1) (1 3))
(loop '(3 1) '((3 1) (2 1) (1 3))
(loop '(1) '((3 2) (2 1) (1 3))
(loop '() '((1 1) (3 2) (2 1) (1 3))
'((1 1) (3 2) (2 1) (1 3)
Given such a function loop you can write
(define (count xs)
(reverse loop xs '())
Now in order to implement loop you need to consider these cases:
1) todo is empty
2) done is empty
3) the first element of todo is different from the first element of done
3) the first element of todo is the same as the first element of done

What is the difference between map and apply in scheme?

I am trying to learn Scheme and I am having a hard time understanding the difference between map and apply.
As I understand, map applies the function to each element of the list, and apply applies something to the arguments of a procedure.
Can they be used interchangeably?
They are not the same! Their names can actually help remember which does what.
map will take as argument one procedure and one or more lists.
The procedure will be called once for each position of the lists, using as arguments the list of elements at that position:
(map - '(2 3 4))
; => (-2 -3 -4)
map called (- 2), (- 3), (- 4) to build the list.
(map + '( 1 2 3)
'(10 20 30))
; => (11 22 33)
map called (+ 1 10) (+ 2 20) (+ 3 30) to build the list.
(map * '(2 2 -1)
'(0 3 4)
'(5 4 2))
; => (0 24 -8)
map called (* 2 0 5) (* 2 3 4) (* -1 4 2) to build the list.
map has that name because it implements a "map" (function) on a set of values (in the lists):
(map - '(2 3 4))
arguments mapping "-" result
2 === (- 2) ===> -2
3 === (- 3) ===> -3
4 === (- 4) ===> -4
(map + '( 1 2 3)
'(10 20 30))
arguments mapping "+" result
1 10 === (+ 1 10) ===> 11
2 20 === (+ 2 20) ===> 22
3 30 === (+ 3 30) ===> 33
apply will take at least two arguments, the first of them being a procedure and the last a list. It will call the procedure with the following arguments, including those inside the list:
(apply + '(2 3 4))
; => 9
This is the same as (+ 2 3 4)
(apply display '("Hello, world!"))
; does not return a value, but prints "Hello, world!"
This is the same as (display "Hello, world!").
apply is useful when you have arguments as a list,
(define arguments '(10 50 100))
(apply + arguments)
If you try to rewrite the last line without using apply, you'll realize that you need to loop over the list summing each element...
apply may also be used with more than those two arguments. The first argument must be a callable object (a procedure or a continuation). The last one must be a list. The others (between the first and the last) are objects of any type. So calling
(apply PROC a b c ... y z '(one two ... twenty))
is the same as calling
(PROC a b c ... y z one two ... twenty)
Here's a concrete example:
(apply + 1 -2 3 '(10 20))
; => 32
This is the same as (+ 1 -2 3 10 20)
apply has that name because it allows you to "apply" a procedure to several arguments.
No, apply calls its first argument as a procedure, with all the rest as its arguments, with the last one -- list -- opened up, i.e. its contents "spliced in":
(apply f a b (list c d e)) == (f a b c d e)
E.g.:
(apply + 1 2 (list 3 4 5))
;Value: 15
It is just one call; whereas map is indeed calling its first argument for each member element of its second argument.
One combined use of map and apply is the famous transpose trick:
(apply map list '((1 2 3) (10 20 30)))
;Value: ((1 10) (2 20) (3 30))
As the top answer suggested, map
The procedure will be called once for each position of the lists, using as arguments the list of elements at that position
In contrast, apply
(apply function argument-list)
pass arguments in argument-list to function all at once. So function is called only once.

count elements from within a nested list in 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)

Resources