I have:
(defun getTotalValue(pack)
(cond ((null pack) 0)
(t (+ (car (car pack)))) (getTotalValue (cdr pack))
)
)
Which, to my understanding, will add up all the first elements of the items in a list. A test function call would be:
(getTotalValue '((10 c u) (3 s u) (5 h d) (7 s d) (12 h u)))
However, when I run the code above, it only prints out the first element of the first item in the list, 10. Why won't it add up the first elements of all the items?
You had parenthesizing problem -- two misplaced close parenthesis after (car (car pack)), so the cond expression terminates there and the recursion happens but the result is thrown away.
(defun getTotalValue (pack)
(cond ((null pack) 0)
(t (+ (car (car pack)) (getTotalValue (cdr pack))))))
Related
I'm working through a textbook on programming languages, and one of the exercises was to make a function in Scheme that flips tuples in a list. Here's my code:
; invert : Listof(List(Int,Int)) -> Listof(List(Int,int))
; usage: (invert '((a 1) (a 2) (1 b) (2 b))) -> ((1 a) (2 a) (b 1) (b 2))
(define invert
(lambda (lst)
(if (null? lst)
'()
(cons
(flip (car lst))
(invert (cdr lst))))))
; flip : List(Int,Int) -> List(Int,int)
; usage: (flip '(a 1)) -> (1 a)
(define flip
(lambda (tuple)
(if (not (eqv? (length (tuple)) 2))
(eopl:error 'flip
"Tuple is not length 2~%")
(cons (cdr tuple) (car tuple)))))
I tried testing my program in chez-scheme. When I use the test case in the usage comment, I get this error: Exception: attempt to apply non-procedure (a 1). I've never worked with Scheme before, so I'd greatly appreciate any help and advice. Thanks!
You have a coupe of errors in flip, this should fix them:
(define flip
(lambda (tuple)
(if (not (= (length tuple) 2))
(eopl:error 'flip "Tuple is not length 2~%")
(list (cadr tuple) (car tuple)))))
In particular:
The specific error reported was because of this expression: (tuple). We must not surround variables with (), unless they're procedures that we intend to call.
We should use = for comparing numbers, not eqv?.
In this expression: (cons (cdr tuple) (car tuple)) there are two issues, for building a list of two elements we use list, not cons. And for accessing the second element we use cadr, not cdr - you should read a bit about how cons, car and cdr are used for building lists.
Notice that there's a simpler way to solve this problem if we use map; I'll skip error checking for simplicity:
(define (invert lst)
(map (lambda (tuple) (list (cadr tuple) (car tuple)))
lst))
The problem is to:
Write a function (encode L) that takes a list of atoms L and run-length encodes the list such that the output is a list of pairs of the form (value length) where the first element is a value and the second is the number of times that value occurs in the list being encoded.
For example:
(encode '(1 1 2 4 4 8 8 8)) ---> '((1 2) (2 1) (4 2) (8 3))
This is the code I have so far:
(define (encode lst)
(cond
((null? lst) '())
(else ((append (list (car lst) (count lst 1))
(encode (cdr lst)))))))
(define (count lst n)
(cond
((null? lst) n)
((equal? (car lst) (car (cdr lst)))
(count (cdr lst) (+ n 1)))
(else (n)))))
So I know this won't work because I can't really think of a way to count the number of a specific atom in a list effectively as I would iterate down the list. Also, Saving the previous (value length) pair before moving on to counting the next unique atom in the list. Basically, my main problem is coming up with a way to keep a count of the amount of atoms I see in the list to create my (value length) pairs.
You need a helper function that has the count as additional argument. You check the first two elements against each other and recurse by increasing the count on the rest if it's a match or by consing a match and resetting count to 1 in the recursive call.
Here is a sketch where you need to implement the <??> parts:
(define (encode lst)
(define (helper lst count)
(cond ((null? lst) <??>)
((null? (cdr lst)) <??>))
((equal? (car lst) (cadr lst)) <??>)
(else (helper <??> <??>))))
(helper lst 1))
;; tests
(encode '()) ; ==> ()
(encode '(1)) ; ==> ((1 1))
(encode '(1 1)) ; ==> ((1 2))
(encode '(1 2 2 3 3 3 3)) ; ==> ((1 1) (2 2) (3 4))
Using a named let expression
This technique of using a recursive helper procedure with state variables is so common in Scheme that there's a special let form which allows you to express the pattern a bit nicer
(define (encode lst)
(let helper ((lst lst) (count 1))
(cond ((null? lst) <??>)
((null? (cdr lst)) <??>))
((equal? (car lst) (cadr lst)) <??>)
(else (helper <??> <??>)))))
Comments on the code in your question: It has excess parentheses..
((append ....)) means call (append ....) then call that result as if it is a function. Since append makes lists that will fail miserably like ERROR: application: expected a function, got a list.
(n) means call n as a function.. Remember + is just a variable, like n. No difference between function and other values in Scheme and when you put an expression like (if (< v 3) + -) it needs to evaluate to a function if you wrap it with parentheses to call it ((if (< v 3) + -) 5 3); ==> 8 or 2
I am totally new to Lisp.
How to find the difference between elements in an arithmetic progression series?
e.g.
(counted-by-N '(20 10 0))
Return -10
(counted-by-N '(20 10 5))
(counted-by-N '(2))
(counted-by-N '())
Returns Nil
In Python/C and other languages, it is very straightforward... Kinda stuck here in Lisp.
My pseudo algorithm would be something like this:
function counted-by-N(L):
if len(L) <= 1:
return Nil
else:
diff = L[second] - L[first]
for (i = second; i < len(L) - 1; i++):
if L[i+1] - L[i] != diff
return Nil
return diff
Current work:
(defun count-by-N (L)
(if (<= (length L) 1) Nil
(
(defvar diff (- (second L) (first L)))
; How to do the loop part?
))
)
(flet ((by-n (list &aux
(e1 (first list))
(e2 (second list))
(difference (and e1 e2 (- e2 e1))))
(and difference
(loop for (one two) on list
while (and one two)
when (/= (- two one) difference)
do (return-from by-n nil)))
difference))
(by-n '(20 10 0)))
or
(flet ((by-n (list &aux
(e1 (first list))
(e2 (second list))
(difference (and e1 e2 (- e2 e1))))
(when difference
(loop for (one two) on list
while (and one two)
when (/= (- two one) difference)
do (return-from by-n nil))
difference)))
(by-n '(20 10 0)))
As far as you said on the second answer the best choice you have to do this example is implement it recursively.
Example Using List Processing (good manners)
That way, you have some ways to do this example on the recursively and simple way:
(defun count-by-N-1 (lst)
(if (equal NIL lst)
NIL
(- (car (cdr lst)) (car lst))
)
(count-by-N-1 (cdr lst))
)
On this first approach of the function count-by-N-1 I am using the simple car and cdr instructions to simplify the basics of Common Lisp List transformations.
Example Using List Processing Shortcuts (best implementation)
However you can resume by using some shortcuts of the car and cdr instructions like when you want to do a a car of a cdr, like I did on this example:
(defun count-by-N-2 (lst)
(if (equal NIL lst)
NIL
(- (cadr lst) (car lst))
)
(count-by-N-2 (cdr lst))
)
If you have some problems to understand this kind of questions using basic instructions of Common Lisp List transformation as well as car and cdr, you still can choose the first, second and rest approach. However I recommend you to see some of this basic instructions first:
http://www.gigamonkeys.com/book/they-called-it-lisp-for-a-reason-list-processing.html
Example Using Accessors (best for understand)
(defun count-by-N-3 (lst)
(if (equal NIL lst)
NIL
(- (first (rest lst)) (first lst))
)
(count-by-N-3 (rest lst))
)
This last one, the one that I will explain more clearly since it is the most understandable, you will do a recursion list manipulation (as in the others examples), and like the others, until the list is not NIL it will get the first element of the rest of the list and subtract the first element of the same list. The program will do this for every element till the list is "clean". And at last returns the list with the subtracted values.
That way if you read and study the similarities between using first, second and rest approach against using car and cdr, you easily will understand the both two first examples that I did put here.
Here is my final answer of this question which uses recursion:
(defun diff (N)
(- (second N) (first N))
)
(defun count-by-N (L)
(cond
((null L) nil)
((= (length L) 1) nil)
((= (length L) 2) (diff L))
((= (diff L) (diff (rest L))) (count-by-N (rest L)))
(T nil)
)
)
I am trying to find the mode of a list
Assuming the list is sorted ascending order
Here is my mode function
(define freq
(lambda (l)
(cond ((null? l)l)
((null? (cdr l))l)
((not(equal? (car l) (car(cdr l))))(freq(cdr(delete l (car l)))))
(else (freq (cdr l)))
)))
(freq '(4 4 4 4 5 7 9 9 9)) => should returns 4 but its returning 9 instead
Here's my solution, which is similar to Óscar's solution but centralises the update of the longest/winning result in one place:
(define (longest-run lst)
(let loop ((result #f)
(cur #f)
(count 0)
(longest 0)
(lst lst))
(cond ((> count longest)
(loop cur cur count count lst))
((null? lst) result)
((eqv? (car lst) cur)
(loop result cur (+ count 1) longest (cdr lst)))
(else
(loop result (car lst) 1 longest (cdr lst))))))
I think my solution is shorter, cleaner, and less repetitive, but Óscar's solution has the advantage of updating the variables fewer times: his solution only updates the variables at the end of a run, whereas mine updates the variables whenever the current length is longer than the longest length seen so far.
What's the logic behind your procedure? how do you expect it to find the mode by removing elements from the input list? you should be counting frequencies instead:
(define (mode lst)
(if (null? lst)
#f ; edge case: an empty list doesn't have a mode
(let loop ((lst lst) ; list to traverse
(current (car lst)) ; current element in sequence
(counter 0) ; number of times current element appears
(max-current (car lst)) ; the mode
(max-counter 0)) ; number of times the mode appears
(cond ((null? lst) ; the list is finished
(if (> counter max-counter) current max-current))
((= (car lst) current) ; current element equal to previous
(loop (cdr lst) ; add 1 to counter and keep iterating
current
(add1 counter)
max-current
max-counter))
(else ; found a different element, a new sequence starts
(loop (cdr lst)
(car lst) ; update current element
1
(if (> counter max-counter) current max-current)
(max counter max-counter)))))))
It works by keeping track of how many times each element appears, returning the element that appears most frequently - because by definition the mode is the value that appears most often in a set of data. We take advantage of the fact that the input list is sorted, because we know that a new sequence of repeated elements starts when the current element is different from the previous one we encountered.
So, I'm trying to add up the sublists of a list. Like, if I have something like this:
(add-pair '((1 4) (2 1)))
I want it to return this:
(5 3)
This is what I have so far:
(define pair-additions
(lambda (ls)
(map
(lambda (n)
(+ (car n) (cdr n)))ls)))
Right now, it's giving me an error saying that the input isn't a number. Can anybody help me out?
You almost got it! here is the problem:
(+ (car n) (cdr n))
For retrieving the second element of a list, you have to take the car of the cdr, not just the cdr. Change the above line for this:
(+ (car n) (car (cdr n)))
Or for this, which is a short form of the previous line:
(+ (car n) (cadr n))
Or for this, which is easier to read (if supported by your Scheme interpreter):
(+ (first n) (second n))
All the above are equivalent.