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

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))))

Related

Repeating elements in scheme [duplicate]

This code in Scheme is used to output a list in which the element of the input lists are repeated n times. I do not understand what is happening in the code.
(define (echo-lots lst n)
(define (helper lst1 n1)
(if (= n1 0)
'()
(cons lst1 (helper lst1 (- n1 1)))))
(if (null? lst)
'()
(append (helper (car lst) n) (echo-lots (cdr lst) n)))
First, note that helper does not use any of the parameters of echo-lots.
That means that you can move the definition outside and figure it out in isolation:
(define (helper lst1 n1)
(if (= n1 0)
'()
(cons lst1 (helper lst1 (- n1 1)))))
> (helper 1 3)
'(1 1 1)
> (helper #f 4)
'(#f #f #f #f)
> (helper '(a b c) 2)
'((a b c) (a b c))
It makes a list whose elements are the first parameter repeated the number of times given by the second parameter.
(It's not difficult to prove this formally, if you're in the mood for that.)
Note also that the first parameter's name is misleading - it does not have to be a list.
Let's improve the naming:
(define (repeat item n)
(if (= n 0)
'()
(cons item (repeat item (- n 1)))))
Now echo-lots is clearer:
(define (echo-lots lst n)
(if (null? lst)
'()
(append (repeat (car lst) n)
(echo-lots (cdr lst) n))))
and it's easier to see that it makes a list of n copies of the first element of lst - (repeat (car lst) n) - and appends that to a list consisting of n copies of each of the remaining elements - (echo-lots (cdr lst) n).

How can I just use high order functions to rewrite these (use Dr.Racket)

This is my homework but we are only allowed to use filter, map, foldr, sort, build-list, and lambda instead of the explicit recursion
How can I rewrite these use those high order functions above to not let the function call itself.
What I have now are these:
(define (worthless loc name)
(cond
[(empty? loc) loc]
[(equal? name (coin-name (first loc))) (cons (make-coin (coin-name (first loc)) 0) (worthless (rest loc) name))]
[else (cons (first loc) (worthless (rest loc) name))]))
(define (working-group locations group-tz)
(cond
[(empty? locations) empty]
[(and (equal? (utc-hours group-tz) (utc-hours (location-timezone (first locations)))) (equal? (utc-sign group-tz) (utc-sign (location-timezone (first locations)))))
(cons (location-city (first locations)) (working-group (rest locations) group-tz))]
[(and (equal? (add1 (utc-hours group-tz)) (utc-hours (location-timezone (first locations))))
(equal? (utc-sign group-tz) (utc-sign (location-timezone (first locations))))
(equal? (utc-mins group-tz) (utc-mins (location-timezone (first locations)))))
(cons (location-city (first locations)) (working-group (rest locations) group-tz))]
[(and (equal? (sub1 (utc-hours group-tz)) (utc-hours (location-timezone (first locations))))
(equal? (utc-sign group-tz) (utc-sign (location-timezone (first locations))))
(equal? (utc-mins group-tz) (utc-mins (location-timezone (first locations)))))
(cons (location-city (first locations)) (working-group (rest locations) group-tz))]
[else (working-group (rest locations) group-tz)])) ```
Yes. worthless can be rewritten with map. Imagine we have this function that adds 3 to each element in a list:
(define (add3 lst)
(if (null? lst)
'()
(cons (+ (car lst) 3)
(add3 (cdr lst)))))
Map for one list looks like this:
(define (map f lst)
(if (null? lst)
'()
(cons (f (car lst))
(map f (cdr lst))))
Looking at these you can see that an add3 with map only needs to focus on adding 3. Basically you need to pass a function with one argument that adds 3 to that argument:
(define (add3-wm lst)
(map (lambda (v) (+ v 3)) lst))
Now foldr for one list looks like this:
(define (foldr f init lst)
(if (null? lst)
init
(f (car lst)
(foldr f init (cdr lst)))))
Here you see that cons isn't done so rewriting add3 using foldr takes a combiner and it needs to add 3 to the first argument and combine the two arguments where the second argument is the result fo the same process with the later elements.
(define (add3-fr lst)
(define (combiner v acc)
(cons (+ v 3) acc))
(foldr combiner '() lst))
In reality using foldr here is overkill, but it would be interesting if you sometimes needed to skip an element like working-group does. In that case the combiner just returns the second argument. You can make filter with foldr:
(define (filter f lst)
(foldr (lambda (v acc)
(if (f v)
(cons v acc)
acc))
'()
lst))
Good luck

Racket - Find lists that has the same element in a 2D list

Can someone please show me how to do this problem/give me a template? I'm not allowed to use map or lambda or any other advanced built-in functions, only list
First extract the country associated with the input string:
(define (get-country l s)
(cond [(empty? (rest l)) (second (second (first l)))]
[else (if (equal? s (first (first l)))
(second (second (first l)))
(get-country (rest l) s))]))
Then extract all strings that have that country associated with it:
(define (get-countries l s)
(cond [(empty? l) '()]
[else (if (equal? s (second (second (first l))))
(cons (first (first l)) (get-countries (rest l) s))
(get-countries (rest l) s))]))
Then put them together:
(define (same-country l s)
(get-countries l (get-country l s)))
When we evaluate we get a result different from (list "YUL" "YVR" "YWG" "YYZ"):
> (same-country alist "YUL")
(list "YYZ" "YWG" "YUL" "YVR")
So we check if the result is a permutation of the desired list. First we make is-permutation:
(define (is-permutation l1 l2)
(and (not (and (cons? l1) (empty? l2)))
(not (and (empty? l1) (cons? l2)))
(or (and (empty? l1) (empty? l2))
(and (is-member (first l1) l2)
(is-permutation (rest l1)
(remove-one (first l1) l2))))))
(define (is-member e l)
(and (not (empty? l))
(or (equal? (first l) e)
(is-member e (rest l)))))
(define (remove-one e nel)
(cond [(empty? (rest nel)) '()]
[else (if (equal? (first nel) e)
(rest nel)
(cons (first nel) (remove-one e (rest nel))))]))
Then we can test:
> (is-permutation (same-country alist "YUL")
(list "YUL" "YVR" "YWG" "YYZ"))
#true

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.

my "lisp-pl language" throwing mistakes

Cheers!!! i have a question about a function contract that i need to write in the pl language (a lisp contribution ) the contract suppose to have a (list of type A)(list of type b) and return a list of lists (type A B) simultaneously . this is what i got so far but it doesn't work :
(: zip2 : (All (A B) (Listof A) (Listof B) -> (Listof (list A B))))
(define (zip2 listA listB)
(cond [(null? listA) (list (null null))]
[else (list ((car listA) (car listB)))])
(zip2 ((rest listA) (rest listB))))
(equal? (list (list 1 'a) (list 2 'b) (list 3 'c)) (zip2 (list 1 2 3) (list 'a 'b 'c)))
(define (zip2 listA listB)
(cond [(null? listA) null]
[else (cons (list (car listA) (car listB))
(zip2 (rest listA) (rest listB)))]))
Probably the simplest approach is just to use mapping. [Since you are using define I'll assume you are using Scheme].
(define (zip A B) (map list A B))
If you can't use map, then here is a tail-recursive algorithm:
(define (zip A B)
(let zipping ((a A) (b B) (rslt '())
(if (or (null? a) (null? b))
(reverse rslt)
(zipping (cdr a) (cdr b)
(cons (list (car a) (car b)) rslt)))))