Maximum sum of a tree in Scheme - recursion

I am having troubles with an exercise I am trying to do because I'm new to this language and to think in a recursive way is kind of hard to me. I have a tree (not neccesary binary) and I need to find the path that gives the maximum sum. For example I have the tree: ’(1 ((0) (2 ((3) (2))) (5))) given in the image
Example tree
1
0 2 5
3 2
So I have to do a function: (function ’(1 ((0) (2 ((3) (2))) (5)))) and it should return 6 (in this case). There are 2 paths that give the answer: 1 + 2 + 3 = 6 and 1 + 5 = 6. I tried to "translate" a code in python found here, but I have no idea how to do it recursively in Scheme.

The recursion is pretty simple, you just need to check 3 cases:
NUMBER?
NULL?
PAIR?
So in scheme you would structure it like this:
(define (tree-sum t)
(cond ((number? t)
...)
((null? t)
...)
((pair? t)
...)))
The pair? one is the recursive case in which you add up the sums of car and cdr. Hope that helps!

Related

Equality of vectors in clojure

I was trying to solve this problem
https://www.4clojure.com/problem/32
and I realized that this statement gave output as false.
(= (#(into [] (distinct %)) [1 2 3])
'(1 1 2 2 3 3))
It is supposed to be true as the function is also returning the same vector.
Can someone please explain to me why this is false?
The question you ask is irrelevant to the problem you refer to, which your own answer solves. Looking at the question alone ...
As rascio comments, you are applying distinct to the wrong
sequence.
Furthermore, you can apply = to any two sequences. You don't have
to convert the lazy sequence that distinct produces to a vector.
Thus the following suffices ...
(= [1 2 3] (distinct '(1 1 2 2 3 3)))
=> true
From the comments, I found out that I was using the distinct method incorrectly and hence decided to use the repeat method to get the answer which was:
mapcat #(repeat 2 %)

Convert a polynomial represented as a list of coefficients to a string

I know this is a newbish question. I am trying to create a function 'displayPoly' to display a polynomial in scheme. For example a list given as
'(2 0 1 5.1 8) should display 2x^4 + x^2 + 5.1x + 8.
I have defined "degree" as the following:
(define degree
(lambda(list)
(if (null? list)
(- 1)
(+ 1 (degree (cdr list))))))
Please note I am strictly limited to basic scheme functions
•define, lambda, if, cond, cons,car, cdr, list , member, list-ref
•predicates : null? list? equal? string? number? member?
•arithmetic operators , relational operators, logical operators
•sort, map, filter, foldr, foldl, length, reverse, append, last , let, let*, letrec, print, begin, newline, display, expt, string-append, reduce, range
You need to write some helper functions.
Write a function that given a polynomial returns a list of the degrees.
Input: '(2 0 1 5.1 8)
Output: (4 3 2 1 0)
Write a function mono that given a coefficient and a degree outputs a monomial as a string.
Input: 2 4
Output: "2x^4"
Use (map mono '(2 0 1 5.1 8) (4 3 2 1 0)) to produce a list of the monomials.
Use add-between (or write one yourself) to add "+" between all your monomials.
Use (apply string-append your-list-of-monomials) to get you final string.
Note: It's possible to produce prettier output, but this is a good start.

range based number guessing game

I want to find the difference between two numbers in a range, but I need to be able to wrap around to the beginning of the range, like a circular list.
The range is 9.
So if the number is 6 and the guess is 5 the answer should be 1, but if the number is 8 and the guess is 2, then the answer should be 3.
My first thought was to bump the number by 10 like this:
n is the correct number, g is the guess, r is the result.
( let
[ r (min (- (+ n 10) g) (- g n)) ]
(if (> 0 r) ( * -1 r ) r) )
)
... and that worked for wrapping around, but then the problem is that the existence of the number 10 increases the result by 1 if it wraps. Just subtracting 1 from the result or the number doesn't work either in all cases.
Depending on the numbers in question, the result is negative, so the if statement is to swap it around to positive.
This isn't a clojure problem exactly, it's really a math issue and I'd have this problem in any language, but it so happens that's what I'm writing it in. I've only just started using clojure (or any functional language), so it's entirely possibly I'm doing things wrong or wildly unidiomatic.
thanks for any help
If you include zero in your loop the question becomes smaller of A - B mod R or B - A mod R
R = 9
8 - 3 mod 9 = 5
3 - 8 mod 9 = 4
min(5 3) = 3
You can get the effect of not allowing guesses of zero by decrementing the numbers you read and incramenting the numbers you print though your game will be mathematically easier if you allow them to guess the number zero.
(defn mod- [x y r]
(let [res (rem (- x y) r)]
(if (neg? res)
(+ res r)
res)))
(min (mod- A B r) (mod- B A r))
Are you sure that for the case if the number is 8 and the guess is 2 the answer should be 3 not 6? Provided it's the case what about the following function to calculate the difference:
(defn difference [rrange number-to-guess guess]
(-> rrange
(- guess)
(+ number-to-guess)
(mod rrange)))
Here are the tests.
user=> (= 1 (difference 9 6 5))
true
user=> (= 6 (difference 9 8 2))
true

What determines when a collection is created?

If I understand correctly Clojure can return lists (as in other Lisps) but also vectors and sets.
What I don't really get is why there's not always a collection that is returned.
For example if I take the following code:
(loop [x 128]
(when (> x 1)
(println x)
(recur (/ x 2))))
It does print 128 64 32 16 8 4 2. But that's only because println is called and println has the side-effect (?) of printing something.
So I tried replacing it with this (removing the println):
(loop [x 128]
(when (> x 1)
x
(recur (/ x 2))))
And I was expecting to get some collecting (supposedly a list), like this:
(128 64 32 16 8 4 2)
but instead I'm getting nil.
I don't understand which determines what creates a collection and what doesn't and how you switch from one to the other. Also, seen that Clojure somehow encourages a "functional" way of programming, aren't you supposed to nearly always return collections?
Why are so many functions that apparently do not return any collection? And what would be an idiomatic way to make these return collections?
For example, how would I solve the above problem by first constructing a collection and then iterating (?) in an idiomatic way other the resulting list/vector?
First I don't know how to transform the loop so that it produces something else than nil and then I tried the following:
(reduce println '(1 2 3))
But it prints "1 2nil 3nil" instead of the "1 2 3nil" I was expecting.
I realize this is basic stuff but I'm just starting and I'm obviously missing basic stuff here.
(P.S.: retag appropriately, I don't know which terms I should use here)
A few other comments have pointed out that when doesn't really work like if - but I don't think that's really your question.
The loop and recur forms create an iteration - like a for loop in other languages. In this case, when you are printing, it is indeed just for the side effects. If you want to return a sequence, then you'll need to build one:
(loop [x 128
acc []]
(if (< x 1)
acc
(recur (/ x 2)
(cons x acc))))
=> (1 2 4 8 16 32 64 128)
In this case, I replaced the spot where you were calling printf with a recur and a form that adds x to the front of that accumulator. In the case that x is less than 1, the code returns the accumulator - and thus a sequence. If you want to add to the end of the vector instead of the front, change it to conj:
(loop [x 128
acc []]
(if (< x 1)
acc
(recur (/ x 2)
(conj acc x))))
=> [128 64 32 16 8 4 2 1]
You were getting nil because that was the result of your expression -- what the final println returned.
Does all this make sense?
reduce is not quite the same thing -- it is used to reduce a list by repeatedly applying a binary function (a function that takes 2 arguments) to either an initial value and the first element of a sequence, or the first two elements of the sequence for the first iteration, then subsequent iterations are passed the result of the previous iteration and the next value from the sequence. Some examples may help:
(reduce + [1 2 3 4])
10
This executes the following:
(+ 1 2) => 3
(+ 3 3) => 6
(+ 6 4) => 10
Reduce will result in whatever the final result is from the binary function being executed -- in this case we're reducing the numbers in the sequence into the sum of all the elements.
You can also supply an initial value:
(reduce + 5 [1 2 3 4])
15
Which executes the following:
(+ 5 1) => 6
(+ 6 2) => 8
(+ 8 3) => 11
(+ 11 4) => 15
HTH,
Kyle
The generalized abstraction over collection is called a sequence in Clojure and many data structure implement this abstraction so that you can use all sequence related operations on those data structure without thinking about which data structure is being passed to your function(s).
As far as the sample code is concerned - the loop, recur is for recursion - so basically any problem that you want to solve using recursion can be solved using it, classic example being factorial. Although you can create a vector/list using loop - by using the accumulator as a vector and keep appending items to it and in the exist condition of recursion returning the accumulated vector - but you can use reductions and take-while functions to do so as shown below. This will return a lazy sequence.
Ex:
(take-while #(> % 1) (reductions (fn [s _] (/ s 2)) 128 (range)))

Project Euler #211 - efficiency issue

I've been slowly working my way through the list of Project Euler problems, and I've come to one that I know how to solve, but it seems like I can't (given the way my solution was written).
I am using Common Lisp to do this with and my script has been running for over 24 hours (well over their one minute goal).
For the sake of conciseness, here's my solution (it's a spoiler, but only if you have one hell of a fast processor):
(defun square? (num)
(if (integerp (sqrt num)) T))
(defun factors (num)
(let ((l '()))
(do ((current 1 (1+ current)))
((> current (/ num current)))
(if (= 0 (mod num current))
(if (= current (/ num current))
(setf l (append l (list current)))
(setf l (append l (list current (/ num current)))))))
(sort l #'< )))
(defun o_2 (n)
(reduce #'+ (mapcar (lambda (x) (* x x)) (factors n))))
(defun sum-divisor-squares (limit)
(loop for i from 1 to limit when (square? (o_2 i)) summing i))
(defun euler-211 ()
(sum-divisor-squares 64000000))
The time required to solve the problem using smaller, more friendly, test arguments seems to grow larger than exponentialy... which is a real problem.
It took:
0.007 seconds to solve for 100
0.107 seconds to solve for 1000
2.020 seconds to solve for 10000
56.61 seconds to solve for 100000
1835.385 seconds to solve for 1000000
24+ hours to solve for 64000000
I'm really trying to figure out which part(s) of the script is causing it to take so long. I've put some thought into memoizing the factors function, but I'm at a loss as to how to actually implement that.
For those that want to take a look at the problem itself, here it be.
Any ideas on how to make this thing go faster would be greatly appreciated.
**sorry if this is a spoiler to anyone, it's not meant to be.... but if you have the computing power to run this in a decent amount of time, more power to you.
Here's a solution, keeping in mind the spirit of [Project] Euler. [Warning: spoiler. I've tried to keep the hints slow, so that you can read only part of the answer and think on your own if you want. :)]
When you are confronted with a problem having to do with numbers, one good strategy (as you probably already know from solving 210 Project Euler problems) is to look at small examples, find a pattern, and prove it. [The last part may be optional depending on your attitude to mathematics ;-)]
In this problem, though, looking at small examples -- for n=1,2,3,4,... will probably not give you any hint. But there is another sense of "small examples" when dealing with number-theoretic problems, which you also probably know by now -- primes are the building blocks of the natural numbers, so start with the primes.
For a prime number p, its only divisors are 1 and p, so the sum of the squares of its divisors is 1+p2.
For a prime power pk, its only divisors are 1, p, p2, … pk, so the sum of the squares of its divisors is 1+p+p2+…+pk=(pk+1-1)/(p-1).
That was the simplest case: you've solved the problem for all numbers with only one prime factor.
So far nothing special. Now suppose you have a number n that has two prime factors, say n=pq. Then its factors are 1, p, q, and pq, so the sum of the squares of its divisors is 1+p2+q2+p2q2=(1+p2)(1+q2).
What about n=paqb? What is the sum of the squares of its factors?
[............................Dangerous to read below this line...................]
It is ∑0≤c≤a, 0≤d≤b(pcqd)2 = ((pa+1-1)/(p-1))((qb+1-1)/(q-1)).
That should give you the hint, both on what the answer is and how to prove it: the sum of the divisors of n is simply the product of the (answer) for each of the prime powers in its factorization, so all you need to do is to factorize 64000000 (which is very easy to do even in one's head :-)) and multiply the answer for each (=both, because the only primes are 2 and 5) of its prime powers.
That solves the Project Euler problem; now the moral to take away from it.
The more general fact here is about multiplicative functions -- functions on the natural numbers such that f(mn) = f(m)f(n) whenever gcd(m,n)=1, i.e. m and n have no prime factors in common. If you have such a function, the value of the function at a particular number is completely determined by its values at prime powers (can you prove this?)
The slightly harder fact, which you can try to prove[it's not that hard], is this: if you have a multiplicative function f [here, f(n)=n2] and you define the function F as F(n) = ∑d divides nf(d), (as the problem did here) then F(n) is also a multiplicative function.
[In fact something very beautiful is true, but don't look at it just yet, and you'll probably never need it. :-)]
I think that your algorithm is not the most efficient possible. Hint: you may be starting from the wrong side.
edit: I'd like to add that choosing 64000000 as the upper limit is likely the problem poster's way of telling you to think of something better.
edit: A few efficiency hints:
instead of
(setf l (append l (...)))
you can use
(push (...) l)
which destructively modifies your list by consing a new cell with your value as car and the former l as cdr, then points l to this cell. This is much faster than appending which has to traverse the list once each. If you need the list in the other order, you can nreverse it after it is complete (but that is not needed here).
why do you sort l?
you can make (> current (/ num current)) more efficient by comparing with the square root of num instead (which only needs to be computed once per num).
is it perhaps possible to find the factors of a number more efficiently?
And a style hint: You can put the scope of l into the do declaration:
(do ((l ())
(current 1 (+ current 1)))
((> current (/ num current))
l)
...)
I would attack this by doing the prime factorization of the number (for example: 300 = 2^2 * 3^1 * 5^2), which is relatively fast, especially if you generate this by sieve. From this, it's relatively simple to generate the factors by iterating i=0..2; j=0..1; k=0..2, and doing 2^i * 3^j * 5^k.
5 3 2
-----
0 0 0 = 1
0 0 1 = 2
0 0 2 = 4
0 1 0 = 3
0 1 1 = 6
0 1 2 = 12
1 0 0 = 5
1 0 1 = 10
1 0 2 = 20
1 1 0 = 15
1 1 1 = 30
1 1 2 = 60
2 0 0 = 25
2 0 1 = 50
2 0 2 = 100
2 1 0 = 75
2 1 1 = 150
2 1 2 = 300
This might not be fast enough
The clever trick you are missing is that you don't need to factor the numbers at all
How many numbers from 1..N are multiples of 1? N
How many numbers from 1..N are multiples of 2? N/2
The trick is to sum each number's factors in a list.
For 1, add 1^2 to every number in the list. For 2, add 2^2 to every other number.
For 3, add 3^2 to every 3rd number.
Don't check for divisibility at all.
At the end, you do have to check whether the sum is a perfect square, and that's it.
In C++, this worked in 58 seconds for me.
Sorry, I don't understand LISP well enough to read your answer. But my first impression is that the time cost of the brute force solution should be:
open bracket
sqrt(k) to find the divisors of k (by trial division), square each one (constant time per factor), and sum them (constant time per factor). This is σ2(k), which I will call x.
plus
not sure what the complexity of a good integer square root algorithm is, but certainly no worse than sqrt(x) (dumb trial multiplication). x might well be big-O larger than k, so I reserve judgement here, but x is obviously bounded above by k^3, because k has at most k divisors, each itself no bigger than k and hence its square no bigger than k^2. It's been so long since my maths degree that I have no idea how fast Newton-Raphson converges, but I suspect it's faster than sqrt(x), and if all else fails a binary chop is log(x).
close bracket
multiplied by n (as k ranges 1 .. n).
So if your algorithm is worse than O(n * sqrt(n^3)) = O(n ^ (5/2)), in the dumb-sqrt case, or O(n * (sqrt(n) + log(n^3)) = O(n ^ 3/2) in the clever-sqrt case, I think something has gone wrong which should be identifiable in the algorithm. At this point I'm stuck because I can't debug your LISP.
Oh, I've assumed that arithmetic is constant-time for the numbers in use. It darn well should be for numbers as small as 64 million, and the cube of that fits in a 64bit unsigned integer, barely. But even if your LISP implementation is making arithmetic worse than O(1), it shouldn't be worse than O(log n), so it won't have much affect on the complexity. Certainly won't make it super-polynomial.
This is where someone comes along and tells me just how wrong I am.
Oops, I just looked at your actual timing figures. They aren't worse than exponential. Ignoring the first and last values (because small times aren't accurately measurable and you haven't finished, respectively), multiplying n by 10 multiplies time by no more than 30-ish. 30 is about 10^1.5, which is about right for brute force as described above.
I think you can attack this problem with something like a prime sieve. That's only my first impression though.
I've reworked the program with some notes taken from the comments here. The 'factors' function is now ever so slightly more efficient and I also had to modify the σ_(2)(n) function to accept the new output.
'factors' went from having an output like:
$ (factors 10) => (1 2 5 10)
to having one like
$ (factors 10) => ((2 5) (1 10))
Revised function looks like this:
(defun o_2 (n)
"sum of squares of divisors"
(reduce #'+ (mapcar (lambda (x) (* x x)) (reduce #'append (factors n)))))
After the modest re-writes I did, I only saved about 7 seconds in the calculation for 100,000.
Looks like I'm going to have to get off of my ass and write a more direct approach.

Resources