#lang Scheme
(define-struct storeItem (id des cost))
(define redApple (make-storeItem 0 "red delicious apple" 1.99))
(define chickenLeg (make-storeItem 1 "boned chicken" 2.99))
(define porkLoin (make-storeItem 2 "processed pork" 4.99))
(define milkD (make-storeItem 3 "vitamin d milk" 3.99))
(define baguetteBread (make-storeItem 4 "french bread" 0.99))
(define orangeJuice (make-storeItem 5 "fruit juice drink)" 1.49))
(define beanCan (make-storeItem 6 "beans in a can" 2.49))
(define masterList '(redApple chickenLeg porkLoin milkD baguetteBread
orangeJuice beanCan))
I am trying to get a list of objects from my structure and I am unsure of the correct syntax. Below is what I tired
(storeItem-des (car masterList)
I was expecting "red delicious apple"
But I get
storeItem-des: contract violation
expected: storeItem?
given: redApple
It seems like it is returning redApple, which seems correct. Where am I going wrong?
You're creating a list of symbols, not storeItems.
'(x y z) is equivalent to (list 'x 'y 'z), not (list x y z). So if you want to create a list containing the values of the variables x, y and z, you need to use the latter.
Related
I am trying to create a function that allows users to have to input 2 values which will then show the elements of the list starting from the specific head to the specific tail. So far I have the basic code:
(define fruits (λ (n) (member n '( "Apple" "Pear"
"Peach" "pineapple"
"dragon fruit" "blue berry" "mango"
"strawberry"))))
so user can get for example:
(fruits "Pear")
'("Pear" "Peach" "pineapple" "dragon fruit" "blue berry" "mango" "strawberry")
I want the list to stop after a specific value that the user inputted. for instance peach to blue berry. I tried various things such as filters, sorts, range, in-range, strings, sequence, etc but still fail. Could anyone please explain to me how do this.
You're using member to get the tail of the list starting with the value you're interested in, but I prefer using dropf for that part, as it's more indicative of what you want to do (Plus when there's no match it returns an empty list, not #f, which simplifies things). There's also takef, which returns the head of the list until an element makes a predicate return false, but since it doesn't include that element, it won't quite work. It's easy to make an inclusive version, though, which can then be combined with dropf to get a list in the inclusive range of two values:
#lang racket/base
(require racket/function racket/list)
;;; Returns the elements of a list up to and including the first one that
;;; pred? returns false for.
(define (takef/inclusive lst pred?)
(for/list ([elem (in-list lst)]
#:final (not (pred? elem)))
elem))
;;; Returns a list of elements from the first one equal to first to the
;;; first one equal to last
(define (extract-list lst first last #:test [=? equal?])
(takef/inclusive (dropf lst (negate (curry =? first))) (negate (curry =? last))))
Examples:
> (extract-list '( "Apple" "Pear" "Peach" "pineapple" "dragon fruit" "blue berry" "mango" "strawberry")
"Peach" "blue berry")
'("Peach" "pineapple" "dragon fruit" "blue berry")
> (extract-list '( "Apple" "Pear" "Peach" "pineapple" "dragon fruit" "blue berry" "mango" "strawberry")
"peach" "blue berry" #:test string-ci=?)
'("Peach" "pineapple" "dragon fruit" "blue berry")
Assuming you want to write a 'primitive' version of this, without using things like for/list and so on, an approach is to do this:
Look at the list:
is it empty? If it is either the answer is the empty list or it is an error;
is the first element of the list the start element? If it is start (2) with this list and an empty list;
otherwise do (1) with the rest of the list.
Look at the first element of the list you now have:
is it empty? This is either an error or the result is the reverse of the list you are accumulating;
Is the first element the same as the end element you are looking for? if it is then the answer is the reverse of the result of consing his element onto the accumulator;
otherwise do (2) with the rest of the list and a cons of the first of the list and the accumulator.
Step (1) is implemented by the member function but I'll just implement it directly.
So here is that algorithm as a function. This version assumes that you don't want errors, but instead returns a second value to tell you whether it succeeded or not.
(define (take-between l from to (test? eqv?))
(let find-tail ([tail l])
;; search down tails of l for from
(cond
[(null? tail)
;; never found from
(values tail #f)]
[(test? (first tail) from)
;; we found it
(let take-tail ([remaining-tail tail]
[accum '()])
;; search down tails of tail for to, accumulating things into accum
;; on the way
(cond
[(null? remaining-tail)
;; never found to
(values (reverse accum) #f)]
[(test? (first remaining-tail) to)
;; found to
(values (reverse (cons (first remaining-tail) accum)) #t)]
[else
;; haven't yet found to
(take-tail (rest remaining-tail)
(cons (first remaining-tail) accum))]))]
[else
;; haven't yet found from
(find-tail (rest tail))])))
Now
> (take-between '(1 2 3 4 5) 2 4)
'(2 3 4)
#t
> (take-between '(1 2 3 4 5) 2 10)
'(2 3 4 5)
#f
> (take-between '(1 2 3 4 5) 10 20)
'()
#f
Give a single function to access the element a in the list L.
(define L '(1 2 (a 3 4 5)))
Following the form (define id expr) which binds id to the result of expression I have tried the following:
(define L '(1 2 (a 3 4 5) (car(cdr L))))
cdr accesses the tail of the list, i.e. a 3 4 5, if I am not mistaken, and then I apply car on the tail to access the head of the list, i.e a. However, it is not working on DrRacket IDE.
I think you meant to do this:
(define L '(1 2 (a 3 4 5)))
(car (car (cdr (cdr L))))
=> 'a
Which can also be written as:
(caaddr L)
=> 'a
You included the (car(cdr L)) part inside the list L.
> (define L '(1 2 (a 3 4 5) (car(cdr L))))
> L
(list 1 2 (list 'a 3 4 5) (list 'car (list 'cdr 'L))) ;; oh no
But that still doesn't extract the 'a because you need to access car of the inner list:
(define L '(1 2 (a 3 4 5)))
(car (car (cdr (cdr L))))
;; or (caaddr L)
I have this list
(define masterList(list redApple chickenLeg porkLoin milkD baguetteBread orangeJuice beanCan))
I am trying to make a function called lookup that will take an integer and return the element from the list that matches that integer. The list contains elements from a structure in this format
(define-struct storeItem (id des cost))
So I will be passing an integer that represents id and I want storeItem to be retuned.
For instance -
(define redApple (make-storeItem 0 "red delicious apple" 1.99))
If I searched masterList and passed it 0, I would expect redApple to be returned.
Any help on the syntax?
(define (contains masterList x)
(cond
((null? masterList) #f)
((eq? (car masterList) x) #t)
(else (contains (cdr masterList) x))))
This is what I am trying to make work.
It returns true/false correctly based on what I pass it.
(contains materList redApple) returns true.
How can I modify this to return redApple if 0 is entered?
;; These are the constructors to make the elements in our structure
(define redApple (make-storeItem 0 "red delicious apple" 1.99))
(define chickenLeg (make-storeItem 1 "boned chicken" 2.99))
(define porkLoin (make-storeItem 2 "processed pork" 4.99))
(define milkD (make-storeItem 3 "vitamin d milk" 3.99))
(define baguetteBread (make-storeItem 4 "french bread" 0.99))
(define orangeJuice (make-storeItem 5 "fruit juice drink)" 1.49))
(define beanCan (make-storeItem 6 "beans in a can" 2.49)
;; Creating a list that we will use as our master list which contains elements from our structure
(define masterList(list redApple chickenLeg porkLoin milkD baguetteBread orangeJuice beanCan))
Your general structure is correct, but you're not testing the correct condition with
(eq? (car masterList) x)
You don't want to compare x with the whole element of the list, just with its id component. So that should be:
(= (storeItem-id (car masterList)) x)
Also, to compare numbers you should use = or eqv? rather than eq?. See What is the difference between eq?, eqv?, equal?, and = in Scheme?
If you want to get the object with the ID, rather than just #true or #false, return (car masterList) when the ID matches.
(define (find-storeItem masterList x)
(cond ((null masterList) #false)
((= (storeItem-id (car masterList)) x) (car masterList))
(else (find-storeItem (cdr masterList) x))))
I'm stuck with a little problem here.
Say that I have a list of lists such as:
(define x '(("1" "one" "two" "2" "three")
("2" "four" "five" "0" "six")
("3" "seven" "eight" "4" "nine")
("4" "ten" "eleven" "2" "twelve")))
So what I want to do is to get each of those lists and make the elements within each one become a single string, such as:
"1 one two 2 three"
"2 four five 0 six" ...
I have designed these functions:
(define (get-sublista-from-lista lista)
(if (list? (car lista))
(car lista)
lista))
and:
(define (string-from-lista lista)
(define (list-to-string lista str)
(if (null? (cdr lista))
(string-append str (car lista))
(list-to-string (cdr lista)
(string-append str (car lista) " "))))
(list-to-string lista ""))
which work properly by themselves. But whenever I try a combination of the two of them or of one of them with another, like in:
(define (string-from-lista1 lista)
(define (list-to-string lista str)
(if (null? (get-sublista-from-lista lista))
(string-append str (car (get-sublista-from-lista lista)))
(list-to-string (cdr (get-sublista-from-lista lista))
(string-append str (car (get-sublista-from-lista lista)) ""))))
(list-to-string lista ""))
Then the individual lists within the master lists are passed as '(), resulting in a contract violation such as:
car: contract violation
expected: pair?
given: '()
Can someone explain why am I getting such error?
A built-in function string-join works to join different strings in a list into one string separated by default character space. Use map to apply it all members of list x and you will have a short code to accomplish this task:
(map string-join x)
Output:
'("1 one two 2 three" "2 four five 0 six" "3 seven eight 4 nine" "4 ten eleven 2 twelve")
I'm trying to use this:
(vector-set! (vector-ref array (car xy)) (cdr xy) step_count)
where xy is a list like '(0 0) passed in as a parameter.
But I get this error:
vector-set!: contract violation
expected: exact-nonnegative-integer?
given: '(0)
argument position: 2nd
other arguments...:
'#(0 0 0 0 0)
1
There is a problem with (cdr xy), I think I need to turn '(0) into 0 but I can't find a mechanism in Racket that can do that.
I know a line like this:
(vector-set! (vector-ref array (sub1 (car xy))) (sub1 (cdr xy)) (read))
works when you form xy with:
(define xy (cons (read) (read)))
Can someone point me in the right direction?
Thanks for reading.
When you use cdr on a list, it means "the rest of the list". The rest of a list is always a list, not a single element of a list.
If you want the second element of the list xy, then you need to use cadr.
(You could also use second.)
(define xy (list 1 2 3))
(cdr xy) ; '(2 3)
(cadr xy) ; 2
(second xy) ; 2