Sum third element of each list in a list - lisp

I currently have a list like:
((map 9 150) (compass 13 35) (water 150 240) (sandwich 50 16) (rope 50 49))
I am trying to loop through this list get the values in bold and give a total of these value. I have been looking at car and cdr but I can't seem to get these values. Is there a simple way to do this?

That would be the third value in the list or the caddr. Thus
(mapcar #'third products) ; ==> (150 35 240 16 49)
If your list is small you can just use apply:
(apply #'+ (mapcar #'third products)) ; ==> 490
For a larger list (more than 1000) I recommend using reduce
(reduce #'+ (mapcar #'third products)) ; ==> 490
With reduce you can use :key to avoid mapcar:
(reduce #'+ products :key #'third) ; ==> 490
You can also use loop:
(loop :for element :in products
:sum (third element)) ; ==> 490

Related

Simplifying a Racket function

I have the following function "change" which takes a certain amount of money to be paid, the size of the bill/coin used to pay, and returns a list with the number of "coins" ($50, $20 $10 $5 $2 and $1) one would receive after completing the transaction:
(define (change total payment)
(let [(x (- payment total))]
(change-aux x '(50 20 10 5 2 1))))
(define (change-aux change coins)
(cond
[(empty? coins) empty]
[else (let [(num-coins (floor (/ change (car coins))))]
(append (list num-coins)
(change-aux (- change (* (car coins) num-coins)) (cdr coins))))]))
So, if I input these parameters:
> (change 44 200)
It returns the output:
'(3 0 0 1 0 1)
That's 200-44 = 156, which corresponds to 3 coins worth $50, 1 worth $5 and 1 worth $1.
My question would be if there's a more elegant, simplified way to write a similar procedure without relying on auxiliary functions, and rather use lambda, filter, map, foldr, foldl etc?
Thanks in advance.
Here is a solution in a different Lisp dialect which shows how to do it with a left fold (reduce) without any mutation of an accumulator variable, as a kind of functional counterpoint to the existing solution.
(defun change (amount coins)
(reduce-left (tb ((counts . rem) next-coin)
(let* ((coin-count (floor rem next-coin))
(coin-value (* coin-count next-coin)))
(cons (cons coin-count counts)
(- rem coin-value))))
coins
(cons '() amount)))
3> (change 156 '(50 20 10 5 2 1))
((1 0 1 0 0 3) . 0)
4> (change 88 '(50 20 10 5 2 1))
((1 1 1 1 1 1) . 0)
Note that the values end up reported in reverse order and wrapped in an extra cons cell; a "porcelain" function could be used around this "plumbing" to report the result in the expected form.
The idea is that we have an accumulator which looks like this: (counts . remainder). The counts part of the accumulator stored in the car is the list of coins accumulated so far. When the reduce is done, this holds the final list. The cdr field holds the remaining amount to be processed; since the last coin is 1, this will always emerge as zero.
Using this accumulator structure, we process the list of coins.
On each call to our reduce kernel function, the left argument is the accumulator, and the right argument, next-coin, is the next coin denomination value.
I used a macro called tb ("tree bind") macro, which is a kind of lambda that provides built-in destructuring, to make it look like we have three parameters.
The initial value for the reduce job is the starting accumulator, which has an empty list of coins, and the full original amount: (cons nil amount) (which I rewrote to (cons '() amount) for better Scheme compatibility).
The reduce function is very simple: greedily calculate how many of the next coin value are needed to represent the remainder, and then calculate the new remainder, packaging these up into a new accumulator cons cell that is returned, and is passed to the next invocation of the function, or returned when the list of coin values has been processed.
Hopefully this points the way to "a more elegant, simplified way to write a similar procedure without relying on auxiliary functions, and rather use lambda, filter, map, foldr, foldl etc" that you can work out in Racket. Good luck!
Sure, you can.
Final solution
(define (change total payment (coins '(50 20 10 5 2 1)))
(let ((rest-diff (- payment total)))
(map (lambda (coin)
(let ((num-coins (floor (/ rest-diff coin))))
(set! rest-diff (- rest-diff (* num-coins coin)))
num-coins))
coins)))
Step by step
First of all, using inner define, you can get rid of the auxiliary function from the global namespace.
(define (change total payment)
(define (change-aux change coins)
(cond
[(empty? coins) empty]
[else (let [(num-coins (floor (/ change (car coins))))]
(append (list num-coins)
(change-aux (- change (* (car coins) num-coins)) (cdr coins))))]))
(let [(x (- payment total))]
(change-aux x '(50 20 10 5 2 1))))
Then, you can pull some variables of the helper function's to the global function's lambda list.
(define (change total payment (coins '(50 20 10 5 2 1)))
(define (change-aux change) ;; eliminate coins in the inner lambda list
(cond
[(empty? coins) empty] ;; coins in function body looked up from outer arguments
[else (let [(num-coins (floor (/ change (car coins))))]
(append (list num-coins)
(change-aux (- change (* (car coins) num-coins)) (cdr coins))))]))
(let [(x (- payment total))]
(change-aux x))) ;; eliminate coins in the call
Then, looking at the code of change-aux, one understands this is actually
a looping through and trying to fit maximal multiples of current value
into the rest of the difference remaining - and collecting those reults. One could loop using map and use set! to mutate the rest.
(define (change total payment (coins '(50 20 10 5 2 1)))
(let ((rest-diff (- payment total)))
(map (lambda (coin)
(let ((num-coins (floor (/ rest-diff coin))))
(set! rest-diff (- rest-diff (* num-coins coin)))
num-coins))
coins)))
Then, you call like above:
(change 44 200)
;; '(3 0 0 1 0 1)

Racket, split a list in two different size lists. And randomly

I would like to code a program that given a list and a percentage, splits the list in two different size lists. It should have random pick of the elements, that way the created lists are always different.
These code is able to do that:
(define (clamp x a b)
(max (min x b) a))
(define (split pct xs)
(define pos (exact-round (* (clamp pct 0.0 1.0) (length xs))))
(split-at (shuffle xs) pos))
Here is an example:
(split 0.25 '(1 2 3 4 5 6 7 8 9))
'(6 2)
'(3 7 1 4 5 8 9)
But, instead of "shuffle" I would like to use this function to achieve the same:
(define (get-randomly-no-pair list)
(list-ref list (random (length list))))
so, get-randomly-no-pair takes one element randomly from the initial list. And all the elements are used to create both lists.
(define (shuffle-list lst)
(define indexes (shuffle (range (length lst))))
(lambda ()
(begin0
(list-ref lst (car indexes))
(set! indexes (cdr indexes)))))
(define gen (shuffle-list (list 10 12 14 16 18 20))
(gen) ; ==> 14 (e.g.)
Now I see you assume you need to pass the list then I would rather make a mapper:
(define (shuffle-accessor len)
(define indexes (list->vector (shuffle (range len))))
(lambda (lst index)
(list-ref lst (vector-ref indexes index))))
(define lst3-ref (shuffle-accessor 3))
(lst3-ref '(1 2 3) 0) ; ==> 3 (e.g.)
(lst3-ref '(6 7 8) 0) ; ==> 8

Racket: how check the size of list?

i need help with racket
(define size1 (lambda (m)
(printf "size is ~v" (length m))))
test it
>(size1 '(2 8 9 0 'uu 98 0))
size is 7
which is fine
,
but second test
> (size1 '((((7) 9 (11)))))
size is 1
it is give me that 1, cuz of the brocket, However
what i want to provide is 3
i need help with that
Note the following:
'((((7) 9 (11)))) ; list with one element --> '(((7) 9 (11)))
'(((7) 9 (11))) ; list with one element --> '((7) 9 (11))
'((7) 9 (11)) ; list with 3 elements --> '(7), 9 and '(11)
If you intended to write a list with three elements, then your list should be '((7) 9 (11)), and your function call becomes:
> (size1 '((7) 9 (11)))
size is 3
So you would like to count the elements that are not null and not pairs:
(define (count-atoms tree)
(cond ((null? tree) 0) ; an empty tree has 0 atoms
((not (pair? tree)) 1) ; an atom is exactly one atom
(else ???))) ; the sum of counting atoms in car and cdr
This is very similar to how length is made.

Racket function that returns all numbers whose sum is <= given number?

I'm taking an intro to computer science course and one question needs me to write a function that takes a list of numbers and a number and returns the numbers in the list whose sum is less than the given number. I've written the function signature, definition, and check-expects, but I'm stuck. The function needs to assume intermediate student with lambda. I don't want any direct answers here; just help so that I can reach the answer myself.
I know it needs to use recursion. Perhaps a helper function would be needed.
;; sum-up-to: lon, number -> lon
;; consumes a list of numbers and a number and
;; returns the numbers in the list whose sum is
;; less than or equal to the given number
(define the-numbers (list 1 2 3 4 5 6 7 8 9))
(check-expect (sum-up-to the-numbers 7) (list 1 2 3))
(check-expect (sum-up-to the-numbers 18) (list 1 2 3 4 5))
(check-expect (sum-up-to the-numbers 45) the-numbers)
This problem can be simplified if we sort the list first and if we define a helper function that keeps track of the accumulated sum. Here's a skeleton, fill-in the blanks with the missing expressions and you'll have the solution:
(define (sum-up-to lst n)
(helper <???> n 0)) ; sort the input list, pass it to the helper
(define (helper lst n sum)
(cond (<???> '()) ; if the list is empty, end the recursion
((> <???> n) '()) ; also end recursion if sum + current element > n
(else
(cons <???> ; otherwise cons current element
(helper <???> ; advance recursion over list
n
(+ <???> <???>)))))) ; update sum
Following recursive method keeps adding numbers from the list sequentially to an initially empty outlist, till the sum is reached:
(define the-numbers (list 1 2 3 4 5 6 7 8 9))
(define (f lst sum)
(let loop ((lst lst)
(ol '()))
(if (or (..ENTER CONDITION FOR EMPTY LIST..)
(..ENTER CONDITION WHEN SUM IS REACHED..)
(..ENTER HOW TO PUT THE NEW LIST OUT..)
(loop (..ENTER ARGUMENTS TO BE SENT TO NEXT LOOP..)
))))
(f the-numbers 7)
(f the-numbers 18)
(f the-numbers 45)
Output:
'(1 2 3)
'(1 2 3 4 5)
'(1 2 3 4 5 6 7 8 9)

Generating list of lists of random numbers with lisp

I'm experimenting with Genetic Algorithms using Lisp,
I want to generate a list of lists that contains five random numbers.
I can generate that list but all the sub-lists are composed of the same random numbers and that is because I'm not sure I'm managing the "random state" properly.
Can anyone give me an hint?
here is the code:
(setf *random-state* (make-random-state t))
(defun random_in
(min max)
(+ (random (+ (- max min) 1) *random-state*) min))
(defun create_chromosome
(min max)
(list (random_in min max) (random_in min max) (random_in min max) (random_in min max) (random_in min max)))
(defun create_population
(individuals min max)
(make-list individuals :initial-element (create_chromosome min max)))
(write (create_population 3 10 100))
The output of this program is:
((54 51 85 61 44) (54 51 85 61 44) (54 51 85 61 44))
but I want each list composed by different random numbers.
Thank you for your time.
When you use :initial-element with make-list, that element is created only once.
One way to achieve what you want:
(loop :repeat individuals
:collect (create-chromosome min max))