How Do I profile my functions using DrScheme?
(require profile)
(define (factorial n)
(cond
((= n 1) 1)
(else (* n (factorial (- n 1))))))
(profile factorial)
The above code returns
Profiling results
-----------------
Total cpu time observed: 0ms (out of 0ms)
Number of samples taken: 0 (once every 0ms)
====================================
Caller
Idx Total Self Name+srcLocal%
ms(pct) ms(pct) Callee
====================================
>
I tried: - (profile (factorial 100))
- (profile factorial) (factorial 100)
But it gives me the same result.
What am I doing wrong?
I'm not familiar with the profile module in PLT Scheme, but perhaps you have to actually call the function?
(profile (factorial 1000))
Have you tried cranking up N in (profile (factorial N)) until there's a noticeable pause?
(factorial 100) is the kind of thing a modern computer should be able to do in <1ms.
Just skimming the documentation makes me suspect its just a matter of factorial being too fast to easily profile for that case.
Related
I am writing the square of sums in racket/scheme recursively. The code sums the numbers right, but it doesn't square it right. I don't know what I am doing wrong. If I pass 10, it should be 3025.
(define (squareOfSums n)
(if (= n 0)
0
(expt (+ n (squareOfSums (- n 1))) 2)))
You should do the squaring only once, at the end of the recursion. Currently, your code squares at every iteration. One way to solve this problem would be to separate the sum part into a helper procedure, and square the result of calling it. Like this:
(define (squareOfSums n)
(define (sum n)
(if (= n 0)
0
(+ n (sum (- n 1)))))
(sqr (sum n)))
Also, did you know that there's a formula to add all natural numbers up to n? This is a nicer solution, with no recursion needed:
(define (squareOfSums n)
(sqr (/ (* n (+ n 1)) 2)))
Either way, it works as expected:
(squareOfSums 10)
=> 3025
Here's a version which I think is idiomatic but which I hope no-one who knows any maths would write:
(define (square-of-sums n)
(let loop ([m n] [sum 0])
(if (> m 0)
(loop (- m 1) (+ sum m))
(* sum sum))))
Here's the version someone who knows some maths would write:
(define (square-of-sums n)
(expt (/ (* n (+ n 1)) 2) 2))
I wish people would not ask homework questions with well-known closed-form solutions: it's actively encouraging people to program badly.
If you start out with your function by writing out some examples, it will be easier to visualize how your function will work.
Here are three examples:
(check-expect (SquareOfSums 0) 0)
(check-expect (SquareOfSums 2) (sqr (+ 2 1))) ;9
(check-expect (SquareOfSums 10) (sqr (+ 10 9 8 7 6 5 4 3 2 1))) ;3025
As we can see clearly, there are two operators we are using, which should indicate that we need to use some sort of helper function to help us out.
We can start with out main function squareOfSums:
(define (squareOfSums n)
(sqr (sum n)))
Now, we have to create the helper function.
The amount of times that you use the addition operator depends on the number that you use. Because of this reason, we're going to have to use natural recursion.
The use of natural recursion requires some sort of base case in order for the function to 'end' somewhere. In this case, this is the value 0.
Now that we have identified the base case, we can create our helper function with little issue:
(define (sum n)
(if (= 0 n)
0
(+ n (sum (sub1 n)))))
I'm new to the racket programming language so as a quick test, I typed this up on DrRacket:
>(define (test k)
(when (not (= k 0))
(begin
k
(test (- k 1)))))
>(test 5)
I expected an output of:
54321
but instead got nothing in return...
Tried an alternate approach:
>(define (test k)
(when (not (= k 0))
(begin
(test (- k 1)) k)))
>(test 5)
but this only printed the number 5. I'm not sure what's going on. What am I doing wrong? Any help is greatly appreciated and thank you so much in advance!
You have to explicitly print the value if you want it to be shown on the console, otherwise the line with the k is doing nothing - remember, Scheme is at its core a functional programming language, and a conditional returns the value of the last expression, all the others are just executed for the effect, but don't return a value. A couple of tips:
(define (test k)
(unless (zero? k) ; use unless instead of when-not, zero? instead of (= x 0)
(display k) ; display prints in console
(test (sub1 k)))) ; use sub1 instead of (- x 1)
Just tried a different approach and that seemed to yield results:
> (define (prnt k) k)
> (define (test k)
(when (not (= k 0))
(begin
(print k)
(test (- k 1)))))
> (test 5)
This printed 54321 which is the behavior I expected. Not too sure why this works but previous attempts didn't but if anyone could shed light on the topic, that would be greatly appreciated!
I am still new in racket language.
I am implementing a switch case in racket but it is not working.
So, I shift into using the equal and condition. I want to know how can i call a function that takes input. for example: factorial(n) function
I want to call it in :
(if (= c 1) (factorial (n))
There are two syntax problems with this snippet:
(if (= c 1) (factorial (n)))
For starters, an if expression in Racket needs three parts:
(if <condition> <consequent> <alternative>)
The first thing to fix would be to provide an expression that will be executed when c equals 1, and another that will run if c is not equal to 1. Say, something like this:
(if (= c 1) 1 (factorial (n)))
Now the second problem: in Scheme, when you surround a symbol with parentheses it means that you're trying to execute a function. So if you write (n), the interpreter believes that n is a function with no arguments and that you're trying to call it. To fix this, simply remove the () around n:
(if (= c 1) 1 (factorial n))
Now that the syntax problems are out of the way, let's examine the logic. In Scheme, we normally use recursion to express solutions, but a recursion has to advance at some point, so it will eventually end. If you keep passing the same parameter to the recursion, without modifying it, you'll get caught in an infinite loop. Here's the proper way to write a recursive factorial procedure:
(define (factorial n)
(if (<= n 0) ; base case: if n <= 0
1 ; then return 1
(* n (factorial (- n 1))))) ; otherwise multiply and advance recursion
Notice how we decrement n at each step, to make sure that it will eventually reach zero, ending the recursion. Once you get comfortable with this solution, we can think of making it better. Read about tail recursion, see how the compiler will optimize our loops as long as we write them in such a way that the last thing done on each execution path is the recursive call, with nothing left to do after it. For instance, the previous code can be written more efficiently as follows, and see how we pass the accumulated answer in a parameter:
(define (factorial n)
(let loop ([n n] [acc 1])
(if (<= n 0)
acc
(loop (- n 1) (* n acc)))))
UPDATE
After taking a look at the comments, I see that you want to implement a switchcase procedure. Once again, there are problems with the way you're declaring functions. This is wrong:
(define fact(x)
The correct way is this:
(define (fact x)
And for actually implementing switchcase, it's possible to use nested ifs as you attempted, but that's not the best way. Learn how to use the cond expression or the case expression, either one will make your solution simpler. And anyway you have to provide an additional condition, in case c is neither 1 nor 2. Also, you're confounding the parameter name - is it c or x? With all the recommendations in place, here's how your code should look:
(define (switchcase c)
(cond ((= c 1) (fact c))
((= c 2) (triple c))
(else (error "unknown value" c))))
In racket-lang, conditionals with if has syntax:
(if <expr> <expr> <expr>)
So in your case, you have to provide another <expr>.
(define (factorial n)
(if (= n 1) 1 (* n (factorial (- n 1)))))
;^exp ^exp ^exp
(factorial 3)
The results would be 6
Update:
(define (factorial n)
(if (= n 1) 1 (* n (factorial (- n 1)))))
(define (triple x)
(* 3 x))
(define (switchcase c)
(if (= c 1)
(factorial c)
(if(= c 2)
(triple c) "c is not 1 or 2")))
(switchcase 2)
If you want something a lot closer to a switch case given you can return procedures.
(define (switch input cases)
(let ((lookup (assoc input cases)))
(if lookup
(cdr lookup)
(error "Undefined case on " input " in " cases))))
(define (this-switch c)
(let ((cases (list (cons 1 triple)
(cons 2 factorial))))
((switch c cases) c)))
I have a problem in understanding the performance of a Common Lisp function (I am still a novice). I have two versions of this function, which simply computes the sum of all integers up to a given n.
Non-tail-recursive version:
(defun addup3 (n)
(if (= n 0)
0
(+ n (addup (- n 1)))))
Tail-recursive version:
(defun addup2 (n)
(labels ((f (acc k)
(if (= k 0)
acc
(f (+ acc k) (- k 1)))))
(f 0 n)))
I am trying to run these functions in CLISP with input n = 1000000. Here is the result
[2]> (addup3 1000000)
500000500000
[3]> (addup2 1000000)
*** - Program stack overflow. RESET
I can run both successfully in SBCL, but the non-tail-recursive one is faster (only by a little, but that seems strange to me). I've scoured Stackoverflow questions for answers but couldn't find something similar. Why do I get a stack overflow although the tail-recursive function is designed NOT to put all recursive function calls on the stack? Do I have to tell the interpreter/compiler to optimise tail calls? (I read something like (proclaim '(optimize (debug 1)) to set the debug level and optimize at the cost of tracing abilities, but I don't know what this does).
Maybe the answer is obvious and the code is bullshit, but I just can't figure it out.
Help is appreciated.
Edit: danlei pointed out the typo, it should be a call to addup3 in the first function, so it is recursive. If corrected, both versions overflow, but not his one
(defun addup (n)
"Adds up the first N integers"
(do ((i 0 (+ i 1))
(sum 0 (+ sum i)))
((> i n) sum)))
While it may be a more typical way to do it, I find it strange that tail recursion is not always optimised, considering my instructors like to tell me it's so much more efficient and stuff.
There is no requirement for a Common Lisp implementation to have tail call optimization. Most do, however (I think that ABCL does not, due to limitations of the Java virtual machine).
The documentation of the implementation should tell you what optimization settings should be chosen to have TCO (if available).
It is more idiomatic for Common Lisp code to use one of the looping constructs:
(loop :for i :upto n
:sum i)
(let ((sum 0))
(dotimes (i n)
(incf sum (1+ i))))
(do ((i 0 (1+ i))
(sum 0 (+ sum i)))
((> i n) sum))
In this case, of course, it is better to use the "little Gauß":
(/ (* n (1+ n)) 2)
Well, your addup3 just isn't recursive at all.
(defun addup3 (n)
(if (= n 0)
0
(+ n (addup (- n 1))))) ; <--
It calls whatever addup is. Trying a corrected version in SBCL:
CL-USER> (defun addup3 (n)
(if (= n 0)
0
(+ n (addup3 (- n 1)))))
ADDUP3
CL-USER> (addup3 100000)
Control stack guard page temporarily disabled: proceed with caution
; ..
; Evaluation aborted on #<SB-SYS:MEMORY-FAULT-ERROR {C2F19B1}>.
As you'd expect.
Using GNU CommonLisp, GCL 2.6.12, compilation of addup2 will optimize tail calls, here is what I got:
>(compile 'addup2)
Compiling /tmp/gazonk_3012_0.lsp.
End of Pass 1.
;; Note: Tail-recursive call of F was replaced by iteration.
End of Pass 2.
OPTIMIZE levels: Safety=0 (No runtime error checking), Space=0, Speed=3
Finished compiling /tmp/gazonk_3012_0.lsp.
Loading /tmp/gazonk_3012_0.o
start address -T 0x9556e8 Finished loading /tmp/gazonk_3012_0.o
#<compiled-function ADDUP2>
NIL
NIL
>>(addup2 1000000)
500000500000
>(addup3 1000000)
Error: ERROR "Invocation history stack overflow."
Fast links are on: do (si::use-fast-links nil) for debugging
Signalled by IF.
ERROR "Invocation history stack overflow."
Broken at +. Type :H for Help.
1 Return to top level.
>>(compile 'addup3)
Compiling /tmp/gazonk_3012_0.lsp.
End of Pass 1.
End of Pass 2.
OPTIMIZE levels: Safety=0 (No runtime error checking), Space=0, Speed=3
Finished compiling /tmp/gazonk_3012_0.lsp.
Loading /tmp/gazonk_3012_0.o
start address -T 0x955a00 Finished loading /tmp/gazonk_3012_0.o
#<compiled-function ADDUP3>
NIL
NIL
>>(addup3 1000000)
Error: ERROR "Value stack overflow."
Hope it helps.
In SBCL User Manual:
The compiler is “properly tail recursive.” [...] The elimination of tail-recursive frames can be prevented by disabling tail-recursion optimization, which happens when the debug optimization quality is greater than 2.
And works as is in the REPL of a fresh image:
(defun sum-no-tail (n)
(if (zerop n)
0
(+ n (sum-no-tail (- n 1)))))
(defun sum-tail (n &key (acc 0))
(if (zerop n)
acc
(sum-tail (- n 1) :acc (+ n acc))))
CL-USER> (sum-no-tail 10000)
50005000 (26 bits, #x2FB0408)
CL-USER> (sum-no-tail 100000)
Control stack guard page temporarily disabled: proceed with caution
; Debugger entered on #<SB-KERNEL::CONTROL-STACK-EXHAUSTED {10026620A3}>
[1] CL-USER>
; Evaluation aborted on #<SB-KERNEL::CONTROL-STACK-EXHAUSTED {10026620A3}>
CL-USER> (sum-tail 100000)
5000050000 (33 bits, #x12A06B550)
CL-USER> (sum-tail 1000000)
500000500000 (39 bits, #x746A5A2920)
CL-USER> (sum-tail 10000000)
50000005000000 (46 bits, #x2D7988896B40)
Hope it helps in SBCL.
I'm trying to expand a simple fibonacci function, and I need to use the values for each term more than once. So, I figured I'd use let to hold onto the values. But, I'm not getting what I think I should out of the function.
Here is the original fib function:
(define (fib n)
(if (< n 2)
n
(+ (fib (- n 1)) (fib (- n 2)))))
Here is my attempt at doing the same thing, but with let:
(define (fib-with-let n)
(if (< n 2)
0
(let ((f1 (fib-with-let (- n 1)))
(f2 (fib-with-let (- n 2))))
(+ f1 f2))))
Results:
> (fib 10)
55
> (fib-with-let 10)
0
Thanks!
You made a typo:
(if (< n 2)
0
...)
You mean n.
You mistyped your base case. In the first version you had:
(if (< n 2)
n
But then in your latter version you wrote:
(if (< n 2)
0
So just change 0 to n.
Your let is not really doing anything. You are still doing all of the extra calculations. Just because you define f1 as (fib-with-let (- n 1)) doesn't mean you won't compute the fib of n-1 again. f2 does not use f1. If you wanted f2 to see f1 you would use let*. However, even this is not really what you want.
As evidence of this, here are the running times for fib(35) and fib-with-let(35):
(time (fib 35))
cpu time: 6824 real time: 6880 gc time: 0
(time (fib-with-let 35))
cpu time: 6779 real time: 6862 gc time: 0
What you really want to do to avoid extra computations is use dynamic programming and recurse in a bottom-up fashion.
What you want is the following code:
(define (dynprog-fib n)
(if (< n 2)
n
(dynprog-fib-helper 1 1 2 n)))
(define (dynprog-fib-helper n1 n2 current target)
(if (= current target)
n2
(dynprog-fib-helper n2 (+ n1 n2) (add1 current) target)))
(time (dynprog-fib 35))
cpu time: 0 real time: 0 gc time: 0
(time (dynprog-fib 150000))
cpu time: 2336 real time: 2471 gc time: 644
As you can see, you can do the first 150,000 fibs in a third of the time the naive approach takes.
Since it looks like you are confused about what let does let me illustrate better:
When you say:
(let ((a 1)
(b 2))
(+ a b))
What you are saying is, let a be 1, and b be 2, add them together.
If you instead said:
(let ((a 1)
(b (+ a 1))
(+ a b))
Can you guess what you'd get? Not 3. It would be blow up with expand: unbound identifier in module in: a
In simple let, your assignments cannot see each other.
If you wanted to write the above you would have to use let*:
(let* ((a 1)
(b (+ a 1))
(+ a b))
That would give you the 3 you expect. let* essentially expands to:
(let ((a 1))
(let ((b (+ a 1)))
(+ a b)))
What you thought you were doing with the lets is called memoization. It's a technique where you store intermediate values so you don't have to repeat them. Let, however, does not do that for you.
Although your problem is a typo in your fib-with-let function, in its simplest form, let is "syntatic-sugar" for an anonymous lambda followed by the arguments that are then evaluated and passed to the lamba, which is then evaluated and a final value returned. So
(let ((f1 (fib-with-let (- n 1)))
(f2 (fib-with-let (- n 2))))
(+ f1 f2))
would be re-written without let to look like
((lambda (f1 f2) (+ f1 f2))(fib-with-let (- n 1))(fib-with-let (- n 2)))