Return the SUM of numeric elements in a nested list using LISP. If there are no numeric elements return an empty list/NIL
Examples:
(6 3 -2 5 (4 2 -3) 4) should return 19
(1 2 3 (-4 5) a b c) should return 7
Asking other people to do your homework for you is almost never a good way of learning anything.
But here's an answer, which is written in a Lisp (Racket) and which does show how you ought to go about solving this problem, and also (I think) demonstrates some nice ways of thinking about problems like this ... but which you almost certainly can't cut and paste.
Note that this does not quite agree with the requirements given: which is supposed to return a non-numeric value for a list with no numbers in it. That breaks a recursive algorithm like this, since the empty list is a list with no numbers in it. So this does something more sensible. Making this answer implement the requirements is left as an exercise to the student.
(define (sum-nested-list l)
(let sum-nested-list-loop ([thing l]
[running-total 0])
(match thing
['()
;; We're done if we've run out of list
running-total]
[(list* (? number? x) r)
;; A list whose first element is a number: add it to the running total
;; and carry on on the rest of the list
(sum-nested-list-loop r (+ running-total x))]
[(list* (? list? x) r)
;; A list whose first element is a nested list: recurse into the
;; nested list
(sum-nested-list-loop r (sum-nested-list-loop x running-total))]
[(list* _ r)
;; A list whose first element is not a number or a nested list:
;; carry on on the rest of the list
(sum-nested-list-loop r running-total)]
[_
;; Not a list at all: explode
(error 'sum-numeric-list "what?")])))
(defun flat-sum (tree)
(let ((count 0))
(tree-equal tree tree :test (lambda (left right)
(if (numberp left)
(incf count left) t)))
count))
1> (flat-sum '(1 2 3 (-4 5) a b c))
7
Related
Write a function to split a list into two lists. The length of the first part is specified by the caller.
I am new to Elm so I am not sure if my reasoning is correct. I think that I need to transform the input list in an array so I am able to slice it by the provided input number. I am struggling a bit with the syntax as well. Here is my code so far:
listSplit: List a -> Int -> List(List a)
listSplit inputList nr =
let myArray = Array.fromList inputList
in Array.slice 0 nr myArray
So I am thinking to return a list containing 2 lists(first one of the specified length), but I am stuck in the syntax. How can I fix this?
Alternative implementation:
split : Int -> List a -> (List a, List a)
split i xs =
(List.take i xs, List.drop i xs)
I'll venture a simple recursive definition, since a big part of learning functional programming is understanding recursion (which foldl is just an abstraction of):
split : Int -> List a -> (List a, List a)
split splitPoint inputList =
splitHelper splitPoint inputList []
{- We use a typical trick here, where we define a helper function
that requires some additional arguments. -}
splitHelper : Int -> List a -> List a -> (List a, List a)
splitHelper splitPoint inputList leftSplitList =
case inputList of
[] ->
-- This is a base case, we end here if we ran out of elements
(List.reverse leftSplitList, [])
head :: tail ->
if splitPoint > 0 then
-- This is the recursive case
-- Note the typical trick here: we are shuffling elements
-- from the input list and putting them onto the
-- leftSplitList.
-- This will reverse the list, so we need to reverse it back
-- in the base cases
splitHelper (splitPoint - 1) tail (head :: leftSplitList)
else
-- here we got to the split point,
-- so the rest of the list is the output
(List.reverse leftSplitList, inputList)
Use List.foldl
split : Int -> List a -> (List a, List a)
split i xs =
let
f : a -> (List a, List a) -> (List a, List a)
f x (p, q) =
if List.length p >= i then
(p, q++[x])
else
(p++[x], q)
in
List.foldl f ([], []) xs
When list p reaches the desired length, append element x to the second list q.
Append element x to list p otherwise.
Normally in Elm, you use List for a sequence of values. Array is used specifically for fast indexing access.
When dealing with lists in functional programming, try to think in terms of map, filter, and fold. They should be all you need.
To return a pair of something (e.g. two lists), use tuple. Elm supports tuples of up to three elements.
Additionally, there is a function splitAt in the List.Extra package that does exactly the same thing, although it is better to roll your own for the purpose of learning.
This question already has answers here:
Common lisp error: "should be lambda expression"
(4 answers)
Closed 5 years ago.
I'm trying to make a function that changes infix input to prefix eg : (x + 1) as input outputted as (+ x 1).
So here is my code for the moment :
(setq x '(Y + 1))
(if (listp x ) (list (second x) (first x) (first (last x))) x)
so it returns (+ Y 1) if I input a list and the user input if it's not a list.
However, the problem is that I can't get this code working in a function :
(defun prefixToInfix (x)(
(if (listp x ) (list (second x) (first x) (first (last x))) x)
)
)
the function is indeed created but when I call it
(prefixtoinfix '(Y + 1))
I get an error
Error: Illegal function object: (IF (LISTP X) (LIST # # #) X).
[condition type: TYPE-ERROR]
I don't know why my if statement works in the main program but doesn't when I run it from my function.
What you are missing is that in Lisp parentheses are meaningful.
In C/Java/Python &c, the following expressions are the same:
a+b
(a+b)
(a)+(b)
(((a)+(b)))
(((((a)+(b)))))
In Lisp, the following expressions are very different:
a --- a symbol
(a) --- a list with a single element, which is the symbol a
(1 (2)) --- a list of two elements:
number 1
list of of length 1, containing number 2
In your case, function (note indentation and paren placement!)
(defun prefixToInfix (x)
((if (listp x) (list (second x) (first x) (first (last x))) x)))
has extra parens around if (and this causes the whole if form to be interpreted as a function, with disastrous results), and should be (note line breaks and indentation - lispers do not count parens, they look at indentation to understand the code, see http://lisp-lang.org/style-guide/)
(defun prefix-to-infix (x)
(if (listp x)
(list (second x)
(first x)
(first (last x)))
x))
PS. See also recommendations in want to learn common lisp.
DrRacket user.
I'm struggling to understand how this program works.I wrote it myself and it does what it must but I can't understand how.
I define while loops as:
(define (while test body)
(if (test)
(begin
(body)
(while test body))
(void)))
Now I need to write a program that applies the given procedure to each element of a mutable list.
Here what I wrote:
(define (mlist-map-while f x)
(while (lambda() (not (null? x)))
(lambda ()
(set-mcar! x (f (mcar x)))
(set! x (mcdr x))))
(void))
So, defining
list1 (mlist 1 2 3)
and applying
(mlist-map-while (lambda (x) (+ x 1)) list1)
we get '(2 3 4).
The thing that I don't understand is how the first element of the list stays in it, because if it's done how I wrote here
(set! x (mcdr x))
the first procedure that sets -mcar! must be useless and be overlapped with the second. Like in this example:
(define list1 (mlist 1 2 3))
(set-mcar! list1 9)
(set-mcdr! list1 (mcdr list!))
and we lack the first element, but this program somehow leaves it in and gives the desired output. I would like to know how it works and whether there is another way of traversing the given list.
There is a big difference between set-cdr! abd set!. The first alters the pair's cdr pointer, while the latter alters the binding, thus what the name should point to.
In your mlist-map-while the variable x alters the car, then changes what x represents, to be the cdr of x. It never changes the cdr so your binding list1 always points to the first pair while x points to the first, then second, etc...
Thus it's more like this:
(define list1 (mlist 1 2 3))
(define list1-ref list1) ; variable pointing to the same value as list1
(set-mcar! list1-ref 9) ; set-car! changes the pair
(set! list1-ref (mcdr list)) ; set! updates what list1-ref points to
list1 ; ==> (9 2 3)
list-ref ; ==> (2 3)
You can iterate over a list in the same fashion without using set!, with recursion:
(define (fold function init lst)
(if (null? lst)
init
(fold function
(function (car lst) init)
(cdr lst))))
(fold + 0 '(1 2 3)
; ==> 6
(fold cons '() '(1 2 3))
; ==> (3 2 1)
Notice that here we recurse and change what lst is, to be the cdr. Every recursion has its own lst, which is not to be confused with the caller's own. It ends up doing the same as set! in your example, without mutation.
I am going over some racket exercises, and one of these exercises asks to create a function called "count-trees" that will count all the elements in a ListTree. Per the instructions, a ListTree is a recursive data structure with the following definition(s):
-It can be an integer
-It can be a list or a list with sublists
-Per the instructions, we assume that a list tree can never be empty
Here are a few examples of what a List Tree looks like:
(list 1 2)
(list (list 1)
2
(list 1 4 5))
(list 1
(list 2 1)
1
1)
Now, here is what my code looks like:
(define count-tree (lambda (lst)
(if (empty? lst)
0
(length (lst)))))
When I execute the function, it works but only when there is one list, not on lists that contain sub-lists. It seems to only count how many lists there are, but I want it to count all elements in the list. Is there a way to go about this? Thanks!
Length can be implemented like this:
(define length
(lambda (lst)
(if (empty? lst)
0
(+ 1 (length (cdr lst))))))
And thus:
(length '((1 2) (3 4)))
; ==> 2
Since the list has two elements. It doesn't bother it that the two elements are two lists that also has elements and your function needs to do that. Thus your function need to do one more thing than length does. You need to sum the recursion of the car and the cdr in the event you have a pair in the car, otherwise the same as length.
There are more clever versions of length but I guess you'll learn about that later.
(defun my_remove(e list1 list2)
(if (null list1)
nil
((setf x car(list1))
(if (!= x e)
((my_append e list2 )
(setf y cdr(list1))
(my_remove(e y list2)))
((setf y cdr(list1))
(my_remove(e y list2))
)))))
I am trying to write a function to remove an element from a list but i am getting an error that "It should be lambada function" and I don't know that my code is correct or wrong.
Problems with your code
There are a few problems with your code. First, let's look at it with standard indentation
(defun my_remove(e list1 list2)
(if (null list1)
nil
((setf x car(list1)) ; (i)
(if (!= x e)
((my_append e list2 ) ; (ii)
(setf y cdr(list1)) ; (iii)
(my_remove(e y list2))) ; (iv)
((setf y cdr(list1)) ; (v)
(my_remove(e y list2))))))) ; (vi)
Each of the marked lines has a problem. The syntax for a function call in Lisp is
(function argument…)
That means that in your line (i), you're trying to call a function named (setf x car(list1)) with an argument (if (!= x e) …). Of course, that's not the name of a function, and I suspect that even if it was, you didn't want to call it with the argument (if (!= x e) …). Similarly
(setf x car (list1))
Is trying to to set x to the value of the value of a variable car (and there isn't one), and then assign a new value to the place (list1). Since the syntax for a function call is (function argument…), you want instead:
(setf x (car list1))
If you're trying to sequence forms, you might consider using cond, in which you can provide multiple forms, or progn (see In Common Lisp, why do multi-expression bodies of (if) statements require (progn)?).
For instance, instead of
((my_append e list2 ) ; (ii)
(setf y cdr(list1)) ; (iii)
(my_remove(e y list2))) ; (iv)
you probably want
(progn
(my_append e list2 ) ; (ii)
(setf y cdr(list1)) ; (iii)
(my_remove(e y list2))) ; (iv)
You'll have some problems with that, too, though. In (iii) and (iv), you'll need to use (cdr list1) and (my_remove e y list2), as discussed above, but you also have the problem that you're evaluating (ii) and (iii), but you're discarding the value.
A simplified approach
I think it might be to your benefit if you think about a simple definition of my-remove. In general, a list is either the empty list () or a cons cell whose car is the first element of the list and whose cdr is the rest of the list. You can use a definition like this, then:
remove(x,list)
if list is empty, then return list (it's empty, so it certainly doesn't contain x)
if list is not empty, then
if the first element of the list is x, then return remove(x,rest(list))
else, the first element of the list is not x, so return a new list whose first element is the first element of list, and whose rest is remove(x,rest(list)).
In code, that looks like:
(defun my-remove (element list)
(if (endp list)
list
(if (eql element (first list))
(my-remove element (rest list))
(list* (first list)
(my-remove element (rest list))))))
CL-USER> (my-remove 1 '(1 2 3 1 2 3))
(2 3 2 3)
Those nested ifs look a bit ugly, and you might want to use cond here, even though you don't need the multiple expression bodies that it permits:
(defun my-remove (element list)
(cond
((endp list)
list)
((eql element (first list))
(my-remove element (rest list)))
(t
(list* (first list) (my-remove element (rest list))))))
Since a cond clause with no body whose test form evaluates to true returns the value of the test form, you can even make that last clause a bit simpler:
(defun my-remove (element list)
(cond
((endp list) list)
((eql element (first list)) (my-remove element (rest list)))
((list* (first list) (my-remove element (rest list))))))