calculate the sum of proper divisors of a given number in Racket BSL - scheme

Design a Racket function named findProperDivisor that takes a natural number and calculates the sum of all its proper divisors. A proper divisor of a natural number is the divisor that is strictly less than the number.
Examples:
Input: 20
Output: 22
//Proper divisors: 1 + 2 + 4 + 5 + 10 = 22
(define (sum-of-proper-divisors n i)
(cond [(= i 1) 1]
[(= (remainder n i) 0)
(+ i (sum-of-proper-divisors n (sub1 i)))]
[else (sum-of-proper-divisors n (sub1 i))]))
I found this code on this page but it gives me 1+2+4+5+10+20=42 I need 22.
I would like to write this code with one parameter by using recursion and cond. I am using Beginning Student Language (BSL), which does not have things like let defined.

Step 1: understand what the code is doing. Why is there an additional parameter? What is happening with it?
Step 2: How do you call this? What does this mean for i?
Step 3: What would you have to do differently so that the remainder is not checked against the number itself?

To fulfill the condition strictly smaller than itself, call it with (sum-of-proper-divisors 20 (sub1 20)) then you get 22, since then, 20 is not counted as divisor.
Since you should define that function with just one number as argument, - due to the constrains of this beginner-language, I would define the desired function as a second function:
(define (sum-of-proper-divisors n i)
(cond ((= 1 i) 1)
((= (remainder n i) 0)
(+ i (sum-of-proper-divisors n (sub1 i))))
(else (sum-of-proper-divisors n (sub1 i)))))
(define (findProperDivisors n)
(sum-of-proper-divisors n (sub1 n)))
(findProperDivisors 20) ;; => 22

Related

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).

Different ways to calculate number

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)

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

Need help in trying to write a procedure for this in scheme

I am working on a tough word problem that's written down below, and i need some help in trying to figure out how to approach this:
Suppose you have a Scheme function that counts the number of people picked up by a certain
bus at a given stop. The bus has many stops, each of which is assigned a number between 1 and
100.
Write a Scheme procedure that takes in (i) a function f, that gives the
number of people picked up from each bus stop, and (ii) an integer m, and returns the number of
stops at which the bus picked up m or fewer people.
Example: suppose the bus stop pickup function is as follows:
(define (stops n)
(cond ((= n 10) 20)
((= n 18) 18)
((= n 39) 52)
((= n 52) 12)
((= n 58) 23)
((= n 70) 34)
((= n 73) 18)
((= n 82) 11)
((= n 97) 33)
(else 0)))
When the procedure is applied to the stops procedure above and given m=20, it should return 5
because the only stops where there were 20 or fewer passengers picked up were stops 10, 18, 52,
73, and 82.
My first approach to this would be to write a helper function to add the parameter n, though I'm not entirely sure what it would do (add the count, maybe?). Other than that, i'm completely stuck. If i could have some clarification. guidance, or direction to this problem, it would be greatly appreciated.
I'm a fan of named lets, so there:
(define (how-many f m)
(let loop ((i 1) (res 0))
(if (<= i 100)
(loop (+ i 1) (if (<= 1 (f i) m) (+ res 1) res))
res)))
Here's a Racket-only solution:
(define (count-fewer-or-equal f m)
(count (lambda (i) (<= 1 (f i) m))
(range 1 100)))
You need to implement iteration using recursion.
Here's the pseudocode:
(define (count f m)
(define (count-iter i sum)
(if (> i 100)
sum
(count-iter (+ i 1)
(if (include-stop? i)
(+ sum 1)
sum))))
(count-iter 1 0))
Once solution, but far from the only one
?b being my notation for a predicate that returns 0 or 1 instead of #t or #f.
(define *potential-stops* (iota 100 1 1))
(define (stops-lt-m f m)
(let ((lt-m?b (lambda (x) (if (> (f x) m) 0 1))))
(reduce + 0 (map lt-m?b potential-stops))))
Could also use a (length (filter ...)) implementation with a lt-m?
potential-stops because it's a constant but could need to be changed if the stop numbering system changed.

weirdness in scheme

