So recently I learned recursive function and I am trying some exercise then I am just stuck.
Question is
list-nth-item, that consumes a list, (lst), and a natural number, (n), and
produces the n-th element in lst if exists, otherwise the function produces false. Note
that the first item is in index 0. For example: (list-nth-item (list 1 2 3) 0)produces 1
Here is my code
;;list-nth-item consumes list and a natural number
;;and produces the n-th element in the list or false
;;list-nth-item: List Nat -> (Anyof Any false)
(define (list-nth-item lst n)
(cond
[(empty? lst)false]
[(= n 0)(first lst)]
[else ????]))
(list-nth-item (list 1 2 3)2)--> should produce 3
I know thus is not a proper recursion, also when n = 0 it should produce first number in the list example (list-nth-item (list 1 2 3)0)should give1.
I am new to this just not getting how to form a recursion.
Think of list as a conveyor belt: you check if you arrived to your item (using you first case (= n 0)), and if not (else case) you just shift the belt by taking the tail of list (using cdr function) and repeating the process again.
This can be done like following:
(define (list-nth-item lst n)
(cond
[(empty? lst) #f]
[(zero? n) (car lst)]
[else (list-nth-item ; <-- repeats the process
(cdr lst) ; <-- shifts the "belt"
(sub1 n))])) ; <-- updates the number of steps to go
PS: this is already done by list-ref function.
Related
I have a problem with a function showlength which I'm programming in Scheme:
(define showlength
(lambda (m lst)
(cond ((number? m) (list (cons m lst)
(+ 1(length lst))))
((pair? m) (let* ([x (cdr m)]
[y (car m)])
(showlength x lst)
(showlength y lst))))))
The code is meant to take either a number or a pair of numbers and a list(lst) and returns a list showing all values contained in the list and the length of the list. The program works for when I have just a number of example:
(showlength 2 '())
and returns
((2) 1)
but when I try it for a problem consisting of a pair of numbers of example
(showlength (cons 2 3) ' ())
in which the returned value is meant to be
((0 . 1) 3 2) 3)
it shows
((2) 1)
What is wrong with my code?
EDIT: For those who the code isnt that clear to. When a pair of numbers is used, the code is meant to add the cdr of the pair to the list. Then its meant to add the car of the pair to the list( where the list already contains the cdr of the pair from above) and then returns the list and its length
The issue is that in your let statement, you have two independent calls to show length, and you implementation is just returning the value of the first.
In scheme a function only ever returns one value (generally, some implementation provide special mechanisms to allow a value to expect and accept multiple return values. )
My question is where in the world do you expect a zero to come from? The smallest value in the m is 2, and the smallest value that length can return of it's own volition is 1, when lst length is zero.
Whatever it is you're doing you need to step back and check your assumptions, something isn't right.
(define showlength
(lambda (m lst)
(cond ((number? m) (list (cons m lst)
(+ 1(length lst))))
((pair? m) (let* ((x (cdr m))
(y (car m)))
(cons (showlength x lst)
(showlength y lst)))))))
Tying the returns together with cons will get you a single value without losing anything, but it's not the return value you want.
So in my scheme function, provided below, I need to produce a list of structures. So far, I've made 2 helper functions: One calls a list of numbers counting up from 1 to x. The other calls the structure that corresponds to x.
For example:
(helper1 10) -> (list 1 2 3 4 5 6 7 8 9 10)
(helper2 1) -> (make-person 0 1)
(helper2 2) -> (make-person 1 2)
(helper2 3) -> (make-person 2 3) etc...
How can I make my main function call the list of helper1, where each element is replaced with its corresponding structure.
Note: My main function must be recursive, and it must produce a list of structures.
So far, for my main function I have:
(define (main-function x)
(cond
[(zero? x) empty]
[else
...]))
Also, I am writing in Beginner Student with List Abbreviations.
You'll want to construct an entirely new list, not replace each element with a structure. That's the appearance of the end result, but not how the function works.
Basically, if your main-function takes in a number, then you'll want to create a helper function that actually does the recursion, where you will pass in the result of calling (helper1 x).
Then, in your recursion, you're just recontructing a list with the corresponding structures.
(define (main-function x)
(main-function-helper (helper1 x)))
(define (main-function-helper l)
(cond
[(empty? l) l]
[else (cons (helper2 (first l))
(main-function-helper (rest l)))]))
Another option that may make more sense is to never create the intermediate list:
(define (main-function x)
(main-function-helper 1 x))
(define (main-function-helper counter max)
(cond
[(= counter max) (cons (helper2 counter) empty)]
[else (cons (helper2 counter)
(main-function-helper (add1 counter) max))]))
The function is supposed to be tail-recursive and count from 1 to the specified number. I think I'm fairly close. Here's what I have:
(define (countup l)
(if (= 1 l)
(list l)
(list
(countup (- l 1))
l
)
)
)
However, this obviously returns a list with nested lists. I've attempted to use the append function instead of the second list to no avail. Any guidance?
Here's an incorrect solution:
(define (countup n)
(define (help i)
(if (<= i n)
(cons i (help (+ i 1)))
'()))
(help 1))
This solution:
uses a helper function
recurses over the numbers from 1 to n, cons-ing them onto an ever-growing list
Why is this wrong? It's not really tail-recursive, because it creates a big long line of cons calls which can't be evaluated immediately. This would cause a stack overflow for large enough values of n.
Here's a better way to approach this problem:
(define (countup n)
(define (help i nums)
(if (> i 0)
(help (- i 1)
(cons i nums))
nums)))
(help n '()))
Things to note:
this solution is better because the calls to cons can be evaluated immediately, so this function is a candidate for tail-recursion optimization (TCO), in which case stack space won't be a problem.
help recurses over the numbers backwards, thus avoiding the need to use append, which can be quite expensive
You should use an auxiliar function for implementing a tail-recursive solution for this problem (a "loop" function), and use an extra parameter for accumulating the answer. Something like this:
(define (countup n)
(loop n '()))
(define (loop i acc)
(if (zero? i)
acc
(loop (sub1 i) (cons i acc))))
Alternatively, you could use a named let. Either way, the solution is tail-recursive and a parameter is used for accumulating values, notice that the recursion advances backwards, starting at n and counting back to 0, consing each value in turn at the beginning of the list:
(define (countup n)
(let loop ((i n)
(acc '()))
(if (zero? i)
acc
(loop (sub1 i) (cons i acc)))))
Here a working version of your code that returns a list in the proper order (I replaced l by n):
(define (countup n)
(if (= 1 n)
(list n)
(append (countup (- n 1)) (list n))))
Sadly, there is a problem with this piece of code: it is not tail-recursive. The reason is that the recursive call to countup is not in a tail position. It is not in tail position because I'm doing an append of the result of (countup (- l 1)), so the tail call is append (or list when n = 1) and not countup. This means this piece of code is a normal recusrive function but to a tail-recursive function.
Check this link from Wikipedia for a better example on why it is not tail-recusrive.
To make it tail-recursive, you would need to have an accumulator responsible of accumulating the counted values. This way, you would be able to put the recursive function call in a tail position. See the difference in the link I gave you.
Don't hesitate to reply if you need further details.
Assuming this is for a learning exercise and you want this kind of behaviour:
(countup 5) => (list 1 2 3 4 5)
Here's a hint - in a tail-recursive function, the call in tail position should be to itself (unless it is the edge case).
Since countup doesn't take a list of numbers, you will need an accumulator function that takes a number and a list, and returns a list.
Here is a template:
;; countup : number -> (listof number)
(define (countup l)
;; countup-acc : number, (listof number) -> (listof number)
(define (countup-acc c ls)
(if ...
...
(countup-acc ... ...)))
(countup-acc l null))
In the inner call to countup-acc, you will need to alter the argument that is checked for in the edge case to get it closer to that edge case, and you will need to alter the other argument to get it closer to what you want to return in the end.
I need a function that will take in a list of characters and numbers, and then return the numbers added up (ignoring the characters). This is what I have so far:
(define (adder lst)
(cond
((null? lst)
0)
((number? (car lst))
(+(adder (car lst)) (adder (cdr lst))))
((char? (car lst))
((adder(cdr lst))))
))
(display (adder '(asd12sdf)))
Running it on codepad.org just displays void. I know the code is wrong because it looks wrong, but I have no idea how to fix it... How do I have the function keep track of the first number it finds and add it to the next one it finds, while skipping all characters?
In your second cond case, there's no reason to run adder on (car lst). Just adding (car list) itself to the recursive step should work.
For the last line, don't test (char? (car lst)). Just make the last line the else clause, meaning that anything BUT a number will go to the else line.
The reason you're getting void is because your input doesn't satisfy any of the cond conditions, and you have no else, so the answer is nothing (i.e. (void)).
The last mistake is in the input you're giving it. '(asd12sdf) is literally a list with one symbol named "asd12sdf". I think you want to give it '(a s d 1 2 s d f) (a list of 6 symbols and 2 numbers) which should result in 3. Notice that there's a very important difference between the symbol 'a and the character #\a.
It looks like you have the logic down, so your problem doesn't seem to be functional languages, just Scheme's syntax.
Edit: and in the last line, you have ((adder(cdr lst))) which has one too many parens wrapped around it. That will cause Scheme to attempt to evaluate the result of adder (which is a number) as a procedure (error!).
You should observe that this function is more or less sum which can be defined simply by using fold.
(define (adder lst)
(fold + 0 lst))
What does fold do? Basically, it's defined like so:
(define (fold f initial lst)
(if (null? lst)
initial
(fold f (f (car lst) initial) (cdr lst))))
(In other words, it calls f, a function of 2 arguments, on each element of lst, using the car of the lst as the first argument, and the accumulated result as the second argument to f.)
The issue here which you need to address is that + doesn't know how to operate on non-numeric values. No problem, you've already dealt with that. What happens if it's a character instead? Well, you're not adding anything to the total value, so replace it with a 0. Therefore, your solution is as simple as:
(define (adder lst)
(fold your-new-protected-+ 0 lst))
In Common Lisp:
(reduce #'+ '(1 #\a #\b 2 1 2 #\c #\d 4)
:key (lambda (item) (if (numberp item) item 0)))
or
(loop for item in '(1 #\a #\b 2 1 2 #\c #\d 4)
when (numberp item) sum item)
How can I pass a list as a parameter to a function adding elements to it recursively,and have it unmodified when it comes out of recursion?
I want to use the list at each level of recursion with the list having the values added by deeper recursion levels.
To be more specific I want to do a DFS search on a graph and I want to store in the list the nodes I visited.
One method of doing this is just to return the list so you have access to it at higher levels of recursion.
Another method is to have your list be stored in a variable outside of the recursion. In other words not stored on the stack. Since it is not a good idea to use a global variable for this we need to have some local recursion.
The following code is a foolish way to reverse a list but it does illustrate the technique I am talking about.
(define (letrecreverse lst)
(letrec ((retlist '())
(reverse (lambda (lst)
(if (null? lst)
'()
(begin
(set! retlist (cons (car lst) retlist))
(reverse (cdr lst)))))))
(reverse lst)
retlist))
(letrecreverse '(1 2 3 4))
;outputs '(4 3 2 1)
Can you adopt this technique for your purposes?
If you build a new list by consing a value onto an old list, that old list is unmodified.
(define old '(1 2 3))
(define new (cons 55 old))
new
>(55 1 2 3)
old
>(1 2 3)
The 'tail' of the first cons in "new" is the list "old". But old hasn't changed.
(cdr new)
> (1 2 3)
If I understood your question correctly, this could be one solution:
;; Just a helper to print the current list.
(define (show list)
(display "list = ")
(display list)
(newline)
(flush-output))
;; Maximum depth of recursion
(define max-recur 5)
;; Original list is backed-up here.
(define orig-list null)
(define (recur list depth)
(if (null? orig-list)
(set! orig-list list))
(cond ((< depth max-recur)
(show list)
(recur (cons (random max-recur) list) (add1 depth)))
(else orig-list)))
Sample run:
> (recur '(1) 0)
list = (1)
list = (1 1)
list = (2 1 1)
list = (3 2 1 1)
list = (4 3 2 1 1)
(1) ;; In the end you get the original list back.