Keeping track of global variables in recursive functions [closed] - lisp

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I've been struggling with this question for the past few hours, scoured the internet for help, and I still can't seem to figure it out.
The question is simple:
Write a recursive program (in lisp) that takes a list and returns the number of 'a atoms in the list.
From the research I've done, it seems like LISP has an implicit counter in it, where if you just do (+ 1) it will keep track? Is this off?
Please help, I'm pretty frustrated...

The idea here is not to use a global variable, but instead to keep the count "in the stack".
Here's a Scheme solution. I'm sure you'll be able to convert this to whatever Lisp dialect you're using:
(define (count-a lst)
(cond ((null? lst) 0)
((eq? (car lst) 'a) (+ (count-a (cdr lst)) 1))
(else (count-a (cdr lst)))))
If that's not DRY enough for you, here's a more condensed version:
(define (count-a lst)
(if (null? lst) 0
(+ (count-a (cdr lst)) (if (eq? (car lst) 'a) 1 0))))

You just need to have a counter carry along in a parameter. I haven't used LISP in forever but just a simple (+ counterName 1) as a parameter should keep track. Don't forget to throw it a starting value though.

Related

Abstracting Lists in Dr. Racket

Currently, I have a function item counts that is meant to count the number of elements in a string and order them into pairs if it occurs once or more.
(check-expect
(item-counts
(cons "hello"
(cons "hey"
(cons "hello" '())))
equal?)
(cons "hello" 2
(cons "hey" 1) '()))
(check-expect
(item-counts
(cons #true
(cons #false
(cons #true '())))
equal?)
(cons #true 2
(cons #false 1 '())))
(define (item-counts lop ef)
(cond
[(empty? (rest lop))
(first lop)]
[(cons? (rest lop))
(if
(ef (first lop) (item-counts (rest lop) ef))) ... ???
As shown by the tests, I wish to add a number to the existing list if one of the elements of this list occurs more than once. I used the equal? function to identify the number of times an element occurs, but I am lost on how to add the number to the existing list as well as condense the repeating elements when producing a new list. I have tried using the append function but it creates a list in a different format ( (list (list) ).
I don't know if this is self-learning, for a class, etc. I know there are standard HtDP ways to do this, recipes, etc. But I don't know these things, sorry. What I will say is that Racket is quite easy to prototype things. You can just describe your problem and don't think too much about the details. I usually like to start in the middle.
For example:
At some point in the middle of execution you will have strings yet to examine and an association list of the strings examined so far. Then your task is 1) if there are no more strings to get, we're done, otherwise 2) get the next string, add it to the table, and continue because we're not done.
(define (build-assoc from-string current-assoc)
(if (done? from-string)
current-assoc
(let ((first-string (get-first-string from-string)))
(let ((result-table (add-string first-string current-assoc))
(result-string (drop-first-string from-string)))
(build-assoc result-string
result-table)))))
Maybe you don't use this procedure in the end. But it's a picture of what you're doing, and it suggests what sort of helper procedures you will need to finish your quest. Give yourself a fighting chance and just use DrRacket to outline your problem. When you see it, then maybe it gives you some ideas how to answer the questions. DrRacket helpfully points out all your unanswered questions like "done?: unbound identifier in: done?" Ah yes, how do we know we're done, good question DrRacket. Well you see, I was given this list of strings, so...

Adapting UCI lisp function with a loop to common lisp [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I'm currently trying to recreate an old program written in UCI Lisp using Common lisp but I'm not very fluent with Lisp.
The original function is:
(DE SETROLE (ROLE FILLER CD)
(CONS (HEADER:CD CD)
(APPEND (FOR (PAIR IN (ROLES:CD CD))
(WHEN (NOT (EQUAL (ROLE:PAIR PAIR) ROLE)))
(SAVE PAIR))
(LIST (LIST ROLE FILLER]
Here's my common lisp interpretation:
(defun setrole (role filler cd)
(cons (header/cd cd)
(append (loop for pair in (roles/cd cd)
do (when (not (equal (role/pair pair) role))
(save pair)))
(list (list role filler)))))
This is the error that comes up:
*** - EVAL: variable WHEN has no value
My initial thinking is that there is no equivalent 'save' function. The description of the function is:
SETROLE Makes a new CD form with (ROLE FILLER) added or replacing the old (ROLE ...) pair.
Kindly help, I'm stumped
I found the bug. There was a loose 'when' in the wild below the code.

implement length in r5rs scheme (drracket) [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
Is it possible to implement the R5RS scheme function "length" using the car and cdr family of functions?
If so could someone post the implementation?
Thanks,
Of course, it's pretty simple. I'm not giving a straight answer because this looks like homework and anyway it's trivial to write. Fill-in the blanks:
(define (length lst)
(if <???> ; if the list is empty
<???> ; return 0
(<???> ; otherwise add 1 and
(length <???>)))) ; advance the recursion over the rest of the list
Notice that only cdr is used. We're not interested in the actual contents of the list, so we can ignore car.
Óscar López's answer is correct. Here are two more implementations (again with the fill-in-the-blanks).
The first one is a left-fold solution (contrast with Óscar's solution, which is a right-fold one):
(define (length lst)
(let loop ((lst lst)
(count 0))
(if <???> ; if the list is empty
<???> ; return the count
(loop <???> <???>)))) ; otherwise bump the count and continue down the list
This has the advantage of being tail-recursive, whereas the right-fold version isn't.
The second one is a tortoise-and-hare solution, which allows cyclic lists to be detected (the earlier solutions would run forever if given a cyclic list):
(define (length lst)
(if (null? lst)
0
(let loop ((tortoise lst)
(hare (cdr lst))
(count 1))
(cond ((eq? tortoise hare) #f) ; found a cycle
((null? hare) <???>) ; reached end of list
((null? (cdr hare)) <???>) ; reached end of list too
(else (loop <???> <???> (+ count 2))))))) ; bump the count and keep looking

Help using Lisp debugger

I'm trying understand how to interpret the output of, and use, the Lisp debugger.
I've got a pretty simple Backtrace for the evaluation of my function, but I cann't seem to work out how to use it to find out in which Lisp 'form' in my function the exception occurred.
I'd appreciate any clues as to what I should be doing, to find where in my code the error originated.
Also - why does the second frame display as "no debug information available for frame"?
I've attached a screen shot with the debugger, and repl (I've also included my function below - I know it's very wrong - but I'm just interested in learning to use the debugger properly). In addition, I hit 'v' on the first frame to go to the source, but this resulted in the error below the repl. (EDIT - the missing source code issue is fixed by downloading & copying it to the correct path)
(horrible function - no comments please!)
(defun myquicksort2 (lst)
(if (eql 1 (length lst))
lst
(let ((mid (middle lst)))
(do ((i 0 (+ i 1)))
((>= i mid) (append (myquicksort2 (subseq lst 0 mid))
(myquicksort2 (subseq lst mid (length lst)))))
(if (> (ltval i lst) (nth 100 lst))
(let ((tmp (ltval i lst)))
(setf (nth i lst) (gtval i lst))
(setf (nth (- (- (length lst) i) 1) lst) tmp)))))))
(defun ltval (i lst)
(nth i lst))
(defun gtval (i lst)
(nth (- (- (length lst) i) 1) lst))
(defun middle (lst)
(round (/ (length lst) 2)))
The error is with > and you have only one > in your source, so that's where the problem is.
edit Built-in CL functions are highly prone to optimization in SBCL, so although the function call in your code is to CL:<, the code that's actually called (and which shows up in the debugger) is from an optimized, specific, SBCL-internal routine. This is less of an issue for user-defined functions, where you will be much more likely to get a useful frame.

Get Last Element of each list

Let us say I have a list ((3 4 5) (d e f) (h i j) (5 5 5 5))
How can I get the last element of each list in such a way that the output would look like this (5 f j 5)?
Assuming this is about Common Lisp, there is a function last which returns a list containing the last item of a list. If you use this function with mapcan, which applies a given function to each element of a list and returns the concatenated results, you'll get what you want.
Note though that accessing the last element of a list is an O(N) operation, so if this isn't just homework after all, you might want to consider if you can't solve the real problem more efficiently than taking the last item of each list (maybe use another datastructure instead).
This, like most early LISPy homework problems is an exercise in thinking recursively and/or thinking in terms of induction. The way to start is to ask yourself simple questions that you can answer easily.
For example, if you had been asked to write something that gave you the first element in each list, I would thing about it this way:
Given a list of lists:
What is first-element of every list in the list '()? (easy - null)
What is first-element of every list in the list '(a)? (easy - a, or maybe an error)
What is first-element of every list in the list '((a))? (easy - (a))
What is first-element of any list in the form '(anything), where anything is a list? (easy - (first anything))
What is the first element of every list in the form '(anything morestuff)? (easy - (cons (first anything) (first-element morestuff)) )
What is first of an atom? either the atom or an error (depends on your point of view)
What is first of null? nil.
What is first of a list? (car list)
From here we can start writing code:
;; here's first, meeting questions 6-8
(define first (lambda (l)
(cond
((null? l) nil) ; Q7
((atom? l) l) ; Q6
(t (car l))))) ; Q8
;; with first we can write first-element, meeting questions 1-5
(define first-element (lambda (l)
(cond
((null? l) nil) ; Q1
((atom? l) (first l)) ; Q2
(t (cons (first (car l) (first-element (cdr l)))))))) ; Q4-5
Now this isn't your homework (intentionally). You should play with this and understand how it works. Your next goal should be to find out how this differs from your assignment and how to get there.
With respect to MAPCAR? Don't worry about it. You need to learn how to solve recursive problems first. Then you can worry about MAPCAR. What is the point of this assignment? To help you learn to think in this mode. Dang near everything in LISP/Scheme is solved by thinking this way.
The reason I went with all the questions to break it down into the parts that I'm worried about. If I'm given the task "how do I do foo on every item in a list?" I should answer the questions: How do I do handle null? How do handle an atom? How do I do handle on the first element on the list? How do I handle everything else? Once I've answered that, then I figure out how to actually do foo. How do I do foo on null? How do I do foo on an atom? How do I do foo on a list?
(defun get-last-lists (s)
(setq rt 'nil)
(loop for i from 0 to (- (length s) 1)
do (setq rt (append rt (last (nth i s)))))
(print rt))
as a beginner of lisp, i post my solution.
Write a procedure that returns the last element of a list, then learn a little about the built-in MAP (a.k.a. MAPCAR) procedure and see if any lightbulbs go off.
probably it is already solved, but I figured this out
; SELECT-FROM-INNER-LIST :: [list] -> [list]
(DEFUN SFIL (lst)
(COND ((NULL lst) NIL)
((LISTP (FIRST lst)) (APPEND (LAST (FIRST lst)) (SFIL (REST lst))))
))
Now, this works for legit list...so if you call function SFIL with correct list.... if not, it will return NIL
hopefully this will be helpful, for anyone who finds it