Clojure Recursive Log Table - recursion

(ns logtable)
(defn displayLogTable[start stop step]
(if (> start stop) nil
(if < star stop) log10 start)
(displayLogTable ( + start step) stop step)
)
))
(defn -main []
(println "\n Enter your start, stop and step: ")
(let
[ start stop step (Integer/parseInt (read-line))]
(print (displayLogTable start stop step)
)
)
I'm getting a "Too many arguments to if" error
I'm trying to implement a recursive function to print out my log table.

There are multiple errors in this part of the code:
(defn displayLogTable[start stop step]
(if (> start stop) nil
(if < star stop) log10 start)
(displayLogTable ( + start step) stop step)
)
))
Formatting to make it obvious:
(defn displayLogTable[start stop step]
(if (> start stop)
nil ; 1
(if < ;2
star
stop)
log10 ; 3
start) ; 4
(displayLogTable (+ start step) stop step))
)) ; to much closing parens
The if has too many forms (1-4), where only three are allowed (if predicate then else). The if at 2 is correctly formed, but for sure not what you want (if < is true (always) then star (typo, most likely start) else stop).

If we correct your code along the lines that #cfrick's answer implies, we get something like ...
(defn displayLogTable [start stop step]
(if (> start stop)
nil
(if (< start stop)
(Math/log10 start)
(displayLogTable (+ start step) stop step))))
This doesn't make much sense. We can simplify it to ...
(defn displayLogTable [start stop step]
(loop [start start]
(cond
(> start stop) nil
(< start stop) (Math/log10 start)
:else (recur ( + start step)))))
Equally futile. It looks as though you want the sequence of logarithms of the range of numbers defined by start, stop, and step. One way to do this in Clojure is ...
(defn displayLogTable [start stop step]
(map
(fn [x] (Math/log10 x))
(range start stop step)))
For example, ...
=> (displayLogTable 1 10 1)
(0.0 0.3010299956639812 0.47712125471966244 0.6020599913279624 0.6989700043360189
0.7781512503836436 0.8450980400142568 0.9030899869919435 0.9542425094393249)
Notice that range is inclusive of the start point (0) but exclusive of the end point (10).
Clojure's means of dealing with sequences (map and range occur here) are often the key to solving problems like this.

Related

Bind a variable based on another variable inside a condition / loop / let

I am going through the tutorial at Lisp Tutor Jr, on my own.
After completing an assignment on recursion, I started thinking about expanding the numeric range to negative numbers.
If I bind as in the following code, it gets adjusted together with x.
1) Do I understand correctly that using defconstant inside the function is wrong?
2) How would I bind a minimal variable based on x, in this case attempted via (- x).
(defun list-odd-range(x)
(let ((neg (- x)))
(cond
((< x neg) nil)
((oddp x)(cons x (list-odd (1- x))))
(t (list-odd (1- x))))))
The function as-is returns
(list-odd 5)=>(5 3 1)
I would like to bind neg once, as (- x)
and have the function return a range from positive to negative x:
(list-odd 5)=>(5 3 1 -1 -3 -5)
Binding with an integer, such as the following bit, works:
(let ((neg -5))
What is the correct way to have it defined in relation to x, such as (- x) ?
1) Defconstant doesn't really make sense in a function. It defines a global constant, which is constant. If you ever call the function again, you either provide the same (eql) value and have no effect, or a different value, which is illegal.
2) As you observed, the inner call doesn't know anything about the outer environment except what is passed as an argument. You can either keep it at that and add the remaining part after the return of the inner call (I elide checking the inputs in the following, you'd need to make sure that x is always a nonnegative integer):
(defun odd-range (x)
(cond ((zerop x) ())
((evenp x) (odd-range (1- x)))
(t (cons x
(append (odd-range (1- x))
(list (- x)))))))
Or you can pass the end number along as an additional argument:
(defun odd-range (start end)
(cond ((< start end) ())
((evenp start) (odd-range (1- start) end))
(t (cons start
(odd-range (1- start) end)))))
This would have the benefit of giving the caller free choice of the range as long as end is smaller than start.
You can also pass along the constructed list so far (often called an accumulator, abbreviated acc):
(defun odd-range (start end acc)
(cond ((< start end) (reverse acc))
((evenp start) (odd-range (1- start) end acc))
(t (odd-range (1- start) end (cons start acc)))))
This conses to the front of the list while accumulating and only reverses the result at the end. This avoids walking the accumulated list at every step and is a big improvement on running time. It also moves the recursive call into tail position so that the compiler may produce code that is equivalent to a simple loop, avoiding stack limits. This compiler technique is called tail call elimination or tail call optimization (TCO).
Since Common Lisp compilers are not required to do TCO, it is good style to write loops actually as loops. Examples:
(defun odd-range (start)
(do ((x start (1- x))
(end (- start))
(acc ()
(if (oddp x)
(cons x acc)
acc)))
((<= x end) (reverse acc))))
(defun odd-range (x)
(let* ((start (if (oddp x) x (1- x)))
(end (- start)))
(loop :for i :from start :downto end :by 2
:collect i)))