I was trying to implement Fermat's primality test in Scheme.
I wrote a procedure fermat2(initially called fermat1) which returns true
when a^p-1 congruent 1(mod p) (please read it correctly guys!!)
a
every prime p number should satisfy the procedure (And hence Fermat's little theorem .. )
for any a
But when I tried to count the number of times this procedure yields true for a fixed number of trials ... ( using countt procedure, described in code) I got shocking results ans
So I changed the procedure slightly (I don't see any logical change .. may be I'm blind) and named it fermat1(replacing older fermat1 , now old fermat1 ->fermat2) and it worked .. the prime numbers passed the test all the times ...
why on earth the procedure fermat2 called less number of times ... what is actually wrong??
if it is wrong why don't I get error ... instead that computation is skipped!!(I think so!)
all you have to do , to understand what I'm trying to tell is
(countt fermat2 19 100)
(countt fermat1 19 100)
and see for yourself.
Code:
;;Guys this is really weird
;;I might not be able to explain this
;;just try out
;;(countt fermat2 19 100)
;;(countt fermat1 19 100)
;;compare both values ...
;;did you get any error using countt with fermat2,if yes please specify why u got error
;;if it was because of reminder procedure .. please tell your scheme version
;;created on 6 mar 2011 by fedvasu
;;using mit-scheme 9.0 (compiled from source/microcode)
;; i cant use a quote it mis idents (unfriendly stack overflow!)
;;fermat-test based on fermat(s) little theorem a^p-1 congruent to 1 (mod p) p is prime
;;see MIT-SICP,or Algorithms by Vazirani or anyother number theory book
;;this is the correct logic of fermat-test (the way it handles 0)
(define (fermat1 n)
(define (tryout a x)
;; (display "I've been called\n")
(= (remainder (fast-exp a (- x 1)) x) 1))
;;this exercises the algorithm
;;1+ to avoid 0
(define temp (random n))
(if (= temp 0)
(tryout (1+ temp) n)
(tryout temp n)))
;;old fermat-test
;;which is wrong
;;it doesnt produce any error!!
;;the inner procedure is called only selective times.. i dont know when exactly
;;uncomment the display line to see how many times tryout is called (using countt)
;;i didnt put any condition when it should be called
;;rather it should be every time fermat2 is called
;;how is it so??(is it to avoid error?)
(define (fermat2 n)
(define (tryout a x)
;; (display "I've been called\n")
(= (remainder (fast-exp a (- x 1)) x) 1))
;;this exercises the algorithm
;;1+ to avoid 0
(tryout (1+ (random n)) n))
;;this is the dependency procedure for fermat1 and fermat2
;;this procedure calculates base^exp (exp=nexp bcoz exp is a keyword,a primitive)
;;And it is correct :)
(define (fast-exp base nexp)
;;this is iterative procedure where a*b^n = base^exp is constant always
;;A bit tricky though
(define (logexp a b n)
(cond ((= n 0) a);;only at the last stage a*b^n is not same as base^exp
((even? n) (logexp a (square b) (/ n 2)))
(else (logexp (* a b) b (- n 1)))))
(logexp 1 base nexp))
;;utility procedure which takes a procedure and its argument and an extra
;; argument times which tells number of times to call
;;returns the number of times result of applying proc on input num yielded true
;;counting the number times it yielded true
;;procedure yields true for fixed input,
;;by calling it fixed times)
;;uncommenting display line will help
(define (countt proc num times)
(define (pcount p n t c)
(cond ((= t 0)c)
((p n );; (display "I'm passed by fermat1\n")
(pcount p n (- t 1) (+ c 1)));;increasing the count
(else c)))
(pcount proc num times 0))
I had real pain .. figuring out what it actually does .. please follow the code and tell why this dicrepieancies?
Even (countt fermat2 19 100) called twice returns different results.
Let's fix your fermat2 since it's shorter. Definition is: "If n is a prime number and a is any positive integer less than n, then a raised to the nth power is congruent to a modulo n.". That means f(a, n) = a^n mod n == a mod n. Your code tells f(a, n) = a^(n-1) mod n == 1 which is different. If we rewrite this according to definition:
(define (fermat2 n)
(define (tryout a x)
(= (remainder (fast-exp a x) x)
(remainder a x)))
(tryout (1+ (random n)) n))
This is not correct yet. (1+ (random n)) returns numbers from 1 to n inclusive, while we need [1..n):
(define (fermat2 n)
(define (tryout a x)
(= (remainder (fast-exp a x) x)
(remainder a x)))
(tryout (+ 1 (random (- n 1))) n))
This is correct version but we can improve it's readability. Since you're using tryout only in scope of fermat2 there is no need in parameter x to pass n - latter is already bound in scope of tryout, so final version is
(define (fermat n)
(define (tryout a)
(= (remainder (fast-exp a n) n)
(remainder a n)))
(tryout (+ 1 (random (- n 1)))))
Update:
I said that formula used in fermat2 is incorrect. This is wrong because if a*k = b*k (mod n) then a = b (mod n). Error as Vasu pointed was in generating random number for test.

Resources