How to show elements of a list from selected head to tail in racket - list

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

Related

How can I append two lists together? Scheme

I need help merging two lists together. My goal is to replace "a" with "abc". I've already done a counter etc but somehow I can't append these two lists (list which is an empty list and '("abc") as my new list that I want to add).
I've tried to add more brackets but the problem just keeps getting worse the more I add.
(define (umwandl tr)
(cond ((null? tr) (display "Kein Text eingegeben"))
(else (uff (string->list tr) '())))) ; string wird nict inliste umgweandel
(define (uff tr liste)
(cond ((null? tr)(list->string liste))
(else
(cond ((equal? (first (rest (first (start1 (first tr))))) 1)
**((append list (list '("abc"))))))**
(uff (rest tr) liste))))
My error messages are either that ('("abc")) isn't an argument or it just gives me "" as an answer. It would be super nice if anyone could help!
Learning Scheme or any Lisp means getting to know list structure. A list (1 2 3) can be made like (cons 1 (cons 2 (cons 3 '()))) and I like to think that element in a list that does not have a . means there is one and the rest has an extra set of paranthesis. Done recursive! Thus:
'(1 2 3) ; ==
'(1 . (2 3)) ; ==
'(1 . (2 . (3))) ; ==
'(1 . (2 . (3 . ()))) ; ==> (1 2 3)
I see the dots that aren't there when I see lists so I know 3 is caddr since I pass . ( 2 times (dd) and then jump into the car, thus caddr.
Appending two lists together means copying the first list and replaceing () with the second list. Thus append can be defined as:
(define (my-append l1 l2)
(if (null? l1)
l2
(cons (car l1)
(my-append (cdr l1) l2))))
Replacing one element with another. You need to do the same BUT you compare the first element in each iteration and based on that either use the element you found or the replacement. If you want to compare strings then you need to use equal? since (eqv? "hello" "hello") ; ==> #f is a valid result.

Using map and other high order functions

I am still learning about high order functions and going to be quizzed on it soon. I am trying to write a program that takes 2 lists of the same length and subtracts the first from second, item by item, until you get 0 in the first position.
(check-expect (min (list 1 1 1) (list 2 4 6)) (list 2 4))
(check-expect (min (list 1 1) (list 2 3)) (list 1))
I can easily do this without map, but Is there any way I can use map here?
(map - 1 (list ...))
or when I pass it on to the first of a list, or rest.
wont work. I know it takes in a function and passes on to each element of a list. I am confused.
This is not a good example to start learning about map. The map higher-order procedure takes a list as input, and returns another list of the same length as output, where a function was applied to each of the elements in the input. See why this is not such a clear-cut case for using map? the output lists are smaller than the inputs!
Of course, it can be done, but it's not that elegant, and obscures the true purpose of map:
(define (min lst1 lst2)
(if (zero? (first lst2)) ; if the first position in lst2 is zero
(rest lst2) ; then return the rest of it.
(min lst1 ; otherwise advance recursion
(map - lst2 lst1)))) ; ok, here `map` was useful
To understand what's happening in the last line, imagine that the input lists are one on top of the other:
'(2 4 6)
'(1 1 1)
Then, map applies the - function element-wise:
(- 2 1)
(- 4 1)
(- 6 1)
And the result of each operation is collected in a new list:
'(1 3 5)
This is a special case of map: when there's more than one list after the function, it applies the function to the first element of each list before advancing to the next - hence the function must accept as many arguments as there are lists. The usual case with map is that you simply apply the function to each of the elements in a single list, and but the way this is a good place to use lambda:
(map (lambda (x) (* x x))
'(1 2 3 4 5))
=> '(1 4 9 16 25)

functions and lists in scheme/racket

How would you define a function which takes one argument, which should be a list, and returns the elements in the
list which are themselves lists?
(check-expect (find-sublists ’(1 2 () (3) (a b c) a b c))
’(() (3) (a b c)))
Do you have experience designing functions that can filter through a list?
A simpler problem with the same flavor as the original is something like this: design a function that takes a list of numbers and keeps only the even numbers. Would you be able to do that function?
Looking at http://www.ccs.neu.edu/home/matthias/HtDP2e/htdp2e-part2.html and going through its guided exercises may also help.
Two useful tools which should start you on your way:
1) Traversing through a list:
; traverse: takes a list of numbers
; Goes through each element, one-by-one, and alters it
(define traverse
(lambda (the_list)
(if (empty? the_list)
empty
(cons (+ 1 (first the_list))
(traverse (rest the_list))))))
(traverse (cons 3 (cons 4 empty))) returns (cons 4 (cons 5 empty))
2) list?:
(list? (list 1 2 3)) returns #t
(list? 5) returns #f

Trying to get the indices of an element from a list in scheme

So i'm trying to get the indices from a list ex:
(get-indices 'G (list 'A 'G 'T 'X 'I 'T 'G))
(2 7)
where the index starts at 1 so 'A is index one
I was thinking on using a helper function where it takes an elt lst and index
ex: (get-indices-helper el lst index)
I was also thinking about possibly using list-ref and like switching it to make it work in the get indices way however i could not find the actual scheme definition for it.
Write a function that recurses down the input list, keeping track of the position of the element that it's looking at, and emitting the matching indexes with cons. This is really trivial; I assume that it is a question that you have been set as homework?
; Walk down the list given in haystack, returning a list of indices at which
; values equal? to needle appear.
(define (get-indices needle haystack)
; Loop along the haystack.
(define (loop rest-of-haystack index)
; If the haystack is empty, return the empty list.
(if (null? rest-of-haystack) '()
; Recurse to the next position in the list.
(let ((rest-of-indices (loop (cdr rest-of-haystack) (+ index 1))))
(if (equal? (car rest-of-haystack) needle)
; If haystack is here, emit the current index.
(cons index rest-of-indices)
; Otherwise, return rest-of-indices.
rest-of-indices))))
; Run the loop defined above, from the beginning of haystack, with
; the first element being assigned an index of 1.
(loop haystack 1))
Testing this with GNU Guile or MzScheme or something:
(display (get-indices 'G (list 'A 'G 'T 'X 'I 'T 'G))) (newline)
(display (get-indices 1 (list 1 1 1 2 1 3))) (newline)
Prints:
(2 7)
(1 2 3 5)
Yay!

Lists in scheme

I'm trying to write a function in scheme that takes a list and squares every item on the list, then returns the list in the form (list x y z). However, I'm not sure how to write a code that will do that. So far, I have
(define (square=list list)
(cond
[(empty? list) false]
[else (list (sqr (first a-list))(square-list (rest a-list)))]))
but it returns the list in the form
(cons x (cons y (cons z empty)))
What can I do to make it return the list just in the form (list x y z)? Thanks!
You're almost there -- make sure you understand the difference between cons and list (the textbook How to Design Programs explains this in Section 13. You can find the online copy here).
cons will take an item as its first element and (usually) a (possibly empty) list for the 'rest' part. As an example, (cons 1 empty) has the number 1 as its first element and the empty list as the 'rest'. (cons 1 (cons 2 empty)) has the number 1 as the first element, and (cons 2 empty) as the 'rest'.
list is just an easy shorthand for making lists, taking an arbitrary number of items. Thus:
(list 1 2 3 4 5)
is the same as...
'(1 2 3 4 5)
which is the same as
(cons 1 (cons 2 (cons 3 (cons 4 (cons 5 empty))))).
But be careful. (list 1 (list 2 (list 3))) is not the same as (cons 1 (cons 2 (cons 3 empty))). In fact, it is (cons 1 (cons 2 (cons 3 empty) empty) empty).
If you're still confused, feel free to post a comment.
The problem is that you're using list in the else statement. You are saying build me a list with this value as the first entry, and a list as the second entry.
You want to cons the first entry onto the list created by recursive call.
(list 'a '(b c d))
; gives you
'(a (b c d))
(cons 'a '(b c d))
; gives you
'(a b c d)
This is probably not what your TA is looking for, but I'll throw it in anyway because it may help you grok a tiny bit more of Scheme. The idiomatic (in Scheme) way to write what you are trying to do is to use map:
> (map (lambda (x) (* x x)) '(1 2 3 66 102 10403))
(1 4 9 4356 10404 108222409)
map applies a function (here, (lambda (x) (* x x)) - a nameless function that returns the square of its input) to each element of a list and returns a new list containing all of the results. Scheme's map basically does the same iteration you are doing in your code, the advantage being that by using map you never have to explicitly write such iterations (and, nominally at least, a Scheme implementation might optimize map in some special way, though that's not really that important in most cases). The important thing about map is that it reduces your code to the important parts - this code squares each element of the list, this other code takes the square root of each element, this code adds one to it, etc, without having to repeat the same basic loop iteration code again and again.