How can I just use high order functions to rewrite these (use Dr.Racket) - 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

Related

Reducing list (dr racket)

I am a beginner in Dr Racket and now I am looking for a solution to reduce nested lists.
For example:
+ 0 (list 1 2 (list 3 (list 4 5) 6) 7 (list (list 8)) empty 9))
should produce 45.
My current function only works for normal lists, but as soon as there is a list in the list, it doesn´t work anymore.
(define (reduce fun neutral lst)
(cond
((empty? lst) neutral)
(else
(fun (car lst)
(reduce fun neutral (rest lst))))))
You must consider the case where (car lst) is also a list. In that case, you will need to reduce (car lst) too, before applying fun.
(define (reduce fun neutral lst)
(cond
[(empty? lst)
neutral]
[(list? (car lst))
(fun (reduce fun neutral (car lst))
(reduce fun neutral (rest lst)))]
[else
(fun (car lst)
(reduce fun neutral (rest lst)))]))

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.

Racket. Make a list of pairs from a list

I want to make a list of pairs starting from a list, the cdr will be always the same. For example, (make-pair '(1 2 3 4 5)) should return '((1.a)(2.a)(3.a)(4.a)(5.a)).
This is the code i am developing, but it doesn't work and I don't know how to debug it.
(define (make-pair lst)
(if (null? (car lst))
'()
(cons ((car lst) ".a")
(make-pair (cdr lst)))))
Thank you in advance!
You have a couple of errors:
(define (make-pair lst)
(if (null? (car lst)) ; - the base case is when the list is null
'()
(cons ((car lst) ".a") ; - there's a missing cons
; - `a` appears to be a symbol, not a string
; - that's not how we create a dotted pair
; - the surrounding `()` are misplaced
(make-pair (cdr lst)))))
This is the right way:
(define (make-pair lst)
(if (null? lst)
'()
(cons (cons (car lst) 'a)
(make-pair (cdr lst)))))
Or even better, use built-in procedures:
(define (make-pair lst)
(map (lambda (n) (cons n 'a))
lst))
Either way, it works as expected:
(make-pair '(1 2 3 4 5))
=> '((1 . a) (2 . a) (3 . a) (4 . a) (5 . a))

Generate Permutations of a List

I'm writing a function that takes a list and returns a list of permutations of the argument.
I know how to do it by using a function that removes an element and then recursively use that function to generate all permutations. I now have a problem where I want to use the following function:
(define (insert-everywhere item lst)
(define (helper item L1 L2)
(if (null? L2) (cons (append L1 (cons item '())) '())
(cons (append L1 (cons item L2))
(helper item (append L1 (cons (car L2) '())) (cdr L2)))))
(helper item '() lst))
This function will insert the item into every possible location of the list, like the following:
(insert-everywhere 1 '(a b))
will get:
'((1 a b) (a 1 b) (a b 1))
How would I use this function to get all permutations of a list?
I now have:
(define (permutations lst)
(if (null? lst)
'()
(insert-helper (car lst) (permutations (cdr lst)))))
(define (insert-helper item lst)
(cond ((null? lst) '())
(else (append (insert-everywhere item (car lst))
(insert-helper item (cdr lst))))))
but doing (permutations '(1 2 3)) just returns the empty list '().
First, construct a family of related examples:
(permutations '()) = ???
(permutations '(z)) = ???
(permutations '(y z)) = ???
(permutations '(x y z)) = ???
Figure out how each answer is related to the one before it. That is, how can you calculate each answer given the previous answer (for the tail of the list) and the new element at the head of the list?
Here is a function, that generates all permutations of numbers with size 'size' , that it consisted of the elements in the list 'items'
(define (generate-permutations items size)
(if (zero? size)
'(())
(for/list ([tail (in-list (generate-permutations items (- size 1)))]
#:when #t
[i (in-list items)]
#:unless (member i tail))
(cons i tail))))