Trying to create something similar to the "make-list" function in Racket - racket

I am trying to code a function that will let me input a list, and it will produce a list of lists. Each list in the product will contain i+1 duplicates of the what was in index i of the original list.
So something like (expand (list "a" "b" "c")) will give me (list (list "a") (list "b" "b") (list "c" "c" "c")).
I am using Racket Beginning Student with List Abbreviations, and I am not allowed to use the "make-list" function.

Write helper function with new argument (i = number of duplicates) and use function make-list for repeating given element i times (or write your own version of make-list):
(define (my-make-list i elem)
(if (<= i 0) '()
(cons elem (my-make-list (- i 1) elem))))
(define (expand-help lst i)
(if (null? lst) '()
(cons (my-make-list i (car lst))
(expand-help (cdr lst) (+ i 1)))))
(define (expand lst)
(expand-help lst 1))
Example:
> (expand (list "a" "b" "c"))
(list (list "a") (list "b" "b") (list "c" "c" "c"))

Related

Racket - Produce a new list based on given list

I'm trying to create a new list based on an original list where each element of the list contains the first element from the original list and second element being the product of the second and third element from the original list.
Example: If the original list is
(list (list "A" 2 3) (list "B" 3 4)
Then the result will be
(list (list "A" 6) (list "B" 12))
So far I've written:
(define (total-price-list lol)
(cond
[(empty? lol) empty]
[else (list (price-list (first lol))
(price-list (rest lol)))]))
(define (price-list row)
(list (first row) (* (second row) (third row))))
I don't know how to achieve the wanted result. Can someone help me with my code?
The lambda within the map keeps the first element as is and multiplies the second and the third element of each sublist.
(define (total-price-list lol)
(map (λ (l) (list (first l) (* (second l) (third l)))) lol))
(total-price-list (list (list "A" 2 3) (list "B" 3 4)))
; => '(("A" 6) ("B" 12))

Racket - Add or remove element from a 2dlist

I'm doing a problem which asks me to write a function that consumes a
list (dict1) and a list (act) that contains an action (remove or add) and a value. The updates should adhere to the following specifications:
• If the first element of act is “remove" and the key is in the dictionary, then the matching value in the associated list should be removed.
• If the matching value happens to be the last element in the associated list, then the key should remain in the dictionary, but the associated list becomes empty. If the value is not in the dictionary, the dictionary does not change.
• If the value of act is "add" and the key is in the dictionary, then the new value
should be added to the associated list in the dictionary if it does not already exist. If the value already exists in the associated list, the updated dictionary would not change.
• If the value of act is “add" and the key does not exist in the dictionary, then a
new association list entry for the key should be added to the dictionary.
For example:
(define dict1 (list (list "Num" (list 5 1.3 -1))
(list "Char" (list #\p))
(list "Str"
(list "cs" "CS" "Computer Science"))))
Then
(update dict1 (list "add" true)) =>
(list (list "Num" (list 5 1.3 -1))
(list "Bool" (list true))
(list "Char" (list #\p))
(list "Str" (list "cs" "CS" "Computer Science")))
(update dict1 (list "remove" "cs")) =>
(list (list "Num" (list 5 1.3 -1))
(list "Char" (list #\p))
(list "Str" (list "CS" "Computer Science")))
I could only come up with the first step, below is what I have so far:
(define (update dict1 act)
(cond
[(equal? (first act) "remove") (remove-value dict1 (second act))]
[(equal? (first act) "add") (add-value dict1 (second act))]))
For this question I'm only allowed to use member? or remove.
I knew that I've been asking a lot of questions in the past couple of days, but I am new to racket and I am doing my best to learn it :( Please help
no set! no local version
; please tell us which language you use (in front of code)
#|
In Beginning Student Language variabe can't be function
error: function call: expected a function after the open parenthesis, but found a variable
(define (f fn) (fn 1))
(f add1)
|#
; use "Advanced Student" language or "#lang racket".
#lang racket
(define dict1
(list (list "Num" (list 1 2 3))
(list "Char" (list #\p))
(list "Bool" '())
(list "Str" (list "a" "b" "c"))))
(define (index-title action)
(cond
[(number? (second action)) 0]
[(char? (second action)) 1]
[(boolean? (second action)) 2]
[(string? (second action)) 3]
[else (error "type error")]))
(define (my-remove word lst)
(cond
[(empty? lst) empty]
[(equal? word (first lst))
(rest lst)]
[else
(cons (first lst)
(my-remove word (rest lst)))]))
(define (exist? word lst)
(cond
[(empty? lst) #f]
[(equal? word (first lst)) #t]
[else
(exist? word (rest lst))]))
(define (add-if-not-exist word data)
(if (exist? word data)
data
(cons word data)))
(define (action-to-data word data action)
(cond
[(equal? action "add")
(add-if-not-exist word data)]
[(equal? action "remove")
(my-remove word data)]))
(define (aux-build-list i n dict act a-function)
(cond
[(= i n) empty]
[else
(cons (a-function i dict act)
(aux-build-list (+ i 1) n dict act a-function))]))
(define (my-build-list n dict act a-function)
(aux-build-list 0 n dict act a-function))
(define (build-new-sub-dict n dict act)
(cond
[(= n (index-title act))
(list (first (list-ref dict n))
(action-to-data (second act) (second (my-list-ref dict n)) (first act)))]
[else
(list-ref dict n)]))
(define (my-list-ref lst n)
(cond
[(< n 0) (error "error")]
[(= n 0) (first lst)]
[else
(my-list-ref (rest lst) (- n 1))]))
(define (update dict act)
(set! dict1
(my-build-list (length dict)
dict
act
(lambda (n dict act) (build-new-sub-dict n dict act)))))
;;; Test
(update dict1 '("add" 2))
(update dict1 '("remove" 3))
(update dict1 '("add" 4))
(update dict1 '("add" 4))
(update dict1 '("remove" 1))
(update dict1 '("remove" 2))
dict1

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.

Can I divide list into multiple parts in BSL?

I have the list of values and want to take first x values from it and create (list (listof first x values) (listof next x values) and so on until this list gets empty...).
For example, given this list: (list "a" "b" "c" "d" "e" "f" "g" "h" "t")
return this: (list (list a" "b" "c") (list "d" "e" "f") (list "g" "h" "t"))
Thanks in advance :)
Remember what a datatype for a list is. Your class is probably doing something like:
;; A IntegerList is one of:
;; - '()
;; - (cons Integer IntegerList)
Given that, your template should reflect this structure. I will solve the base case (where we want to turn a list of integers into lists of one integers.
First I will define a 1List datatype as:
;; a 1List is:
;; - (cons Integer '())
Next, the purpose statement and signature for the function will be:
;; Takes a list of integers and returns a list of 1Lists of the same integers
;; IntegerList -> 1List
(define (make-1list lst)
...)
Okay cool. Now we need test cases:
(check-expect (make-1list (list 1 2 3)) (list (list 1) (list 2) (list 3)))
(check-expect (make-1list (list)) (list))
(check-expect (make-1list (list 42)) (list (list 42)))
Finally, I can make my template:
(define (make-1list lst)
(cond [(null? lst) ...]
[else ... (first lst) ... (rest lst) ...]))
(Note that it sometimes makes sense to make some of the template first, to help you guide what tests you need.)
Finally, we can fill in our code:
(define (make-1list lst)
(cond [(null? lst) '()]
[else (cons (list (first lst)) (make-1list (rest lst)))]))
And finally, are examples are also tests so we just need to run them to make sure everything works.
Now, since you want to make 3Lists instead of 1Lists, do you see how you can follow this recipe to solve the problem?
Write down your data definition.
Make your purpose statement and signature.
Make your examples.
Make your template.
Write the actual function.
Turn your existing examples into tests.
Following this pattern should help you break the problem down into smaller steps. Good luck.
Better way to accomplish this task is to use accumulators & recursion.

Get cdr of an elt in a list

I use 2 methods to build a tree based on cons cells.
(defun make-tree (nodes)
(cons nodes NIL))
(defun add-child (tree child)
(setf (cdr tree) (append (cdr tree) child)))
Then I created 4 parameters:
(defparameter *root* (make-tree "root"))
(defparameter *a* (make-tree "a"))
(defparameter *b* (make-tree "b"))
(defparameter *c* (make-tree "c"))
And I construct the following tree:
(add-child *root* *a*)
(add-child *root* *b*)
(add-child *a* *c*)
The *root* is displayed in the console:
CL-USER> *root*
("root" "a" "b")
My question is: Is it possible to retrieve c from *root*? Something like: (cdr (car (cdr *root*))) returns an error.
You need to use NCONC rather than APPEND in ADD-CHILD, so you don't make copies of the subtrees.
(defun add-child (tree child)
(setf (cdr tree) (append (cdr tree) child)))
With this change, after I do all the other steps, I get:
> *root*
("root" "a" "b" "c")
> (car (cdr (cdr (cdr *root*))))
"c"
> (cadddr *root*)
"c"