Dr. Racket: saving intermidiate results - Collatz Conjecture - collatz

I am new into coding and got interested in Dr. Racket and I am facing my first problem now. I created this code:
(define (collatz n)
(cond ((= n 1) 1)
((> n 1) (collatz_helper n))))
(define (collatz_helper n)
(if (even? n)
(collatz (/ n 2))
(collatz (+ (* 3 n) 1))))
(collatz 100) ;; >1
Is it possible to store all the intermidiate results in a list or something and then print them out. I mean by intermidiate results n/2 or 3n+1 until we get 1.
For example n=100 (100, 50, 25, 76, 38, 19, 58, 29, 88, 44, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1)
Can someone give me a clue or show me how to implement something like this?

First, you can merge your two functions into one, using cond to check all three cases:
(define (collatz n)
(cond
((= n 1) 1)
((even? n)
(collatz (/ n 2)))
(else
(collatz (+ (* 3 n) 1)))))
Then, to build the list of intermediate values, you can cons n with each recursive step, creating a list whose first element is the original n and last element is 1 (assuming it terminates):
(define (collatz n)
(cond
((= n 1) '(1))
((even? n)
(cons n (collatz (/ n 2))))
(else
(cons n (collatz (+ (* 3 n) 1))))))
For example,
(collatz 100)
=> '(100 50 25 76 38 19 58 29 88 44 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1)

Related

scheme wrong-type-argument in attempted solution to Euler Project problem 7

I've been trying to solve the seventh Euler Project problem. My program looks like this:
(define (add-prime c)
(define (smallest-divisor n) (find-divisor n 2))
(define (find-divisor n test-divisor)
(cond
((> (* test-divisor test-divisor) n) n)
((divides? test-divisor n) test-divisor)
(else
(find-divisor n (+ test-divisor 1)))))
(define (divides? a b) (= (remainder b a) 0))
(define (prime? n)
(= n (smallest-divisor n)))
(if (prime? (+ c 1))
(+ c 1)
(add-prime (+ c 1))))
(define (pv v c)
(if (= c (vector-length v))
v
(begin
(vector-set! v c
(add-prime (vector-ref v (- c 1))))
(pv v (+ c 1)))))
(let ((prime-vec (make-vector 10002)))
(vector-set! prime-vec 0 2)
(pv prime-vec 3)
(display v))
The output looks like this:
In procedure add-prime:
In procedure +: Wrong type argument in position 1: #<unspecified>
I'm very confused. By itself, the add-prime procedure works correctly, it's just that when I combine it to create a vector containing 10,002 prime numbers, it returns this error.
You initialize your vector only at the address 0
(let ((prime-vec (make-vector 10002)))
(vector-set! prime-vec 0 2)
but then you go on filling it starting from the address 3
(pv prime-vec 3)
=
(let ((v prime-vec) (c 3))
....
(vector-set! v c
(add-prime (vector-ref v (- c 1))))
....
=
....
(vector-set! prime-vec 3
(add-prime (vector-ref prime-vec 2)))
....
but you haven't initialized the contents of the vector at the address 2, yet.
Racket uses the value 0 for the uninitialized addresses evidently, but your implementation apparently isn't and instead has #<unspecified> there, causing the error.
Start filling the vector from address 1, instead of 3, and it should fix the error.
As a side note, add-prime is really next-prime. Naming is important, good naming can reduce the cognitive load.
I think there is a typo in your code:
(let ((prime-vec (make-vector 10002)))
(vector-set! prime-vec 0 2)
(pv prime-vec 3)
(display prime-vec)) ;; here you want to print the vector
If I run this program in DrScheme, it gives the following result, which seems kinda fantastic:
#(2 0 0 1 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 ...)

How to write procedure that interleaves two sequences in to one in Scheme

In our exam we had to write a procedure that display first 20 elements of sequence and a procedures that takes 2 sequences and returns one in form of procedure. I wrote an procedures for display-sequence for first 20 elements but I cannot figure out how to make the second procedure which interleave two sequences in to one. I would appreciate any ideas how it can be done.
(define (display-sequence seq)
(letrec ((iter (lambda (seq i j)
(if (= i j)
(display "...")
(begin (display (seq i))
(display ", ")
(iter seq (+ 1 i) j))))))
(iter seq 0 20)))
(define (seq-interleave seq1 seq2)
(lambda (n)
(if (even? n)
(seq1 n)
(seq2 n))))
This should be output when calling these 2 procedures
(display-sequence (seq-interleave sqr (lambda (n) 5)))
0, 5, 1, 5, 4, 5, 9, 5, 16, 5, 25, 5, 36, 5, 49, 5, 64, 5, 81, 5, ...
We just need to map the even numbers back to the corresponding number in the sequence of integers, for example: 2->1, 4->2, 6->3 and so on, doing something similar for the odd numbers. Here's how:
(define (seq-interleave seq1 seq2)
(lambda (n)
(if (even? n)
(seq1 (/ n 2))
(seq2 (/ (+ n 1) 2)))))

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

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

Create stream of numbers that only have certain prime factors

I want to take the infinite stream of numbers 1, 2, 3, 4 ... and filter it so that only numbers that have the prime factors of 7 and 13 are in it. (i.e. 7, 13, 49, 91, 169, 343, ...)
I have the following function started but I'm mixed up on how to properly filter out numbers with only these specific prime factors.
(define function
(stream-filter
(lambda (x)
(or
(= (/ x 7) 1)
(= (/ x 13) 1)
)
)
numbers
)
)
Where stream-filter is the same function from SICP.
Here's one idea: find the prime factors of the number and check if there are factors other than 7 and 13:
(define (factor number)
(let loop ((divisor 2) (number number))
(cond ((> (* divisor divisor) number) (list number))
((zero? (modulo number divisor))
(cons divisor (loop divisor (/ number divisor))))
(else (loop (add1 divisor) number)))))
(stream-filter
(lambda (x)
(null?
(filter (lambda (e) (not (or (= e 7) (= e 13))))
(factor x))))
numbers)

Infinite random stream

I'm having some trouble creating an infinite random stream of numbers from 0 to 9.
Here's where I'm at now:
(#%require (only mzscheme random))
(define (input_stream) (cons (random 9) (delay input_stream)))
Only problem is, (random 9) appears to be initiated only once. The stream is indeed random, but the values of the stream remain constant.
I get 7, 7, 7, 7, 7 or 3, 3, 3, 3, 3
Any ideas on how to initiate the random function each time the endless loop starts over?
I've searched all over online, but couldn't find any way to tackle this one.
As it is, the random procedure is called only once because you didn't recursively call input_stream again, that's why all the random numbers in the stream are in fact, the same number. You have to guarantee that the pseudo-random number generator is called every time a new value is cons'ed, for example:
(define (random-stream n)
(cons (random n) (delay (random-stream n))))
Now this stream will contain random numbers in the range 0-9:
(define input_stream (random-stream 10))
Note: I defined n as a parameter jut to make the generated stream parameterizable, it'll work just as well with a fixed value:
(define (random-stream)
(cons (random 10) (delay (random-stream))))
(define input_stream (random-stream))
For example, to access the first three elements:
(car input_stream)
=> 9 ; random number between 0-9
(car (force (cdr input_stream)))
=> 7 ; random number between 0-9
(car (force (cdr (force (cdr input_stream)))))
=> 8 ; random number between 0-9
Or in general, for generating a list of m random elements from 0 (inclusive) to n (exclusive):
(define (stream-take s m)
(if (zero? m)
'()
(cons (car s)
(stream-take (force (cdr s)) (sub1 m)))))
(stream-take (random-stream 10) 20) ; n=10, m=20
=> '(3 3 3 7 0 7 3 2 3 7 6 0 6 4 1 4 6 1 6 9) ; 20 random numbers between 0-9
I'm not sure how much sense it makes to create a random stream, since simply calling (random n) repeatedly will achieve the same effect.
But a nice way to create streams is with stream-cons:
#lang racket
;;; infinite stream of random numbers
(define (random-stream n)
(stream-cons
(random n)
(random-stream n)))
It is important how you consume streams, since you might end up getting the first number every time if you do it wrong:
(define S (random-stream 10))
;;; right
(for/list ((i (range 5)))
(stream-ref S i))
=> '(7 1 4 8 4)
;;; right
; primitive to take the first n elements of a stream
(define (stream-take s n)
(for/list ((e s) (i (in-range n)))
e))
(stream-take S 20)
=> '(7 1 4 8 4 3 9 8 6 8 4 8 1 1 1 7 0 3 9 4)
;;; wrong
(for/list ((i (range 5)))
(stream-take S 1))
=> '((7) (7) (7) (7) (7))

Resources