Common Lisp - How to sum user input

I would like to take a series of user-input integers, then sum the input. For instance, if the user enters:
1 <return>
2 <return>
3 <return>
<return>
6
Here is my code so far:
(defun stuff ()
(format t "Enter a number: ")
(let ((n (read)))
(+ n)))
This example is actually more complicated than it should be since it requires multiple things (looping, reading input, and accumulating). I am going to give you two solutions, one which is the easy way and another which is how I would personally do it. First of all the easy way:
(defun stuff (&optional (acc 0)) ; An optional argument for keeping track of the sum.
(if (y-or-n-p "Do you want to continue?") ; Ask if they want to continue
(progn (format t "Enter a number: ") ; If they say yes we need to ask them for the
(stuff (+ acc (read)))) ; number, read it, add it to the sum, and
; continue. We need progn because we need to
; execute two pieces of code (format and stuff) in the if
acc)) ; If they say no, then return the total sum
More advanced version which is how I would do it:
(defun stuff ()
(loop while (y-or-n-p "Do you want to continue?") ; while they want to continue
do (format t "Enter a number: ") ; print the prompt
sum (parse-integer (read-line)))) ; read the line, parse the integer, and sum it
Edit: Versions of the previous which stop on a new line.
(defun stuff (&optional (acc 0))
(let ((line (read-line)))
(if (string= line "") ; If this line is the empty string
acc ; return the sum
(stuff (+ acc (parse-integer line)))))) ; otherwise recur and sum the number on the line
(defun stuff ()
(loop for line = (read-line)
until (string= line "")
sum (parse-integer line)))

How do I get rid of the #<void> that results from this recursive Scheme function?

