recursive problem using the image module in racket - racket

I have the following error on line 27:
first: expects a non-empty list; given: #<image>
Is it a problem with recursion?
I've been researching but can't find an example where the image package is used recursively.
I can't think of anything, I don't understand why it gives me that error :(
; You must make a program that needs a list of n figures, which you will paint,
; all the color options that the user indicates and separates by a fixed distance that you determine.
; These figures contain a name (they depend on the naming options that you set),
; a measurement or measurements according to what the figure requires and an indicator of whether it is painted full or only the silhouette.
; NOTE: These drawings must be made using the image of the package.
(require 2htdp/image)
(define-struct triangulo_ (color size complete))
(define-struct cuadrado_ (color size complete))
(define-struct circulo_ (color size complete))
(define circulo (make-circulo_ "yellow" 10 "outline"))
(define triangulo (make-triangulo_ "blue" 10 "solid"))
(define cuadrado (make-cuadrado_ "orange" 10 "outline"))
(define lista_figuras (cons circulo (cons triangulo (cons cuadrado empty))))
(define (validar figura ID)
(cond
[(empty? figura) ID]
[(and (circulo_? (first figura)) (positive? (circulo_-size (first figura))) (number? (circulo_-size (first figura))) (string? (circulo_-color (first figura))) (string? (circulo_-complete (first figura)))) (validar (rest figura) #t)]
[(and (cuadrado_? (first figura)) (positive? (cuadrado_-size (first figura))) (number? (cuadrado_-size (first figura))) (string? (cuadrado_-color (first figura))) (string? (cuadrado_-complete (first figura)))) (validar (rest figura) #t)]
[(and (triangulo_? (first figura)) (positive? (triangulo_-size (first figura))) (number? (triangulo_-size (first figura))) (string? (triangulo_-color (first figura))) (string? (triangulo_-complete (first figura)))) (validar (rest figura) #t)]
[else (validar (rest figura) #f)]))
(define (pathway figura)
(cond
[(empty? figura) empty]
[(circulo_? (first figura)) (pathway(circle (circulo_-size (first figura)) (circulo_-complete (first figura)) (circulo_-color (first figura))))]
[(triangulo_? (first figura)) (pathway(triangle (triangulo_-size (first figura)) (triangulo_-complete (first figura)) (triangulo_-color (first figura))))]
[(cuadrado_? (first figura)) (pathway(square (cuadrado_-size (first figura)) (cuadrado_-complete (first figura)) (cuadrado_-color (first figura))))]
[else (pathway (rest figura))]))
(define (main figura)
(cond
[(boolean=? (validar figura 0) #t) (pathway figura)]
[else "Error, solo se permiten: [ circulos, cuadrados y triangulos <equilateros> ]"]))
(main lista_figuras)

It's a type error. In the recursive call to pathway, you're passing in an image but it requires a list which contains triangulo_/cuadrado_/circulo_. Also the right hand side of the cond clauses in validar have multiple expressions, each will be evaluated from left to right but their values wouldn't matter, even if they're false. It's better to combine validation of each field with an and.
First, give a name to the structs you define, let's call it ImageConfig
At a higher level, the problem with the design is that you're mixing up list-processing with the processing of the element in the list. It's better to separate those.
Now separate the processing of [List-of ImageConfig] from ImageConfig for both validar and pathway.
; validar-l : [List-of ImageConfig] -> Boolean
; validar : ImageConfig -> Boolean
; pathway-l : [List-of ImageConfig] -> [List-of Image]
; pathway : ImageConfig -> Image
; main : [List-of ImageConfig] -> [List-of Image]
; You must make a program that needs a list of n figures, which you will paint,
; all the color options that the user indicates and separates by a fixed distance that you determine.
; These figures contain a name (they depend on the naming options that you set),
; a measurement or measurements according to what the figure requires and an indicator of whether it is painted full or only the silhouette.
; NOTE: These drawings must be made using the image of the package.
(require 2htdp/image)
; ImageConfig is one of
(define-struct triangulo_ (color size complete))
(define-struct cuadrado_ (color size complete))
(define-struct circulo_ (color size complete))
(define circulo (make-circulo_ "yellow" 10 "outline"))
(define triangulo (make-triangulo_ "blue" 10 "solid"))
(define cuadrado (make-cuadrado_ "orange" 10 "outline"))
(define lista_figuras (cons circulo (cons triangulo (cons cuadrado empty))))
; [List-of ImageConfig] -> Boolean
(define (validar-l fl)
(cond [(empty? fl) true]
[else (and (validar (first fl)) (validar-l (rest fl)))]))
; ImageConfig -> Boolean
(define (validar f)
(cond
[(circulo_? f) (and (positive? (circulo_-size f)) (number? (circulo_-size f)) (string? (circulo_-color f)))]
[(cuadrado_? f) (and (positive? (cuadrado_-size f)) (number? (cuadrado_-size f)) (string? (cuadrado_-color f)))]
[(triangulo_? f) (and (positive? (triangulo_-size f)) (number? (triangulo_-size f)) (string? (triangulo_-color f)))]))
; ImageConfig -> Image
(define (pathway f)
(cond
[(circulo_? f) (circle (circulo_-size f) (circulo_-complete f) (circulo_-color f))]
[(triangulo_? f) (triangle (triangulo_-size f) (triangulo_-complete f) (triangulo_-color f))]
[(cuadrado_? f) (square (cuadrado_-size f) (cuadrado_-complete f) (cuadrado_-color f))]))
; [List-of ImageConfig] -> [List-of Image]
(define (pathway-l fl)
(cond
[(empty? fl) empty]
[else (cons (pathway (first fl)) (pathway-l (rest fl)))]))
; [List-of ImageConfig] -> [List-of Image]
(define (main fl)
(cond
[(boolean=? (validar-l fl) true) (pathway-l fl)]
[else (error "Error, solo se permiten: [ circulos, cuadrados y triangulos <equilateros> ]")]))
(main lista_figuras)
Result:

Related

Using Racket BSL to abstract two functions and redfine the functions using the new abstraction

I have tried to abstract both functions (good-job and total-length) by creating a new abstraction function called new-num and this is what I have so far but I keep getting errors so I assume I am abstracting incorrectly:
; good-job : [List-of NonNegReal] -> [List-of NonNegReal]
; adds 20% to all supplied costs
(define (good-job lon)
(cond
[(empty? lon) '()]
[(cons? lon)
(cons
(add-thanks (first lon))
(good-job (rest lon)))]))
; add-thanks : NonNegReal -> NonNegReal
; adds 20% to the supplied cost
(define (add-thanks cost)
(* cost 1.2))
; total-length : [List-of String] -> Nat
; returns the total length of all strings in the list
(define (total-length los)
(cond
[(empty? los) 0]
[(cons? los)
(+
(string-length (first los))
(total-length (rest los)))]))
; new-num : [List-of X] X -> X
; abstracts good-job and total-length
; functions
(define (new-num lox cons/+ add-thanks/string-length def)
(cond
[(empty? lox) def]
[(cons? lox)
(cons/+
(add-thanks/string-length (first lox))
(new-num (rest lox) cons/+ add-thanks/string-length def))]))

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

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

Calculating the number of matches for every sublist separately

Here is my big list with sublists:
(define family
(list
(list 'Daddy 't-shirt 'raincoat 'sunglasses 'pants 'coat 'sneakers)
(list 'Mamma 'high-heels 'dress 'pants 'sunglasses 'scarf)
(list 'son 'pants 'sunglasses 'sneakers 't-shirt 'jacket)
(list 'daughter 'bikini 'Leggings 'sneakers 'blouse 'top)))
And i want to compare family with this simple list:
(list 'sneakers 'dress 'pants 'sunglasses 'scarf)
each matching should give 1 point and i want that the point to be calculated separately for each sublist.
Here is the code:
;checking if an element exists in a list
(define occurs?
(lambda (element lst)
(cond
[(and (null? element) (null? lst))]
[(null? lst) #f]
[(pair? lst)
(if
(occurs? element (car lst)) #t
(occurs? element (cdr lst)))]
[else (eqv? element lst)])))
;--------------------------------------
; a list of just names are created.
(define (name-list lst)
(list (map car lst)))
; Each sublist has a name (car of the sublist). The name-list turn to point-list for each sublist. All of my code except the code below is functioning as i want. The problem lies within point-list code.
(define (point lst db)
(let ((no-point (name-list db)))
(cond ((or (null? lst) (null? db)) '())
(set! (first no-point) (comp lst (rest db)))
(else (point lst (cdr db))))))
Daddy-sublist has 3 elements in common. Mamma-sublist has 4 elements in common, son-sublist 3 elements and daugther-sublist 1 element.
I want the outdata to be like this:
> (comparison (list 'sneakers 'dress 'pants 'sunglasses 'scarf) family)
'(3 4 3 1)
My code is not functioning as I want it. I get this Eror :
set!: bad syntax in: set!
Can someone guide explain me what to do?
You have bad syntax with set!:
(set! (first no-point-lst) (comparison lst (rest db)))
This is an invalid use of set!, attempting to "mutate the structure" of the list no-point-lst, changing what's actually held in its first position.
set! can't do that. It can be used to change a binding, i.e. the value of a variable: (let ((a 1)) (set! a 2)).
In Common Lisp they can write (setf (first list) newval), but not in Scheme / Racket.
If this is essential to your algorithm, you can use set-car! in R5RS Scheme, or set-mcar! in Racket. Or you could do this with vectors.
But you could also restructure your code as
(set! no-points-list
(cons
(comparison lst (rest db))
(cdr no-points-list)))

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