Different ways to calculate number - algorithm

I need to write a function that will return the number of ways in which can be n (n is a natural number) written as the sum of natural numbers.
For example: 4 can be written as 1+1+1+1, 1+1+2, 2+2, 3+1 and 4.
I have written a function that returns the number of all the options, but does not take into account that the possibilities 1 + 1 + 2 and 2 + 1 + 1 (and all similar cases) are equal. So for n=4 it returns 8 instead of 5.
Here is my function:
(define (possibilities n)
(define (loop i)
(cond [(= i n) 1]
[(> i n) 0]
[(+ (possibilities (- n i)) (loop (+ i 1)))]))
(cond [(< n 1) 0]
[#t (loop 1)]))
Could you please help me with fixing my function, so it will work the way it should be. Thank you.

This is a well-known function, it's called the partition function P, its possible values are referenced as A000041 in the on-line encyclopedia of integer sequences.
One simple solution (not the fastest!) would be to use this helper function, which denotes the number of ways of writing n as a sum of exactly k terms:
(define (p n k)
(cond ((> k n) 0)
((= k 0) 0)
((= k n) 1)
(else
(+ (p (sub1 n) (sub1 k))
(p (- n k) k)))))
Then we just have to add the possible results, being careful with the edge cases:
(define (possibilities n)
(cond ((negative? n) 0)
((zero? n) 1)
(else
(for/sum ([i (in-range (add1 n))])
(p n i)))))
For example:
(map possibilities (range 11))
=> '(1 1 2 3 5 7 11 15 22 30 42)

Related

Scheme Binomial function using Pascal's Triangle

The binom procedure is suppose to return a function such that ((binom n) k a b) is the kth term in the binomial expansion of (a + b)^n.
This is my code.
(define (pascal row col)
(cond ((= col 1) 1)
((= row col) 1)
(else (+ (pascal (- row 1) (- col 1)) (pascal (- row 1) col)))))
(define (binom n)
(lambda (k a b)
(cond ((or (= n 0) (= n k)) 1)
(else (binom (pascal k n)))) 1))
I am trying to fix the binom function. I think the formula is (n k) * a^k * b^(n-k). How should I write it in Scheme?
I think you got confused with the formulas, you're mixing up n, k, row and col.
I'd recommend writing down the formulas you want to program, name the variables on paper, then write the procedure using the same variable names.
With binom though, I'm not sure what your intent was.
Binom returns a lambda, that's all well and good.
But then in that lambda you make a recursive call to binom,
again returning a lambda? And then at the very end you basically ignore
the result you get from this and return 1?
In its current form binom will never return anything other than a lambda or 1.
Here's what I think you want:
(define (pascal n k)
(cond ((< n k) (error "not defined: k > n"))
((= k 1) n)
((= k 0) 1)
((= n k) 1)
(else (+ (pascal (- n 1) (- k 1)) (pascal (- n 1) k)))))
(define (binom n i a b)
(* (pascal n i) (expt a (- n i)) (expt b i)))

Scheme - speed up a heavily recursive function

I must write a Scheme predicate that computes the function f(N -> N) defined as :
if n < 4 :f(n)= (n^2) + 5
if n ≥ 4 :f(n) = [f(n−1) + f(n−2)] * f(n−4)
I wrote a simple predicate that works :
(define functionfNaive
(lambda (n)
(if (< n 4) (+ (* n n) 5)
(* (+ (functionfNaive (- n 1)) (functionfNaive (- n 2)))
(functionfNaive (- n 4))))))
Now, I try a method with an accumulator but it doesn't work...
My code :
(define functionf
(lambda(n)
(functionfAux n 5 9 14)))
(define functionfAux
(lambda (n n1 n2 n4)
(cond
[(< n 4) (+ (* n n) 5)]
[(= n 4) (* n1 (+ n2 n4))]
[else (functionfAux (- n 1) n2 n4 (* n1 (+ n2 n4)))])))
As requested, here's a memoized version of your code that performs better than the naïve version:
(define functionf
(let ((cache (make-hash)))
(lambda (n)
(hash-ref!
cache
n
(thunk
(if (< n 4)
(+ (* n n) 5)
(* (+ (functionf (- n 1)) (functionf (- n 2))) (functionf (- n 4)))))))))
BTW... computing the result for large values of n is very quick, but printing takes a lot of time. To measure the time, use something like
(time (functionf 50) 'done)
AND here's a generic memoize procedure, should you need it:
(define (memoize fn)
(let ((cache (make-hash)))
(λ arg (hash-ref! cache arg (thunk (apply fn arg))))))
which in your case could be used like
(define functionf
(memoize
(lambda (n)
(if (< n 4)
(+ (* n n) 5)
(* (+ (functionf (- n 1)) (functionf (- n 2))) (functionf (- n 4)))))))
First, that's not a predicate. A Predicate is a function which returns a Boolean value.
To calculate the nth result, start with the first four and count up, maintaining the last four known elements. Stop when n is reached:
(define (step a b c d n)
(list b c d (* (+ c d) a)) (+ n 1)))
etc. Simple. The first call will be (step 5 6 9 14 3).
The depth of the recursion tree may be the biggest question, so may be use the iteration which means use some variables to memory the intermediate processes.
#lang racket
(define (functionf n)
(define (iter now n1 n2 n3 n4 back)
(if (= n now)
back
(iter (+ now 1) back n1 n2 n3 (* n3 (+ back n1)))))
(if (< n 4)
(+ 5 (* n n))
(iter 4 14 9 6 5 125)))
(functionf 5)
in this way, the depth of the stack only be 1 and the code is speeded up.

How to decrement a value in Scheme?

I have a procedure that can find the n smallest primes larger than from
(define (primes_range from to n)
(for ([i (in-range from to)])
(if (> n 0)
(cond ((prime? i) (display i)
(- n 1)))
false)))
I add a parameter n to the procedure primes_range and decrement it during the execution only if a prime was found.
But n not changed. How to fix that?
The idiomatic Scheme way to write this function is to use recursion:
(define (primes-range from to n)
(cond ((>= from to) '())
((<= n 0) '())
((prime? from) (cons from (primes-range (+ from 1) to (- n 1))))
(else (primes-range (+ from 1) to n))))
You can easily spell this out in English:
Base cases:
A prime range where the from is equal or greater to to is empty.
A prime range where n is 0 or less is empty.
Recursive cases:
If from is a prime, then the prime range is from, prepended to the result of calling primes-range starting from (+ from 1) and with (- n 1) elements.
Otherwise, the result is calling primes-range starting from (+ from 1) (still with n elements).

Sort prime factors in ascending order Scheme

I am new to Scheme and I want to sort the prime factors of a number into ascending order. I found this code, but it does not sort.
(define (primefact n)
(let loop ([n n] [m 2] [factors (list)])
(cond [(= n 1) factors]
[(= 0 (modulo n m)) (loop (/ n m) 2 (cons m factors))]
[else (loop n (add1 m) factors)])))
Can you please help.
Thank you
I would say it sorts, but descending. If you want to sort the other way, just reverse the result:
(cond [(= n 1) (reverse factors)]
Usually when you need something sorted in the order you get them you can
cons them like this:
(define (primefact-asc n)
(let recur ((n n) (m 2))
(cond ((= n 1) '())
((= 0 (modulo n m)) (cons m (recur (/ n m) m))) ; replaced 2 with m
(else (recur n (+ 1 m))))))
Note that this is not tail recursive since it needs to cons the result, but since the amount of factors in an answer is few (thousands perhaps) it won't matter much.
Also, since it does find the factors in order you don't need to start at 2 every round but the number you found.
Which dialect of Scheme is used?
Three hints:
You need only to test for divisors less equal as the square-root of your Number.
a * b = N ; a < b ---> a <= sqrt( N ).
If you need all Prime-Numbers less some Number, you should use the sieve of eratothenes. See Wikipedia.
Before you start to write a program, look in Wikipedia.
If

Collatz function in scheme

So i'm trying to solve the collatz function iteratively in scheme but my test cases keep showing up as
(define (collatz n)
(define (collatz-iter n counter)
(if (<= n 1)
1
(if (even? n) (collatz-iter (/ n 2) (+ counter 1))
(collatz-iter (+ (* n 3) 1) (+ counter 1))
)
)
)
)
However, my test cases keep resulting in "#[constant 13 #x2]". What did I write wrong, if anything?
You forgot to call collatz-iter. Also, it's not clear what do you intend to do with counter, you just increment it, but never actually use its value - your procedure will always return 1 (assuming that the Collatz conjecture is true, which seems quite possible).
I'm guessing you intended to return the counter, so here's how to fix your procedure:
(define (collatz n)
(define (collatz-iter n counter)
(if (<= n 1)
counter ; return the counter
(if (even? n)
(collatz-iter (/ n 2) (+ counter 1))
(collatz-iter (+ (* n 3) 1) (+ counter 1)))))
(collatz-iter n 1)) ; call collatz-iter
And this is how it works for the examples in wikipedia:
(collatz 6)
=> 9
(collatz 11)
=> 15
(collatz 27)
=> 112
So basically we're counting the length of the Collatz sequence for a given number.
You should indent your code properly. With proper formatting, it's
(define (collatz n)
(define (collatz-iter n counter)
(if (<= n 1)
1
(if (even? n)
(collatz-iter (/ n 2) (+ counter 1))
(collatz-iter (+ (* n 3) 1) (+ counter 1))))))
which clearly has no body forms to execute, just an internal definition. You need to add a call to collatz-iter, like this:
(define (collatz n)
(define (collatz-iter n counter)
(if (<= n 1)
1
(if (even? n)
(collatz-iter (/ n 2) (+ counter 1))
(collatz-iter (+ (* n 3) 1) (+ counter 1)))))
(collatz-iter n 1))
(I'm not sure what your initial counter value should be. I'm assuming 1 is reasonable, but perhaps it should be zero?) Better yet, since the body it just a call to collatz-iter, you can make this a named let, which is more like your original code:
(define (collatz n)
(let iter ((n n) (counter 1))
(if (<= n 1)
1
(if (even? n)
(iter (/ n 2) (+ counter 1))
(iter (+ (* n 3) 1) (+ counter 1))))))
It's sort of like combining the internal definition with the single call to the local function. Once you've done this, though, you'll see that it always returns 1, when it eventually gets to the base case (assuming the Collatz conjecture is true, of course). Fixing this, you'll end up with:
(define (collatz n)
(let iter ((n n) (counter 1))
(if (<= n 1)
counter
(if (even? n)
(iter (/ n 2) (+ counter 1))
(iter (+ (* n 3) 1) (+ counter 1))))))
When I try to run your code in Racket I get the error:
no expression after a sequence of internal definitions
This is telling us that the collatz function conatains the collatz-iter definition, but no expression to call it (other than the recursive calls in collatz-iter). That can be fixed by adding a call to (collatz-iter n 0) as the last line in collatz.
However, when you run the program it always returns 1. Not very interesting. If instead you change it to return the value of counter you can see how many steps it took for the sequence to reach 1.
(define (collatz n)
(define (collatz-iter n counter)
(if (<= n 1)
counter
(if (even? n) (collatz-iter (/ n 2) (+ counter 1))
(collatz-iter (+ (* n 3) 1) (+ counter 1))
)
)
)
(collatz-iter n 0)
)
We can check it against a few examples given on the Wikipedia Collatz conjecture article.
> (collatz 6)
8
> (collatz 11)
14
> (collatz 27)
111
>

Resources