How to get the cheapest fruit - list

I am practicing DrRacket. Here is the task description:
Recursion is not allowed, you must use filter or map/or/andmap or foldr/foldl to loop through lists. creat a function names cheapest-fruit=bundle and receive a list of fruits as parameter. you input lists of fruit-bundles and want to get the cheapest fruit-bundle. If two fruit-bundles are both the cheapest, then chose the one with more kinds of fruit.
(define-struct fruit (name price))
(define (cheapest-fruit-bundle fruits)...)
check-expected:
giving list: (list (list (make-fruit 'apple 3) (make-fruit 'banana 4) (make-fruit 'avocado 5))
(list (make-fruit 'apple 7)(make-fruit 'avocado 5))
(list (make-fruit 'apple 7)(make-fruit 'avocado 9) (make-fruit 'banana 2)))
results: (list (make-fruit 'apple 3) (make-fruit 'banane 4) (make-fruit 'avocado 5))
I have solved this problem a bit: I can sum up the price in list and find the smallest element. But I want to get the cheapest bundle and choose the bundle with more kinds of fruits. I get stucked in this step. Furthermore, my function to choose smallest element not meet requirement, because I use recursion of list itself, and I should use map/foldr/foll.filter.
Here is what I have tried;
(define (sum-price f) (foldl + 0 (map fruit-price f)))
(define (smallest l)
(cond [(empty? (rest l)) (first l)]
[else (local ((define smallest-in-rest (smallest (rest l))))
(if (< (first l) smallest-in-rest) (first l) smallest-in-rest))]))
(define (cheap-fruit-bundle myfruit)
(smallest (map (lambda (fruit-list) (sum-price fruit-list)) myfruit)))
my code give out at end only a number. I have spent hours on this task and can't think up new ideas. Thanks for help in advance.

cheapest-budle-and-max-optioin function process is:
If budle-1's price less than budle-2's price we choice budle-1.
Or budle-1's price might bigger or equal to budle-2's price. If budle-1's price bigger than budle-2 we choice budle-2.
Or two budle price is the same. Than we compare options.
Notice: In here if we have many budles have same price and same option number we still choice one budle.
After finish cheapest-budle-and-max-optioin process. Using foldlr to compare each budle element in list.
(define-struct fruit (name price) #:transparent #:mutable)
(define (filter-cheapest-budle-and-max-optioin budle-list)
(local [(define (budle-price budle-list)
(foldl + 0 (map fruit-price budle-list)))
(define (budle-option-n budle-list)
(foldl (lambda (x1 x2) (+ x2 1)) 0 budle-list))
(define (budle-option<? b1 b2)
(< (budle-option-n b1) (budle-option-n b2)))
(define (budle-price<? b1 b2)
(< (budle-price b1) (budle-price b2)))
(define (cheapest-budle-and-max-optioin b1 b2)
(cond
[(budle-price<? b1 b2) b1]
[(budle-price<? b2 b1) b2]
[(budle-option<? b1 b2) b2]
[else b1]))]
(foldr cheapest-budle-and-max-optioin (first budle-list) budle-list)))
;;; TEST
(define budle-list1
(list
(list (make-fruit 'apple 0.5)
(make-fruit 'banana 0.5))
(list (make-fruit 'apple 1))
(list (make-fruit 'avocado 1))))
(define budle-list2
(list
(list (make-fruit 'apple 1)
(make-fruit 'banana 1))
(list (make-fruit 'apple 2))
(list (make-fruit 'avocado 2))))
(filter-cheapest-budle-and-max-optioin budle-list1) ; should be (list (fruit 'apple 0.5) (fruit 'banana 0.5))
(filter-cheapest-budle-and-max-optioin budle-list2) ; should be (list (fruit 'apple 1) (fruit 'banana 1))

When you get stuck in a programming problem, a good strategy is to break that problem down into the smallest parts that make sense. You can focus on small problems that are easier to solve, and then combine those parts into the final solution. After you have a working solution, you can refactor if you wish, combining the smaller procedures into larger ones.
Here is one way that you can break your problem down into smaller parts.
You already have a working definition for sum-price, although I am going to change the name here:
(define-struct fruit (name price))
(define fruit-bundles (list (list (make-fruit 'apple 3)
(make-fruit 'banana 4)
(make-fruit 'avocado 5))
(list (make-fruit 'apple 7)
(make-fruit 'avocado 5))
(list (make-fruit 'apple 7)
(make-fruit 'avocado 9)
(make-fruit 'banana 2))))
(define (bundle-price bundle)
(foldl + 0 (map fruit-price bundle)))
Now, we want to be able to take a list of fruit-bundles and get to the largest, cheapest fruit bundle of the list. The first part of this problem seems to be that we want to get a list of all of the cheapest bundles; after that we can worry about getting the largest bundle.
I'd like to do something like this to get a list of the cheapest bundles, using filter with an anonymous procedure that returns true when the bundle price is equal to the minimum bundle price:
;; Takes a list of fruit-bundles and returns a list of the cheapest bundles.
(define (cheapest-bundles bundles)
(filter (lambda (b) (= (bundle-price b)
(min-bundle-price bundles)))
bundles))
I already have bundle-price, so I just need to write min-bundle-price. Since I know that I can map over a list of fruits to get a list of prices, I just need to apply the min procedure to that list:
;; Takes a list of fruit-bundles and returns the minimum bundle price.
(define (min-bundle-price bundles)
(apply min (map bundle-price bundles)))
Now I have a way to get a list of the cheapest fruit bundles. Now, lets test the cheapest-bundles procedure:
scratch.rkt> (cheapest-bundles fruit-bundles)
'((#<fruit> #<fruit> #<fruit>) (#<fruit> #<fruit>))
Well, that looks ok, but we can't really see what is in the fruit structs. Let's just write a couple of utility procedures to help us see inside the structs:
;; A couple of utility functions for inspecting fruits.
(define (inspect-fruit f)
(list (fruit-name f) (fruit-price f)))
(define (inspect-fruit-bundle bundle)
(map inspect-fruit bundle))
Now let's try again:
scratch.rkt> (map inspect-fruit-bundle (cheapest-bundles fruit-bundles))
'(((apple 3) (banana 4) (avocado 5)) ((apple 7) (avocado 5)))
That is what we expected; this is a list containing the two cheapest fruit bundles.
Now we need to devise a way to get the largest fruit bundle from this list of the cheapest fruit bundles. But, it could be the case that there are multiple fruit bundles that are the same size; in that case, let's agree to take the first bundle from a list of the largest bundles. So, we plan on creating a list of largest bundles, and we want the first element from that list:
;; Takes a list of bundles and returns the largest bundle.
;; If there are multiple largest bundles, the first one in the list is returned.
(define (largest-bundle bundles)
(car (largest-bundles bundles)))
We will need to write largest-bundles, which we can write in a way similar to the cheapest-bundles procedure by using filter to create a list of bundles with counts that are equal to the maximum count for all bundles:
;; Takes a list of fruit-bundles and returns a list of the largest bundles.
(define (largest-bundles bundles)
(filter (lambda (b) (= (bundle-count b)
(max-bundle-count bundles)))
bundles))
Before, we needed to get the price for a bundle, but now we will need to get a count of the number of kinds of fruits in a bundle:
;; Takes a fruit-bundle and returns the number of fruit elements.
(define (bundle-count bundle)
(length bundle))
Now we just need to write the max-bundle-count procedure. We can do this in a way similar to what we did for the min-bundle-price procedure, by applying the max procedure to a list of bundle counts:
;; Takes a list of fruit-bundles and returns the maximum bundle count.
(define (max-bundle-count bundles)
(apply max (map bundle-count bundles)))
Now we have a procedure that will get us a list of the largest fruit bundles, and another procedure that takes the first one from this list so that multiple hits are handled. Let's test them:
scratch.rkt> (map inspect-fruit-bundle (largest-bundles fruit-bundles))
'(((apple 3) (banana 4) (avocado 5)) ((apple 7) (avocado 9) (banana 2)))
scratch.rkt> (inspect-fruit-bundle (largest-bundle fruit-bundles))
'((apple 3) (banana 4) (avocado 5))
As expected, largest-bundles returns a list of the two largest fruit bundles, and largest-bundle returns the first fruit bundle in that list.
Now we just have to combine the above to create the cheapest-fruit-bundle procedure:
;; Takes a list of fruit-bundles and returns the largest, cheapest bundle.
(define (cheapest-fruit-bundle bundles)
(largest-bundle (cheapest-bundles bundles)))
Remembering to use inspect-fruit-bundle so that we can easily read the results, here is the final result:
scratch.rkt> (inspect-fruit-bundle (cheapest-fruit-bundle fruit-bundles))
'((apple 3) (banana 4) (avocado 5))

Related

mapcar with lambda and two list as input

first, i would like to understand the difference, if there is any, in the following code:
1 (setf list1 '(1 2 3))
2 (setf list2 '(10 100))
3
4 (defun som(x y )
5 (* x y))
6
7
8 (print(mapcar #'(lambda(x)x) list1))
9 (print (mapcar #'(lambda(x)x) list1))
which returns the following:
(1 2 3)
(1 2 3)
Then i would like to understand how to do the following:
(setf list1 '(1 2 3))
(setf list2 '(10 100))
(mapcar '#+ x y)
in order to get the following:
((11 101) (12 102) (13 103)), this is, add the first item of the first list
to every item of the second list.
Of course I could, very quickly define a function which would iterate through a list and apply a mapcar to the list. I was wondering if there is any primitive which would do that.
Thanks, have a good night
Your code
(setf list1 '(1 2 3))
(setf list2 '(10 100))
(defun som(x y )
(* x y))
(print(mapcar #'(lambda(x)x) list1))
(print (mapcar #'(lambda(x)x) list1))
;; This is the same between forms you do not need the space
;; but it is more readeable to write things with spcaes and tabs
so this is how I woul write the expression
(print (mapcar #'(lambda (x) x) list1))
or you can use the function identity
(print (mapcar #'identity list1))
allways remeber that the first element of the form is a function for the evaluator
to understand this you need to get a full understanding of lambda experssions and map functions in lisp also will be useful to learn functional programming, in that case you will wirte this as quickly as you will write the iterate version
You will have other aproches, this is not one of my foavourites because the use of global variables but it should do the thick it allways remember me to the iterative version
(defparameter *list1* '(1 2 3))
(defparameter *list2* '(10 100))
(print (mapcar (lambda (x) (mapcar (lambda (y) (+ x y)) *list2*)) *list1*))

Dr. Racket: Removing elements from a list using abstract list functions

So when given two lists, how do I remove elements in one list from another using only map, filter or foldr? I can't use explicit recursion or lambda either.
The lists consist of only numbers that are sorted in ascending order.
For example, if given (list 1 2 3) and (list 1 3 5), I want to remove all of the second list's elements from the first list. The output I want is (list 2).
If given (list 4 5 6) and (list 2 3 5), I would get (list 4 6).
I'm guessing the final code would be something like:
(define (fn-name list-one list-two)
(filter ... list-one))
Thanks!
Given that you're using Racket, we can write a simple solution in terms of some of the built-in abstract list functions and without using explicit lambdas, we only need a little help from SRFI-26. Try this:
(require srfi/26)
(define (difference lst1 lst2)
(filter-not (cut member <> lst2) lst1))
It works as expected:
(difference (list 1 2 3) (list 1 3 5))
=> '(2)
(difference (list 4 5 6) (list 2 3 5))
=> '(4 6)
You use filter, but you have to curry and invert member so you cannot do it without lambda.
(define (remove-elements needles haystack)
(filter (lambda (x) (not (member ...)))
haystack))
(define (remove-elements needles haystack)
(define (not-in-needles x)
(not (member ...)))
(filter not-in-needles haystack))
Both of these use lambda twice! Once for the define of remove-elements and once explicit / in not-in-needles. In your own example you use lambda once too since (define (name . args) . body) is the same as (define name (lambda args . body))

Transpose a matrix in racket (list of lists

I got a list of lists in racket and have to transpose them.
(: transpose ((list-of(list-of %a)) -> (list-of (list-of %a))))
(check-expect (transpose (list (list 1 2 3)
(list 4 5 6)))
(list (list 1 4)
(list 2 5)
(list 3 6)))
(define transpose
(lambda (xs)
(cond
((empty? xs)empty)
((pair? xs)(make-pair (make-pair (first(first xs)) (make-pair (first(first(rest xs)))empty)) (transpose (rest(rest xs))))))))
That's my code at the moment.
I think the problem is in the recursive call (correct me if I'm wrong please).
The actual outcome is (list (list 1 4)). The rest seems kinda ignored.
It would really help me, if somebody knows the problem, or has a tip.
The simplest definition of transpose is:
(define (transpose xss)
(apply map list xss))
Why does it work?
(apply map list '((a b) (d e))
= (apply map List '((a b) (d e)) ; use List rather than list
= (map List '(a b) '(d e))
= (list (List 'a 'd) (List 'b e))
= '((a d) (b e))
Here List is spelled with capital letters only to show which list was given by the user and which was produced by map.
Here is a less "clever" solution. It uses that the first column of
a matrix becomes the first row in the transposed matrix.
(define transpose
(lambda (xss)
(cond
[(empty? xss) empty]
[(empty? (first xss)) empty]
[else (define first-column (map first xss))
(define other-columns (map rest xss))
(cons first-column
(transpose other-columns))])))
(define (transpose xss)
(apply map list xss))
If you are, like me, new to Scheme, you'll wonder how the apply map list trick works.
It all boils down to understanding apply and map.
First, apply does its job. It takes a function, some fixed arguments and a list of arguments.
It calls the function with the fixed arguments followed by the flattenned list arguments.
So:
(apply map list '((1 2) (3 4)))
^^^^^^^^^^^^^^-- list of arguments
^^^^ ---------------- a fixed argument
^^^ --------------------- function
evaluates to:
(map list '(1 2) '(3 4))
Note how the list of lists is turned into two lists.
Now map accepts an N-argument function and N lists of equal length. Then it returns a list, where each element is an application of the function.
For example
(map + '(1 2) '(3 4))
evaluates to:
(list (+ 1 3) (+ 2 4))
In the transpose trick the function is simply list, so:
(map list '(1 2) '(3 4))
evaluates to:
(list (list 1 3) (list 2 4))
where the first list constructs a list because map always returns a list and the other two are invocations of the passed list function.
for/list can be used sequentially to create a list of lists with transposed items:
(define (transpose_ lol) ; lol is list of lists
(for/list ((i (length (list-ref lol 0)))) ; loop for length of first inner list
(for/list ((il lol)) ; for each inner list (il)
(list-ref il i)))) ; get its item
Testing:
(transpose_ (list (list 1 2 3)
(list 4 5 6)))
Output:
'((1 4) (2 5) (3 6))
(define (tr ls)
(if (empty? (car ls)) empty
(if (null? ls) empty
(cons (map car ls) (tr (map cdr ls))))))

Scheme: Counting Structures

(count-by-type
(list
(make-animal "Slytherin" "snake" (make-date 2013 8 23))
(make-animal "Toby" "dog" (make-date 2014 3 20))
(make-animal "Curly" "dog" (make-date 2014 1 18))
(make-animal "Maximus" "cat" (make-date 2013 10 7))
(make-animal "Mia" "cat" (make-date 2013 10 7))))
=> (list (list 2 "cat") (list 2 "dog") (list 1 "snake"))
;; A Date is a structure (make-date y m d), where
;; y is positive integer (year),
;; m is an integer between 1 and 12 (month),
;; d is an integer between 1 and 31 (day of the month).
(define-struct date (year month day))
;; An Animal is a structure (make-structure n t a), where
;; n is a nonempty string (name of animal),
;; t is a nonempty string (type of animal),
;; a is a Date (date animal arrived at the shelter).
(define-struct animal (name type arrival))
Note: The applicable data structures as at the top.
So I am trying to make a function (in Scheme using Dr. Racket) that consumes a list of Animal structures and produces a list of lists.
The elements in the produced lists are of the form (list number type) where type is the type of animal and number is the number of that animal type in the consumed list.
This much is doable for me, but here is where the issues comes in: -> The list needs to be in descending order -> Even worse, in the event of a tie between any number of pairs of lists, alphabetical sorting is utilized.
Note: I wish to only solve this using abstract list functions excluding build-list and lambda (as I wish to strengthen my ability to solve such problems without advanced abstract functions)
Keeping that in mind, I know this problem will use the abstract functions map, filter, and foldr, but can't quite think of how.
Any help is appreciated.
If you do (map animal-type list-of-animals) you get a list consisting just of the types like ("snake" "dog" "cat" "dog" "cat")
I imagine your list can be mixed (like in my example) so if you (sort list-of-animal-types string>?) you have a sorted list in descending order.
Given the list has at least one element:
(let rec ((cur (car sorted-list-of-animal-types))
(cnt 1)
(lst (cdr sorted-list-of-animal-types))
(acc '()))
(cond ((equal? cur <??>) (rec cur (add1 <??>) <??> acc))
(else (rec <??> 1 <??> (cons (list cnt cur) <??>)))))
This will produce a list in ascending order with counts. It's possible to do this with a fold, but it's probably not fewer lines than using a named let.
If you sort again:
(sort list-of-animal-types-and-counts (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 using let to store intermediates to make expressions shorter and more readable.
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 sepcial sort function that sorts by count, then animal type.

Reverse first n elements of a list in LISP

Assume I have the list (3 1 4 5 2) with the name "numbers". I am looking for a command that will reverse the list from index 0 up to an arbitrary index, i.e. (reverse numbers 2) which will give the new list as (4 1 3 5 2).
I've tried googling, but could not find a suitable function and I'm too much of a newbie to write the function myself at this stage.
Thank you.
Simple CL version based on the libary functions:
(defun reverse-first-n (list n)
(nreconc (subseq list 0 n) (nthcdr n list)))
This is memory-optimal, i.e., it does not allocate unnecessarily:
no need to copy the tail, thus nthcdr instead of subseq
revappend copies the 1st argument which is a fresh list anyway, so nreconc is more economical.
This version is speed-suboptimal, because it traverses list to the nth position 3 times - once in subseq, once in nthcdr, and then once in nreconc.
Here is the optimal verion:
(defun reverse-first-n (list n)
(if (or (= n 0) (= n 1))
list
(do* ((tail (list (pop list)))
(head tail (cons (pop list) head))
(count (1- n) (1- count)))
((zerop count)
(setf (cdr tail) list)
head))))
Note that there is very little chance that this is the performance bottleneck in your code. My main purpose in providing the second version is to show how much time and effort the extensive and well-designed CL library saves you.
Which dialect of Lisp are you using? Here's a Scheme solution (using SRFI 1):
(require srfi/1) ; assuming you're using Racket
(define (reverse-first-n lst n)
(call-with-values (lambda ()
(split-at lst n))
append-reverse!))
I made the function really "reverse the first n elements" like your title says, and unlike your question description. So for example:
> (reverse-first-n '(3 1 4 5 2) 2)
'(1 3 4 5 2)
> (reverse-first-n '(3 1 4 5 2) 3)
'(4 1 3 5 2)
As requested by the OP, here's a Common Lisp version. sds already posted a pretty decent version, so the version I'm writing is a more direct port of my Scheme solution (append-reverse! ⇒ nreconc; call-with-values ⇒ multiple-value-call; and I'm porting SRFI 1's split-at to CL):
(defun split-at (list n)
(if (zerop n)
(values '() list)
(multiple-value-bind (prefix suffix)
(split-at (cdr list) (1- n))
(values (cons (car list) prefix) suffix))))
(defun reverse-first-n (list n)
(multiple-value-call #'nreconc (split-at list n)))
(Why split-at? Its purpose is to provide both the take (subseq) and drop (nthcdr) with only one traversal of the input list.)