I'm supposed to write a recursive function that applies another function to a set of consecutive integers and returns a list. If start is > than stop, I'm just supposed to return an empty set.
Here's what I've got. I'm not sure this is the best solution to the problem, but...
(define (myfunction start stop fn)
(if (<= start stop)
(cons (fn start)(myfunction (+ start 1) stop fn)))
)
(define (foo val1) ; just to demonstrate myfunction
(* val1 2))
When I try to use it in the scheme interpreter, I get this:
(myfunction 0 5 foo)
(0 2 4 6 8 10 . #<void>)
What can I do to get rid of the void thing? I'm a bit confused.
Consider what happens if you do:
> (list (if #f 'then-value))
;=> (#<void>)
Your function has an if without an "else" part.
(define (myfunction start stop fn)
(if (<= start stop)
(cons (fn start)
(myfunction (+ start 1) stop fn))
; missing something here
))
What should the list be when it's not the case that (<= start stop)? I'd guess that a reasonable default would be the empty list, so that when (myfunction (+ start 1) stop fn) is finally called with values of start and stop such that start is greater than stop, you get the empty list, so that (cons (fn start) (myfunction ...)) has an empty list as its second argument:
(define (myfunction start stop fn)
(if (<= start stop)
(cons (fn start)
(myfunction (+ start 1) stop fn))
'()))
(myfunction 0 5 (lambda (x) (* x 2)))
;=> (0 2 4 6 8 10)
For more about why the output was (<elements> . #<void>) (i.e., why it's got the dot at the end), have a look at this answer (disclaimer: it's my answer) to Recursive range in Lisp adds a period?.

Create a list out of the output in the loop

We are tasked to print out the values in the pascal triangle in this manner
(pascal 2)
(1 2 1)
(pascal 0)
(1)
I copied the code for the binomial thereom somewhere in the internet defined as follows:
(defun choose(n k)
(labels ((prod-enum (s e)
(do ((i s (1+ i)) (r 1 (* i r))) ((> i e) r)))
(fact (n) (prod-enum 1 n)))
(/ (prod-enum (- (1+ n) k) n) (fact k))))
Now I'm trying to create a list out of the values here in my pascal function:
(defun pascal (start end)
(do ((i start (+ i 1)))
((> i end) )
(print (choose end i) ))
)
The function produces 1 2 1 NIL if I test it with (pascal 0 2). How can I eliminate the NIL and create the list?
Note: I explicitly didn't provide an implementation of pascal, since the introductory “we are tasked…” suggests that this is a homework assignment.
Instead of printing the result of (choose end i) on each iteration, just collect the values produced by (choose end i) into a list of results, and then return the results at the end of the loop. It's a common idiom to construct a list in reverse order by pushing elements into it, and then using nreverse to reverse it to produce the final return value. For instance, you might implement range by:
(defun range (start end &optional (delta 1) &aux (results '()))
(do ((i start (+ i delta)))
((>= i end) (nreverse results))
(push i results)))
or (It always feels satisfying to write a do/do* loop that doesn't need any code in the body.)
(defun range (start end &optional (delta 1))
(do* ((results '() (list* i results))
(i start (+ i delta)))
((>= i end) (nreverse results))))
so that
(range 0 10 3)
;=> (0 3 6 9)
However, since the rows in Pascal's triangle are palidromes, you don't need to reverse them. Actually, since the rows are palindromes, you should even be able to adjust the loop to generate just half the list return, e.g.,
(revappend results results)
when there are an even number of elements, and
(revappend results (rest results))
when there are an odd number.

For-loop in scheme

I want to define a for-n function in scheme that takes 3 parameters, start and stop are integers and fn is a function. I want the for-n function to call fn with start then start+1 ... and in the end with stop.
Also I want to store all the values fn returns in a list. Please help me get started. I am an experienced programmer but have just starting learning scheme.
This is the function definition I got:
[edit]
(define (fn a)
a
)
(define (for-n start stop fn)
(cond
((> start stop) (quote ()))
((= start stop) (list(fn start)))
(else (list(for-n (+ start 1) stop fn)))
)
)
> (for-n 3 5 fn)
(list (list (list 5)))
When (for-n 3 5 fn) is called, I want it to return
(3 4 5), what am I doing wrong?
[edit-2]
Thanks for the help everyone. I got function working now. Here is what I got:
(define (for-n start stop fn)
(cond
((> start stop) (quote ()))
((= start stop) (list(fn start)))
(else (cons (fn start) (for-n (+ start 1) stop fn)))
)
)
You seldom want to use list to recursively construct lists. Lists are built with cons and null (aka '()); list is just a convenience function to create a fixed sized list.
(list 1 2 3) = (cons 1 (cons 2 (cons 3 null)))
You should only have two cases in your cond clause: either you're done or you aren't.
Examples help. In particular, pick examples that are related by your recursive calls. You included the example (for-n 3 5 fn). What about (for-n 4 5 fn); what should it return? Now, given start = 3, stop = 5, and (for-n 4 5 fn) = whatever you think it should produce, how can you construct the answer you think (for-n 3 5 fn) should produce?
I highly recommend How to Design Programs (text available online) as an introduction to functional programming.
Here's a solution that uses SRFI 1:
(define (for-n start stop fn)
(map fn (iota (- stop start) start)))
If this is for homework, then it's up to you to define iota, and perhaps map also. :-D
Another solution using a different strategy (also uses SRFI 1):
(define (for-n start stop fn)
(unfold-right (lambda (x) (< x start))
fn sub1 (sub1 stop)))
where sub1 == (lambda (x) (- x 1)). Of course, you have to implement unfold-right yourself, in this case.
Hopefully from the above two example solutions, you have enough ideas to build your own from-scratch solution. :-)
I'm new to scheme too, but here's what I came up with for a generic for loop that seems to work for me:
(define (for i end-cond end-fn fn var)
(if (end-cond i)
var
(for (end-fn i) end-cond end-fn fn (fn var))
)
)
So the canonical:
for (i=0; i > 5; i++) {
print i;
}
return i;
Can be written as:
(define i 0) (for i (lambda (x) (> 5 x)) (lambda (y) (+ 1 y)) display i)
...and you can see why the paradigm doesn't translate well, though you can replace those lambdas with named functions to make it more readable.
--
Self-edit 2015:
This is awful, and the wrong way to do functional programming. A 'map' or 'fold' based approach is much better.

Resources