Switch uppercase and lowercase of a string - racket

I'm doing a question where it asks me to convert all uppercases in a string to lowercases and lowercases to uppercases, and all other characters remain the same.
Below is my code:
(define (switch-case str)
(list->string
(cons
(cond
[(char-lower-case? (first (string->list str))) (char-upcase (first
(string->list str)))]
[(char-upper-case? (first (string->list str))) (char-downcase (first
(string->list str)))]
[else (first (string->list str))])
(switch-case (rest (string->list str))))))
The error message for str "ABC" is:
string->list: expects a string, given (cons #\B (cons #\C empty))
Can somebody tell me what has gone wrong with my code? Thx

The recursive call is on the wrong type. You pass [List-of Character] to switch-case, but it expects String.
; String -> String
(define (switch-case str)
(list->string
(cons
(swapcase nestr)
(switch-case
(rest (string->list str)) ; the type of this expression is [List-of Character]
))))
Follow this template:
; [List-of Character] -> [List-of Character]
(define (switch-case-charlist cl)
(cond [(empty? cl) ...]
[else (... (first cl) ... (switch-case-charlist (rest cl)))]))
; Character -> Character
(define (swap-case-character c)
...)
; String -> String
(define (swap-case-string s)
(list->string (... (string->list s))))

Related

define: expected only one expression for the function body, but found 1 extra part ceasercipher function

I am currently writing a drracket function for rscipher-3 that consumes a non-empty string s consisting of only alphabet uppercase letters and produces a new string (i.e., ciphertext) with the "right shift of 3" rule applied on s. Here is my function but I keep getting the "define: expected only one expression for the function body, but found 1 extra part" error.
(define (rscipher-3 s)
(define (helper s)
(cond [(empty? s) '()]
[(= (first s) "X") (cons "A" (helper (rest s)))]
[(= (first s) "Y") (cons "B" (helper (rest s)))]
[(= (first s) "Z") (cons "C" (helper (rest s)))]
[else (cons (integer->char (+ (char->integer (first s)) 3))
(helper (rest s)))]))
(list->string (helper (string->list s))))
Where did I go wrong?
Some DrRacket dialects/ teaching languages (Beginning Student, Intermediate Student and so on) don't allow definitions with multiple expressions.
Your rscipher-3 has two expressions:
First one:
(define (helper s)
(cond [(empty? s) '()]
[(= (first s) "X") (cons "A" (helper (rest s)))]
[(= (first s) "Y") (cons "B" (helper (rest s)))]
[(= (first s) "Z") (cons "C" (helper (rest s)))]
[else (cons (integer->char (+ (char->integer (first s)) 3))
(helper (rest s)))]))
Second one:
(list->string (helper (string->list s)))
You have to change your language- or, if you have to use it, move the definition of the helper function outside rscipher-3 definition. Also, you don't need these three branches (as noted in the comments, they also don't work, because you should compare with character, not with string):
[(= (first s) "X") (cons "A" (helper (rest s)))]
[(= (first s) "Y") (cons "B" (helper (rest s)))]
[(= (first s) "Z") (cons "C" (helper (rest s)))]
When you remove them, you can simplify your cond to if:
(define (helper s)
(if (empty? s) '()
(cons (integer->char (+ (char->integer (first s)) 3))
(helper (rest s)))))
(define (rscipher-3 s)
(list->string (helper (string->list s))))
Example:
> (rscipher-3 "FOOBAR")
"IRREDU"
If your DrRacket language supports map, you can also do:
(define (rscipher-3 s)
(list->string
(map (lambda (c) (integer->char (+ (char->integer c) 3)))
(string->list s))))

Create Python's collections.counter() method in Beginner Racket

The goal is to create a function that accepts a list of symbols and produces a list of key value pairs that count how many times each symbol in list appears. eg:
(counter (list 't 't 'c 'a)) -> (list (list 't 2) (list 'c 1) (list 'a 1))
The function must be completed with recursion
I've only gotten as far as to create a list of key value pairs that treat duplicates as standalone values:
(define val 0)
(define (counter los)
(cond
[(empty? los) empty]
[else (cons (list (first los) (add1 val))
(counter (rest los)))]))
(counter (list 't 't 'c 'a)) -> (list (list 't) (list 't) (list 'c 1) (list 'a 1))
It has been a very long time since I used BSL but I believe these operations are all present. There may be a cleaner way of doing this but I will leave it up to you to check the documentation and simplify it if possible
(define (counter los) (counter-helper los empty))
(define (counter-helper los lists)
(cond
[(empty? los) lists]
[else (if (list? (assq (first los) lists))
(counter-helper
(rest los)
(cons (list (first los) (add1 (second (assq (first los) lists))))
(remove (assq (first los) lists) lists)))
(counter-helper (rest los) (cons (list (first los) 1) lists)))]))
the if statement checks if there is already an entry in our list of lists for that key, it returns the pair if yes, false otherwise.
If the result is false we just append a new pair with value 1 and recur.
If it already exists, we construct a new pair from the previous one, with the same key, but the value incremented and append this new pair to our list of lists - the previous pair removed

Going over a list of strings to find the string with the needed prefix

I need to define the function plPrefixContained – that consumes 5 strings and
returns the first one that contains the string "pl" as a prefix – if one such
exists, and returns #f otherwise.
What I'm trying to do is to use the prefixes function to go over all the strings in the list and check their prefixes, put them in a new list and to output the first string as the result.
(I will handle the #f case later) my code is down below but it keeps giving me the error-
first: contract violation
expected: (and/c list? (not/c empty?))
given: '()
any help would be appreciated
(: plPrefixContained : String String String String String -> String)
(define (plPrefixContained x y z w v)
(list-ref (prefixes (list x y z w v) '()) 0))
(: prefixes : (Listof String) (Listof String) -> (Listof String))
(define (prefixes lis em)
(cond
[(and (eq? (string-ref (first lis) 0) "p") (eq? (string-ref (first lis) 1) "l"))
(cons (first lis) em)]
[else
(prefixes (rest lis) em)]))
this is how I want my output to be like-for example
(test (plPrefixContained "yypl" "opl" "lpTT" "plpl" "lol")
=>
"plpl")
There are two problems:
intensional equality eq?, instead of extensional equality such as equal? or string=?
comparing string / char, instead of comparing char / char or string / string
You are using eq?, which always makes me suspicious. eq? uses "intensional" equality, which is basically pointer equality, meaning that a string which is allocated somewhere in memory won't necessarily be eq? even if it has the same characters. You can see this with (eq? "abc123" (string-append "abc" "123")).
If you're dealing with strings, lists, or any other data which "contains" things, you should avoid eq?. Instead you should use an "extensional" equality predicate such as equal?, or even better, a predicate specific to the types of values you expect, such as string=?. Here's how they behave better than eq?:
> (eq? "abc123" (string-append "abc" "123"))
#f
> (equal? "abc123" (string-append "abc" "123"))
#t
> (string=? "abc123" (string-append "abc" "123"))
#t
Since you're comparing using the strings "p" and "l", I should be able to substitute eq? with string=? in your code:
(: prefixes : (Listof String) (Listof String) -> (Listof String))
(define (prefixes lis em)
(cond
[(and (string=? (string-ref (first lis) 0) "p") (string=? (string-ref (first lis) 1) "l"))
(cons (first lis) em)]
[else
(prefixes (rest lis) em)]))
However, this reveals the second problem, which I only spotted after seeing the error message:
string=?: contract violation
expected: string?
given: #\y
argument position: 1st
other arguments...:
"p"
The string=? isn't working because its first argument, the result of string-ref, is a character (like #\y), not a string. To fix this, use char=? instead of string=?, and compare with the characters #\p and #\l instead of the strings "p" and "l".
(: prefixes : (Listof String) (Listof String) -> (Listof String))
(define (prefixes lis em)
(cond
[(and (char=? (string-ref (first lis) 0) #\p) (char=? (string-ref (first lis) 1) #\l))
(cons (first lis) em)]
[else
(prefixes (rest lis) em)]))

how to iterate through a list in racket? if the character in the list is alphabetic, I want to add to a new string

Here is my code? Can anyone tell me how to iterate through a list? if the character in the list is alphabetic, I want to add to a new string
#lang racket
(define (conversion input)
(define s (string))
(let ((char (string->list input)))
(cond
[(char-alphabetic? (first (char)))
(string-append s first)]
[(char-alphabetic? (rest (char)))
(string-append s rest)]))
(display s))
Basic iteration is:
(define (copy-list lst)
(if (null? lst)
'()
(cons (car lst)
(copy-list (cdr lst))))
(copy-list '(1 2 3)) ; ==> (1 2 3)
This one actually makes a shallow copy of your list. Sometimes you iterate with keeping some variables to accumulate stuff:
(define (sum-list lst acc)
(if (null lst)
acc
(sum-list (cdr lst) (+ acc (car lst)))))
(sum-list '(1 2 3)) ; ==> 6
Looking at these you'll see a pattern emerges so we have made stuff like map, foldl, and foldr to abstract the iteration:
(define (copy-list-foldr lst)
(foldr cons '() lst)
(define (copy-list-map lst)
(map values lst))
(define (sum-list-foldl lst)
(foldl + 0 lst))
Looking at your challenge I bet you can fix it with a foldr.

I am new to Racket and need some help for this function

I want the answer to be #t here:
> (is-member? "foo" '(4 5 #f "foo" a))
#t
But I'm getting the error:
> (is-member? "foo" '(4 5 #f "foo" a))
;string=?: contract violation
; expected: string?
; given: #f
; argument position: 2nd
; other arguments...:
; "foo"
My definitions of is-member? and is-member-string? are:
#lang racket
(define (is-member? num lst)
(if (null? lst)
#f
(if (string? num)
(is-member-string? num lst)
(is-member-number? num lst))))
(define (is-member-string? num lst)
(if (null? lst)
#f
(if (integer? (car lst))
(is-member-string? num (rest lst))
(if (string=? (car lst) num)
#t
(is-member-string? num (rest lst))))))
(define (is-member-number? num lst)
....)
Look at the error message and see how it helps you. It says the error is coming from string=?, and if you look in DrRacket it even highlights the specific call that went wrong. It's the (string=? (car lst) num) in the is-member-string? function.
Figure out what arguments were and why they're wrong. The error message says that the wrong argument was #f where it expected a string.
Where did the bad argument come from? Was it num or (car lst)? Looking at how num flows through the program, num should always be "foo", so it's probably the other one, (car lst).
How did this code execute with that bad argument? Why is (car lst) false here? Because it's walking down the list, and the list contains a false in it. That should be fine, as long as you design your function properly to handle all values.
To do that, you should put a type signature on your functions to show what types of arguments are allowed. For is-member-string? I'm assuming you meant:
;; is-member-string? : String [List-of Any] -> Boolean
(define (is-member-string? str lst)
....)
(I've renamed num to str because it's not a number, it's a string.)
Next you need to make sure that the code works with the signature. You're designing this function by destructuring the list argument, but you need to keep the types of the values in mind:
;; is-member-string? : String [List-of Any] -> Boolean
(define (is-member-string? str lst)
(if (null? lst)
#f
(.... (first lst) ; (first lst) is an Any
.... (rest lst)))) ; (rest lst) is a [List-of Any]
(I'm using first instead of car because first makes more sense.)
Can you see what's wrong now?
;; is-member-string? : String [List-of Any] -> Boolean
(define (is-member-string? str lst)
(if (null? lst)
#f
(if (integer? (first lst)) ; (first lst) is an Any
(is-member-string? str (rest lst))
(if (string=? (first lst) str) ; (first lst) is an Any, but not an integer
#t
(is-member-string? str (rest lst))))))
(first lst) is an Any, but you're using (string=? (first lst) str). That shouldn't be allowed unless you're sure that (first lst) is a string.
There are two ways to do this. One way to fix this is to use (equal? (first lst) str) instead.
;; is-member-string? : String [List-of Any] -> Boolean
(define (is-member-string? str lst)
(if (null? lst)
#f
(if (equal? (first lst) str)
#t
(is-member-string? str (rest lst)))))
The second way is to check that it's a string before you use string=?. I assume that's what you were trying to do with your integer? check, but it isn't working. Instead you want to use (string? (first lst)) somehow. You only want to check string=? after that passes. One way to do that is with and.
;; is-member-string? : String [List-of Any] -> Boolean
(define (is-member-string? str lst)
(if (null? lst)
#f
(if (and (string? (first lst)) (string=? (first lst) str))
#t
(is-member-string? str (rest lst)))))