Checking if element is present in list in racket - string

How to check if an element is present in a list, both taken as input from the function call, without using the lambda? I was trying member? but could not get it.
(define (find-string (lst lst str ua)
(cond ((member? ua lst) #t)
(else #f))

The use of member would work it's just that you are adding extra "?" in front of the function none is required
(member 2 (list 1 2 3 4)) [1]
would return true
another way around is writing ones own recursive function
(define (is-in-list list value)
(cond
[(empty? list) false]
[(= (first list) value) true]
[else (is-in-list (rest list) value)]))
[1]https://docs.racket-lang.org/reference/pairs.html#%28def._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._member%29%29

First, the way with lambda and ormap (for testing):
; ismember? :: String List-of-Strings -> Bool
(define (ismember1? str strs) (ormap [lambda (s) (string=? s str)] strs) )
Second way, with for/or, without lambda:
(define (ismember2? str strs)
(for/or ([s (in-list strs)])
(string=? s str) ) )
Third way, with member, without lambda:
(define (ismember3? str strs) (if [member str strs] #t #f) )
Refer to the official Racket documentation for member.
Notice that the last version is actually the worst in terms of performance.

Related

How do I find the number of characters in a string using scheme programming language?

I used string-length to get the number of characters but I am having difficulties in defining a recursive function. Should I convert the string to a list and then count the elements?
There's no useful way of doing this recursively (or even tail recursively): strings in Scheme are objects which know how long they are. There would be such an approach in a language like C where strings don't know how long they are but are delimited by some special marker. So for instance if (special-marker? s i) told you whether the i'th element of s was the special marker object, then you could write a function to know how long the string was:
(define (silly-string-length s)
(let silly-string-length-loop ([i 1])
(if (special-marker? s i)
(- i 1)
(silly-string-length-loop (+ i 1)))))
But now think about how you would implement special-marker? in Scheme: in particular here's the obvious implementation:
(define (special-marker? s i)
(= i (+ (string-length s) 1)))
And you can see that silly-string-length is now just a terrible version of string-length.
Well, if you wanted to make it look even more terrible, you could, as you suggest, convert a string to a list and then compute the length of the lists. Lists are delimited by a special marker object, () so this approach is reasonable:
(define (length-of-list l)
(let length-of-list-loop ([i 0]
[lt l])
(if (null? lt)
i
(length-of-list-loop (+ i 1) (rest lt)))))
So you could write
(define (superficially-less-silly-string-length s)
(length-of-list
(turn-string-into-list s)))
But, wait, how do you write turn-string-into-list? Well, something like this perhaps:
(define (turn-string-into-list s)
(let ([l (string-length s)])
(let loop ([i 0]
[r '()])
(if (= i l)
(reverse r)
(loop (+ i 1)
(cons (string-ref s i) r))))))
And this ... uses string-length.
What is the problem with?
(string-length string)
If the question is a puzzle "count characters in a string without using string-length",
then maybe:
(define (my-string-length s)
(define (my-string-length t n)
(if (string=? s t) n
(my-string-length
(string-append t (string (string-ref s n))) (+ n 1))))
(my-string-length "" 0))
or:
(define (my-string-length s)
(define (my-string-length n)
(define (try thunk)
(call/cc (lambda (k)
(with-exception-handler (lambda (x)
(k n))
thunk))))
(try (lambda ()
(string-ref s n)
(my-string-length (+ n 1)))))
(my-string-length 0))
(but of course string-ref will be using the base string-length or equivalent)

Scheme: How to find a position of a char in a string

I am trying to find the index of a string where it is equal to a certain character, but I can seem to figure it out.
This is what I got so far, but its not working...
(define getPos
(lambda ()
(define s (apply string-append myList))
(getPosition pos (string->list s))))
(define getPosition
(lambda (position s)
(if (and (< position (length s)) (equal? (car s) #\space))
((set! pos (+ pos 1)) (getPosition (cdr s) pos));increment the positon and continue the loop
pos)));else
(define length
(lambda (s);the value s must be coverted to a string->list when passed in
(cond
((null? s) 0)
(else (+ 1 (length (cdr s)))))))
The solution is simple: we have to test each char in the list until either we run out of elements or we find the first occurrence of the char, keeping track of which position we're in.
Your proposed solution looks weird, in Scheme we try to avoid set! and other operations that mutate data - the way to go, is by using recursion to traverse the list of chars. Something like this is preferred:
(define (getPosition char-list char pos)
(cond ((null? char-list) #f) ; list was empty
((char=? char (car char-list)) pos) ; we found it!
(else (getPosition (cdr char-list) char (add1 pos))))) ; char was not found
For 0-based indexes use it like this, converting the string to a list of chars and initializing the position in 0:
(getPosition (string->list "abcde") #\e 0)
=> 4
Of course, we can do better by using existing procedures - here's a more idiomatic solution:
(require srfi/1) ; required for using the `list-index` procedure
(define (getPosition string char)
(list-index (curry char=? char)
(string->list string)))
(getPosition "abcde" #\e)
=> 4
A solution with for:
#lang racket
(define (find-char c s)
(for/first ([x s] ; for each character in the string c
[i (in-naturals)] ; counts 0, 1, 2, ...
#:when (char=? c x))
i))
(find-char #\o "hello world")
(find-char #\x "hello world")
Output:
4
#f

How to get the last element of a list and return nil if the element isn't in the list

I would like to get the position of any element in the list and get nil if the element isn't in the list. I did:
(defun myposition (letter list)
(cond
((atom list) nil)
((equal (car list) letter) 0)
((null (car list)) (myposition letter))
(t (1+ (myposition letter (cdr list)))) ) )
(myposition 'k '(g h i j k l)
4
(myposition 'p '(g h i j k l)
nil is not a number
When I replace ((atom list) nil) par ((atom list) 0), I get 6 instead nil
(myposition 'p '(g h i j k l)
6
In your first example, your function will recursively compute 1+1+1+1+0 = 4 to find the correct result.
In your second example, it will run through the whole list, add 1 per (non-matching) element, and finally add nil. So it actually computes 1+1+1+1+1+1+nil, which is incorrect since nil is not a number, hence the error message. If you replace nil by zero, it computes 1+1+1+1+1+1+0 which is wrong.
So your basic problem is that you recursively add 1 and, reaching the end of the list, you would like to throw away what you computed until then. But you have an addition pending which you cannot escape.
The easiest way is to change from a recursive to a tail-recursive solution, which is technically a plain goto. Here the addition is done by incrementing a variable, not by unwinding the call stack, which makes it easy to throw away the result from the previous additions and just return nil because there is no addition pending.
A (tail-)recursive solution could be:
(defun myposition (letter lst)
(labels ((sub (lst pos)
(cond
((null lst) nil)
((equal (car lst) letter) pos)
(t (sub (cdr lst) (1+ pos))))))
(if (atom lst) nil (sub lst 0))))
This will work in Common Lisp, but technically, if your implementation does no tail call optimisation, it might still blow the stack for large lists. That's why Common Lisp prefers iterative solutions, such as using the loop macro:
(defun myposition (letter lst)
(when (consp lst)
(loop for c in lst for i from 0
when (equal c letter) return i)))

Scheme - list functions with filter

I am currently working on a homework assignment with MIT scheme, and have come across a few problems that are supposedly very short, though I'm a bit confused as to how to implement some of them.
One problem asks me to write a function that returns a list with all the integers removed. I did manage to solve that,
(define (f2a lst) (map (lambda(x) (remove number? x)) lst))
though I'm confused as to how I can rewrite it to not use remove, but rather use a filter.
*note: (f2a '(("a" 1 "b") (2 "c") (-1 "d") (-2))) returns '(("a" "b") ("c") ("d"))
The other two problems are ones to which I haven't found any solutions.
They ask me to write a function that returns a list with all positive odd and negative even integers removed. For example,
(f2b '(("a" 1 "b") (2 "c") (-1 "d") (-2)))
returns
(("a" "b") (2 "c") (-1 "d"))
I have some code down that is incorrect, but I feel shows how I have tried to approach solving this one:
(define (f2b lst)
(lambda(x)
(cond ((and (positive? x) (odd? x)) (filter x lst))
((and (negative? x) (even? x)) (filter x lst))
(else "this should never print"))))
The last problem simply asks for a function that returns a string consisting of all strings appended together in a list. (f2c '(("a" 1 "b") (2 "c") (-1 "d") (-2))) returns "abcd".
I almost managed to figure this one out, but got stuck when it kept returning strange values. This is the code I have:
(define (f2c lst)
(lambda(x)
(map (lambda (x) (filter string? x)) lst)
(list x))
(string-append (car lst) (cdr lst)))
In terms of higher-order syntax, I'm limited to map, filter, accumulate and sum. I am not asking for a direct answer, but rather some help for me to figure out what I need to do. What am I doing wrong with my code? Any assistance given with this is very much appreciated. Thank you.
The structure of the input and the desired output is identical in the first two problems; the only thing that differs is the predicate on when/when-not to remove an element. For the second case it would be:
(define (f2b lst)
(map (lambda (sublst)
(remove (lambda (x)
(and (number? x)
(or (and (positive? x) (odd? x))
(and (negative? x) (even? x)))))
sublst))
lst))
Since only the predicate differs you can generalize this as:
(define (f2x predicate)
(lambda (lst)
(map (lambda (sublst) (remove predicate sublst)) lst)))
(define f2a (f2x number?))
(define f2b (f2x (lambda (x)
(and (number? x)
(or (and (positive? x) (odd? x))
(and (negative? x) (even? x))))))
For your last problem, you can use the result of the first problem as:
(define (f2c lst)
(apply string-append (apply append (f2a list))))
Also, note that your syntax for f2b and f2a is incorrect. You are using
(define (func arg)
(lambda (x) ...))
which means that (func arg) returns a function which isn't what you want.

Scheme String Help

I am trying to write a function that evaluates to the number of distinct characters in the input string str. So for example (distinct-char "eeeiicczz") would return 4. I need some help with my code. This is what I have.
(define string-contains
(lambda (str char)
(if (equal? str "")
#f
(if (char=? (string-ref str 0) char)
#t
(if (not (char=? (string-ref str 0) char))
(string-contains (substring str 1 (string-length str)) char))))))
(define unique-chars
(lambda (str)
(cond
((equal? str "") "")
((equal? (string-length str) 1) (string-ref str 0))
(else
(if (equal? (string-contains (substring str 1 (string-length str)) (string-ref str 0)) #t)
(unique-chars (substring str 1 (string-length str)))
(string-append (substring str 0 1) (substring str 1 (string-length str))))))))
(define distinct-char
(lambda (str)
(string-length (unique-chars str))))
I am limited to using these Built in functions:
(if x y z), (cond ...),
(read)
(string-length x)
(string-ref str x)
(substring x y)
(string-append x y)
(equal? x y), (char=?)
(remainder x y), (quotient x y)
(max ...), (min ...)
(+ x y), (- x y), (* x y), (/ x y)
(> x y), (< x y), (<= x y), (>= x y)
(and x y), (or x y), (not x y)
Since it's possible to convert a string to a list, it would be much easier to do that and use the built in list functions. (Note: the following code is in Racket. Since it's pretty much Scheme, I'm assuming these functions exist. If they don't check your docs for something similar)
(define (distinct-char str)
(length (remove-duplicates (string->list str))))
Here is a template you can fill in. Replace the comments with what you think should happen in each situation. Good luck!
(define (empty-string? str)
( #| What property does an empty string have? Add a simple boolean expression here. |# )
(define (char-exists? str char)
(cond
[(empty-string? str) ( #| If the string is empty, does the character exist? |# )]
[else ( #| Check the first character in the string. If it is what we're looking for
we're done! If it's not call this function on the rest of the string. |# )]))
(define (unique-chars str)
(cond
[(empty-string? str) ( #| What should you return if the string is empty? |# )]
[(equal? (string-length str) 1) ( #| What should you return if the string is one character long? |# )]
[else ( #| If the character at the beginning of the string exists in the rest of the string, ignore it
and preform recursion on the rest of the string. If it doesn't, append the character to
the result of this function on the rest of the string. |# )]))
(define (distinct-char str)
(string-length (unique-chars str)))
One of the reasons you learn stuff in scheme is it trains you to build up useful building blocks yourself, and then hook those building blocks together.
In this case, the general approach I would recommend is to write a function:
(string-contains str ch)
That returns #t or #f depending on whether or not str contains the character ch, and then use that to define a function:
(unique-chars str)
that returns a string of the unique characters in str (you scan str, building up your answer, and at every spot see if the next character is already in the answer string you're building, and if not, add it to your answer string).
Then, the function you wanted is just
(string-length (unique-chars str))
You can keep and pass along a list of every distinct character that you've come across before. That way, every time you check a new character, you look it up in your list to see if you've already seen it before. If it's not in your list, then it's a new character and you can add it to your list.
Homework question, so I'm not writing code in the answer.

Resources