A funtion which takes a list and add their position in racket programming - racket

I want to write a function that takes as input a list of elements and returns a list with elements and their position after. For example, if the input to the function is (list x y z ) then it will return (list x 1 y 2 z 3). I wrote code which can reverse first two items, but I can't handle this one, can anybody help?

The following is an implementation using a recursive helper function. I think the code is self-explanatory.
(define (index-list-rec lst start)
(if (empty? lst) empty
(cons (first lst) (cons start (index-list-rec (rest lst) (add1 start))))))
(define (index-list lst) (index-list-rec lst 1))

Related

>: expects a real, given (void)

I am currently struggling with creating a list that finds if all the numbers within the list are equal to each other:
(define (list-all-equal lon) (cond [(empty? lon) lon]
[(empty? (rest lon)) (first lon)]
[(empty? (rest (rest lon))) (first lon)]
[(equal? (first lon) (list-all-equal(rest lon))) (write #true)]
[(> (first lon) (list-all-equal(rest lon))) (write #false)]
[(< (first lon) (list-all-equal(rest lon))) (write #false)]
[else (list-all-equal (rest lon))]))
However, I keep on receiving the error: >: expects a real, given void. is there a way to solve the error?
write does not return a value, so when you compare to the recursive result you're going to end up comparing to "nothing".
Also, your function should return #true or #false, not list elements, and comparing list elements to the results of recursing does not make much sense.
I think you started writing code before solving the problem.
A helpful way to start is with listing the possibilities.
All elements of an empty list are equal
All elements of a singleton list are equal
If the list has at least two elements, and the first element is equal to the second element, all the elements are equal if and only if all elements in its tail are equal
Otherwise, there is at least one unequal element
Translated:
(define (list-all-equal lon)
(cond [(empty? lon) #true]
[(empty? (rest lon)) #true]
[(equal? (first lon) (second lon)) (list-all-equal (rest lon))]
[else #false]))
The problem is that you're calling write as part of the recursion, and write "returns" void, which will lead to something like this:
(> some-number (void))
Never use write to return a value from your procedures! We want to return the results, not to display them on the console. And for this case you have to implement your procedure in such a way that, if it finds a different number, it stops comparing - the result is false and we shouldn't continue. A good strategy would be to pass along the first element and compare the rest against it:
(define (list-all-equal lst)
(if (empty? lst)
#t
(list-all-equal-helper (first lst) (rest lst))))
(define (list-all-equal-helper ele lst)
(cond ((empty? lst) #t)
((not (= (first lst) ele)) #f)
(else (list-all-equal-helper ele (rest lst)))))
Or, we could use apply :)
(define (list-all-equal lst)
(apply = lst))
Either way, it works as expected:
(list-all-equal '(1 2 3))
=> #f
(list-all-equal '(1 1 1))
=> #t

Common Lisp - Function which return an element appears n times in a list

I'm trying to write a function which return an element appears n times in a list.
For example, for a list like : (setq lst '(a b b b c)), the function returns :
count-list (lst 3) --> b
But when there is two element (or more) which appears in n same time, the function only returns the first element :
count-list (lst 1) --> a
Instead of
count-list (lst 1) --> a b
Here is the function :
(defun count-list (lst nb)
(loop for x in lst do
(if (eq (count x lst) nb)
(return x)
)
)
)
What did I miss ?
return tells the count-list function to exit immediately as soon as it finds a hit, so it won't look for other elements matching the count.
One possible solution is this:
(defun count-list (lst n)
(remove-duplicates
(mapcan #'(lambda (x)
(when (eql (count x lst) n)
(list x) ))
lst )))
However, this is very inefficient since for each item the list has to be traversed twice, one for the function itself and one for count, so this would take a time proportional to the square of the length of the list.
A more efficient way would be to accumulate the values (e.g. in an assoc list) and select at the end those items matching the input count number.
(defun count-list (lst n)
(let* (count-list pair)
(dolist (x lst)
(if (setq pair (assoc x count-list))
(incf (cdr pair))
(push (cons x 1) count-list) ))
(mapcan #'(lambda (pair)
(when (eql n (cdr pair))
(list (car pair)) ))
count-list )))
I never used LISP. I assume your problem is that your function returns at the first match. Either create an array in your function for storing all the elements appearing n times and return to that array, or, for example, in Python I would use print(x) so the function does not return at the first match, like in your case.

How can I use more than "return" statement in the following piece of code?

In my else condition I have two statements to execute. The first one ought to append my calculation to my return-list and the second one calls my recursive procedure again.
The problem is that my append procedure is being ignored so I am just returning an empty list.
(define (calcit x lst)
(cond ((= x 0)
retlst)
(else (append (list (floor (/ x (first lst)))) retlst)
(calcit (modulo x (first lst)) (rest lst)))))
You need to do something with the data you are creating. You probably want to have the first element consed on the result of the list you get from the recursion:
(define (calcit x lst)
(if (= x 0)
'() ;; base case
(cons (floor (/ x (first lst)))
(calcit (modulo x (first lst)) (rest lst)))))
When creating lists in Scheme with recursion try to avoid append. Using append is an anti pattern. Learn how Scheme lists work and train to know it intimately. eg '((2 3) (4 5)) if I ask you how to get 5 from that you should think d a d a and answer cadadr almost right away.

How to use foldr in Racket to eliminate numbers in a list that are greater than any subsequent numbers

I have to write a function in Racket using foldr that will take a list of numbers and remove list elements that are larger than any subsequent numbers.
Example: (eliminate-larger (list 1 2 3 5 4)) should produce (1 2 3 4)
I can do it without using foldr or any higher-order functions but I can't figure it out with foldr. Here's what I have:
(define (eliminate-larger lst)
(filter (lambda (z) (not(equal? z null)))
(foldr (lambda (x y)
(cons (determine-larger x (rest lst)) y)) null lst))
)
(define (determine-larger value lst)
(if (equal? (filter (lambda (x) (>= x value)) lst) lst)
value
null)
)
determine-larger will take in a value and a list and return that value if it is greater than or equal to all elements in the list. If not, it returns null. Now the eliminate-larger function is trying to go through the list and pass each value to determine-larger along with a list of every number after it. If it is a "good" value it will be returned and put in the list, if it's not a null is put in the list. Then at the end the nulls are being filtered out. My problem is getting the list of numbers that follow after the current number in the foldr function. Using "rest lst" doesn't work since it's not being done recursively like that. How do I get the rest of the numbers after x in foldr?
I really hope I'm not doing your homework for you, but here goes ...
How do I get the rest of the numbers after x in foldr?
Because you're consuming the list from the right, you can structure your accumulator such that "the rest of the numbers after x" are available as its memo argument.
(define (eliminate-larger lst)
(foldr
(lambda (member memo)
(if (andmap (lambda (n) (<= member n)) memo)
(cons member memo)
memo))
'()
lst))
(eliminate-larger (list 1 2 3 5 4)) ;; (1 2 3 4)
This is admittedly a naive solution, as you're forced to traverse the entire accumulator with each iteration, but you could easily maintain a max value, in addition to your memo, and compare against that each time through.
Following works:
(define (el lst)
(define (inner x lsti)
(if(empty? lsti) (list x)
(if(<= x (apply max lsti))
(cons x lsti)
lsti)))
(foldr inner '() lst))
(el (list 1 2 3 5 4))
Output:
'(1 2 3 4)
The cond version may be preferable:
(define (el lst)
(define (inner x lsti)
(cond
[(empty? lsti) (list x)]
[(<= x (apply max lsti)) (cons x lsti)]
[else lsti] ))
(foldr inner '() lst) )

looping through two lists while updating one of the lists

I have two lists as follows:
(x y z) & (2 1)
and I want to have a result like:
((x y) (z))
The relation of the lists is quite clear. So basically I want to rearrange the members of the first list into a list of lists with two (length of second list) lists.
I have tried running two dotimes iterations to do this:
(let ((result) (list1* list1))
(dotimes (n (length list2) result)
(progn (setq result
(append result
(list (let ((result2))
(dotimes (m (nth n list2) result2)
(setq result2
(append result2
(list (nth m list1*)))))))))
(setq list1*
(subseq list1* 0 (nth n list2))))))
The idea is that I make the first list of the expected result (x y), and then I want to update the (x y z) list so that the x any y are removed and I only have (z). Then the loop runs again to get the (z) list in the expected result. This does not work correctly and results in:
((x y) (x))
which means apparently the second command for progn which is basically updating the list1* is not working. Clearly there must be a correct and better way of doing this and I was wondering whether anyone can help with this. Also explain why it is not possible to have the solution explained?
If I see that right, your problem is in (subseq list1* 0 (nth n list2)), which returns the part of the list that you do not want.
I have the following to offer:
(defun partition-list (list lengths)
(mapcar (lambda (length)
(loop :repeat length
:collect (pop list)))
lengths))
This is a bit simplistic, of course, as it does not handle unexpected input, such as (length list) being smaller than (reduce #'+ lengths), but it can be expanded upon.
Just for the sake of example, an alternative using iterate:
(defun partition-list (list by)
(iter:iter
(iter:for element in list)
(iter:for i from 1)
(iter:generating measure in by)
(iter:collect element into sublist)
(when (= (or measure (iter:next measure)) i)
(iter:collect sublist)
(iter:next measure)
(setf i 0 sublist nil))))