I want to insert an element next to the last element of the list, but I only know how to insert an element next to the first element of the list, can someone help me further?
Example : (insert '5 '(1 3 2 7 8 9)) should output => (1 3 2 7 8 5 9)
(defun insert (item list)
(cons (first list)
(cons item
(rest list))))
//when I do (insert '5 '(1 3 2 7 8 9)) I get (1 5 3 2 7 8 9)
Lists are singly linked lists so only add to the front is possible without having to copy parts of the list. your attempt makes a copy of the first pair, the add your pair as the second element then share the rest of the original list with the argument.
In order to add as the last element you need to do this until list is empty and then return a list with the one element. None of the cons will be in common. So:
(insert 'x '()) ; ==> (list 'x)
(insert 'x '(1)) ; ==> (cons '1 (insert 'x (cdr '(1))))
Of course this can be done with append. Laziness is rewarded in programming:
(defun insert-last (item list)
(append list (list item)))
Know that if you have a recursive function or an iteration where you add like this for many elements depending on the arguments you are making a very bad algorithm. It is much better to either use loop to collect to the end or to make the list backwards and in the last step reverse it. Then you'll get n or 2n passes through the data instead of n^2.
Related
I am writing a function using recursion that is supposed to add the alternating values in a list. It's relatively simple to just write some code to add all the values in the list but I am struggling to only add the alternating values in the list. If possible I would strongly prefer the code written using recursion over higher-order functions for this problem.
My only guess for this problem is to manipulate the length of the list to only add the alternating values of the list or to possibly find a way to only add the odd elements in the list but I have no clue if this is even possible and if it was even possible i would have no clue where to even begin.
This is my code so far
(define (skip-sum L)
(cond
[(empty? L) 0]
[else (+ (first L) (skip-sum (rest L)))]))
This is what the results should look like. As you can see only the odd elements in the lists were summed showing only alternating values in the list were added.
(check-expect (skip-sum (list 4 6 8)) 12)
(check-expect (skip-sum (list 1 3 5 7 9 11)) 15)
(check-expect (skip-sum (list 2 10 4 12 6 14 8 12 10))30)
For instance for the second example the alternating values which were added are 1+5+9=15.
Here is a possibile recursive definition:
(define (skip-sum l)
(cond ((empty? l) 0)
((empty? (cdr l)) (car l))
(else (+ (car l) (skip-sum (cddr l))))))
Note that there are two cases to end the recursion: when the list is empty, or has only one element.
In the recursive case we simply sum the first element of the list with the result of calling the function on the list starting from the third one (and so ignoring the second one). In this way we skip every even element and obtain the correct sum.
I want to make sublists of a given list when my first number is lower than my next number. I already wrote something but it's not working, it says 'NIL ist not a real number' I hope someone can help me further
(defun order(lst)
(cond ((null lst) nil)
(t (if (< (car lst) (cadr lst))
(cons (car lst) (cadr lst))) (order (rest lst)))))
(print(order '(1 4 5 12 22 34 7 9 0)))
//Output should be this -->((1 4 5) (12 22 34) (7 9) (0))
Since this seems like homework just some pointers:
Right now you are only forming a new list with cons that is exactly two long. Think about how you want the recursion to go to either extend this new list if necessary or include new elements before "closing" it.
You don't call any further recursion when you find a sorted pair. Your code just ends.
If the two compared elements are NOT sorted you do nothing with the old head, you just drop it. Overall there is no "outer" list generated in the course of your algorithm.
Right now cadr might run into the end of the list. So < will be called on a number and nil which leads to disaster.
I am new to Scheme and not currently using (Racket version), therefore I do not have such built in functions as filter and etc.
My task for now is to get elements out of my inputted list, and take out of it only those that are above my MinValue and below my MaxValue
In my "lst" variable for example I have (2 4 1 6 5 4 7 3)
In my "MinValue" I have 2
In my MaxValue I have 5
So that now after I apply something similar like
(remove (< # minVal) lst)
It technically should give remove and left out:
(2 4 4 3)
But I am getting the error:
READ from #<INPUT CONCATENATED-STREAM #<INPUT STRING-INPUT-STREAM> #<IO TERMINAL-STREAM>>: objects printed as # in view of *PRINT-LEVEL* cannot be read back in
Main questions:
Does Scheme has a specific defined variable like # that is iterating through the list when remove/remove-if functions are used, so I can use it?
Is there is a way to get this to work in such way:
(remove (< # minVal) lst)
Thanks!
tag "homework" should be there, but I cannot create it yet
Almost any Scheme I know of includes a filter procedure, it's not specific to Racket, you should be able to use it (remove is not the right tool for this job).
Simply pass a lambda that receives each element in turn and you can set any condition for determining which elements go in the output list:
(filter (lambda (e) (and (>= e 2) (< e 5)))
'(2 4 1 6 5 4 7 3))
=> '(2 4 4 3)
There is no # variable that iterates through a list and gives you each element in turn, to do that you have to explicitly traverse the list using recursion, or use one of the built-in procedures that expect a list and a lambda - the lambda's parameter represents each of the elements.
If for some reason you are not allowed to use filter, it's easy to implement it from scratch, and again notice that we don't need to use remove, and that pred gets called with each of the elements:
(define (filter pred lst)
(cond ((null? lst) '())
((pred (car lst))
(cons (car lst) (filter pred (cdr lst))))
(else (filter pred (cdr lst)))))
I have been trying to understand how to use loops in LISP and they still don't really seem to work correctly. I tried using the following code:
(loop for i from 0 to (list-length y)
(when (eq (values-list (nth i (car y))) 0)
(return-from checkZero t)))
Which should loop through my list checking if my value is equal to 0 or not. If it is equal then it should return from and exit the loop, otherwise it should run until it reaches the list length. Am I thinking about this wrong and if so how do I go about fixing this loop?
(I'm not sure if my actual code works or not yet since I am still dealing with the errors generated by the incorrectly used loop and I can't find many good resources for using loops online)
The main problem in the loop is the WHEN-expression. There are two ways you can write that:
Use the loop WHEN condition DO forms-clause:
(loop for...
when (eq ...) do (return-from ...))
Use the regular WHEN-macro inside a loop DO-clause:
(loop for...
do (when (eq ...)
(return-from ...)))
There are a few other things to fix in your code.
When naming things in Lisp, use dashes between words rather than camelCase (check-zero rather than checkZero).
Use = for general numeric comparison, or ZEROP to check that a number is zero. EQ is used to check if two objects are the same object.
You can return from a loop using RETURN
I'm not quite sure what you're trying to accomplish with the (VALUES-LIST (NTH ... (CAR ...))), but it's not going to work. If you're trying to simply loop over a flat list of values (such as (1 2 3 4 5 6)), you should be using the loop FOR item IN list-clause.
So now you should have something like:
(defun check-zero (list)
(loop for item in list
when (zerop item) do (return t)))
LOOP also has a THEREIS condition-clause that you could use:
(defun check-zero (list)
(loop for item in list
thereis (zerop item)))
This return as soon as it finds an item that satisfies ZEROP. However, there are easier ways to achieve the same. You could use MEMBER to check if the list contains a zero:
(defun check-zero (list)
(member 0 list :test #'=))
CL-USER> (check-zero '(1 3 4 3 5 7))
NIL
CL-USER> (check-zero '(1 3 4 3 0 5 7))
(0 5 7)
This returns a generalized boolean. That is, any value that is not NIL is considered true in Common Lisp.
Since there is a predicate function (ZEROP) to check if an object is a zero, you could also use SOME or MEMBER-IF for this:
(some #'zerop '(1 3 4 6 2 0 45 6 7)) ;=> T
(member-if #'zerop '(1 3 4 6 2 0 45 6 7)) ;=> (0 45 6 7)
I need some help understanding the syntax on how to append a number into a list, i'm doing this from user input via the console so this elements have to be entered in recursively. So for ever number that is entered, the list must grow for each element (only numbers) added.
Here is the code I am working with, the problem lies in the second conditional. Right now this works but only creates an empty list of each number I put in, so the results would be
>12
>202
>30
()()()
zero input: stopping list
(define (inputlist)
(let ((applist list))
(let ((inpt (read)))
(cond
((= inpt 0)(newline) (display "zero input: stopping list"))
;;OLD((number? inpt) (cons inpt applist) (display (applist))(inputlist))
((number? inpt) (append (applist)(list inpt)) (display (applist))(inputlist))
(else
display "Not a number")))))
I understand why cons is not doing what I need it to be doing, but is there a similar functionality to appending each read in element to a pre-existing list?
EDIT: I've gotten closer what i've needed to do but still with the same results, i am now appending upon my applist with a list i create via every input, though it is still resulting in as many empty lists as I input.
SECOND EDIT: I've realized why it's printing multiple ()'s is because it's being called off the stack when 0 is entered, so i'm sure it's not working because the appending isn't working as intended, i've displayed the applist on the 0 conditional and it returns one null list.
A simple way to append an element to the end of a list while looping would be to do call append and update the reference to the list afterwards:
(set! applist (append applist (list inpt)))
Notice that you have several misplaced parentheses - in your code some are missing, some are unnecessary. In Scheme () means function application, and you have to be careful where you put those brackets.
Also, be aware that append doesn't modify the initial list, it creates a new one, and if you need to refer to it, you have to store it somewhere (that's why I'm doing a set! above).
There are more serious errors with you logic. The conditions are in the wrong order (you have to test if the input is a number before asking if it's zero), and you forgot to loop if something other than a number is entered. Also, if we pass along the list as a parameter to the loop, we won't have to do an ugly set!. Try this instead, it's closer to what you were aiming for:
(define (inputlist)
(let loop ((applist '()))
(let ((inpt (read)))
(cond ((not (number? inpt))
(display "not a number")
(newline)
(loop applist))
((zero? inpt)
(display "zero input: stopping list"))
(else
(let ((new-applist (append applist (list inpt))))
(display new-applist)
(newline)
(loop new-applist)))))))
As mentioned in the comments, bear in mind that appending at the end of a list inside a loop in general is a bad idea. It's ok for learning purposes, but in real-life code, you'd cons at the head of the list and reverse it at the end - this is more efficient.
Note that (cons x xs) where x is an element and xs is a list produces a new list which has x as its first element.
Here is one way to use cons to add an element in the end of a list:
Example:
Add 4 to (1 2 3)
1. Reverse the list: (3 2 1)
2. Add 4 to the front: (4 3 2 1)
3. Reverse: (1 2 3 4)
> (reverse (cons 4 (reverse (list 1 2 3)))
(1 2 3 4)
A function that uses this principle:
(define (cons-to-back x xs)
(reverse (cons x (reverse xs))))
> (cons-to-back 4 (list 1 2 3))
(1 2 3 4)
An alternative is to use append which appends the elements of two lists:
> (append '(1 2 3) '(4 5 6))
(1 2 3 4 5 6)
All we need to do, is to the the element into a list before using append:
> (append '(1 2 3) (list 4))
'(1 2 3 4)
Alternative definition of cons-to-back:
(define (cons-to-back x xs)
(append xs (list x)))