Why does my function outputting expected and unexpected values in ruby? - ruby

I have a method called fibs_rec that results in an unexpected output:
def fibs_rec(n)
if n == 1 || n == 0
return 1
else
a = fibs_rec(n-1) + fibs_rec(n-2)
puts a
return a
end
end
fibs_rec(5)
The call fibs_rec(5) should return 1,1,2,3,5 but here is the actual output:
2
3
2
5
2
3
8
Not only is the output incorrect, it lacks a number from the beginning.
Can someone explain why is this happening?

This is correct since your recursion is splitting into two sub-problems every time it recurses. If you want the series to appear properly then you should try doing this via dynamic programming for O(n) time complexity. As is, the first and second position won’t be printed because of the base case in the recursion.
As for the incorrect answer, it seems you have not accounted for the sequence starting with 0 index. Either find 4 index in the function which will give the fifth element or modify your function to work with position instead of index.

Related

Input to different attributes values from a random.sample list

so this is what I'm trying to do, and I'm not sure how cause I'm new to python. I've searched for a few options and I'm not sure why this doesn't work.
So I have 6 different nodes, in maya, called aiSwitch. I need to generate random different numbers from 0 to 6 and input that value in the aiSiwtch*.index.
In short the result should be
aiSwitch1.index = (random number from 0 to 5)
aiSwitch2.index = (another random number from 0 to 5 different than the one before)
And so on unil aiSwitch6.index
I tried the following:
import maya.cmds as mc
import random
allswtich = mc.ls('aiSwitch*')
for i in allswitch:
print i
S = range(0,6)
print S
shuffle = random.sample(S, len(S))
print shuffle
for w in shuffle:
print w
mc.setAttr(i + '.index', w)
This is the result I get from the prints:
aiSwitch1 <-- from print i
[0,1,2,3,4,5] <--- from print S
[2,3,5,4,0,1] <--- from print Shuffle (random.sample results)
2
3
5
4
0
1 <--- from print w, every separated item in the random.sample list.
Now, this happens for every aiSwitch, cause it's in a loop of course. And the random numbers are always a different list cause it happens every time the loop runs.
So where is the problem then?
aiSwitch1.index = 1
And all the other aiSwitch*.index always take only the last item in the list but the time I get to do the setAttr. It seems to be that w is retaining the last value of the for loop. I don't quite understand how to
Get a random value from 0 to 5
Input that value in aiSwitch1.index
Get another random value from 0 to 6 different to the one before
Input that value in aiSwitch2.index
Repeat until aiSwitch5.index.
I did get it to work with the following form:
allSwitch = mc.ls('aiSwitch')
for i in allSwitch:
mc.setAttr(i + '.index', random.uniform(0,5))
This gave a random number from 0 to 5 to all aiSwitch*.index, but some of them repeat. I think this works cause the value is being generated every time the loop runs, hence setting the attribute with a random number. But the numbers repeat and I was trying to avoid that. I also tried a shuffle but failed to get any values from it.
My main mistake seems to be that I'm generating a list and sampling it, but I'm failing to assign every different item from that list to different aiSwitch*.index nodes. And I'm running out of ideas for this.
Any clues would be greatly appreciated.
Thanks.
Jonathan.
Here is a somewhat Pythonic way: shuffle the list of indices, then iterate over it using zip (which is useful for iterating over structures in parallel, which is what you need to do here):
import random
index = list(range(6))
random.shuffle(index)
allSwitch = mc.ls('aiSwitch*')
for i,j in zip(allSwitch,index):
mc.setAttr(i + '.index', j)

How does combining these two methods return the value 5?

def add_one(number)
number + 1
end
puts add_one(5)
def add_two(number)
number = add_one(number)
add_one(number)
end
puts add_two(3)
Hello. I completely understand the first method. However, I am now trying to understand combining methods as we can see from method add_two. I am clueless to how the second method can return 5?
From my knowledge, we call the method add_two and pass the number '3' into the argument. From there we get one local variable number with the object 3. From there I do not understand how we can include the add_one method when we haven't defined it below? Can someone walk me through the second method?
Let me help you understand my logic by breaking the components down below:
first method:
add_one(5)
5 + 1 = 6
second method:
add_two(3)
3 = number + 1
number + 1
Am I right by thinking of the second method like this above?
In add_two method, the line number = add_one(number) overrides the value in number with the result of add_one(number):
For example, when you call add_two(3), this happens:
number = add_one(number)
number = add_one(3)
number = 4
On the second line you call add_one again, but with the modified number, that is, it no longer has value 3 it is now 4, as it was overwritten in previous line.
So second line add_one(number) becomes add_one(4), thus the result is 5.
your interpretation of the second function is incorrect.
second method:
add_two(number(3))
number = number(3) + 1 #=> 4
number(4) + 1 #=> 5
the first line in the second function is processed as add_one(number) store result at number so number after that line is now 4 not 3
the second line is processed as add_one(number) and return result which is 5

Optimizing Array Memory Usage

I currently have a very large array of permutations, which is currently using a significant amount of RAM. This is the current code I have which SHOULD:
Count all but the occurrences where more than one '1' exists or three '2's exist in a row.
arr = [*1..3].repeated_permutation(30).to_a;
count = 0
arr.each do |x|
if not x.join('').include? '222' and x.count(1) < 2
count += 1
end
end
print count
So basically this results in a 24,360 element array, each of which have 30 elements.
I've tried to run it through Terminal but it literally ate through 14GB of RAM, and didn't move for 15 minutes, so I'm not sure whether the process froze while attempting to access more RAM or if it was still computing.
My question being: is there a faster way of doing this?
Thanks!
I am not sure what problem you try to solve. If your code is just an example for a more complex problem and you really need to check programatically every single permumation, then you might want to experiment with lazy:
[*1..3].repeated_permutation(30).lazy.each do ||
# your condition
end
Or you might want to make the nested iteratior very explicit:
[1,2,3].each do |x1|
[1,2,3].each do |x2|
[1,2,3].each do |x3|
# ...
[1,2,3].each do |x30|
permutation = [x1,x2,x3, ... , x30]
# your condition
end
end
end
end
end
But it feels wrong to me to solve this kind of problem with Ruby enumerables at all. Let's have a look at your strings:
111111111111111111111111111111
111111111111111111111111111112
111111111111111111111111111113
111111111111111111111111111121
111111111111111111111111111122
111111111111111111111111111123
111111111111111111111111111131
...
333333333333333333333333333323
333333333333333333333333333331
333333333333333333333333333332
333333333333333333333333333333
I suggest to just use enumerative combinatorics. Just look at the patterns and analyse (or count) how often your condition can be true. For example there are 28 indexes in your string at which a 222 substring could be place, only 27 for the 2222 substring... If you place a substring how likely is it that there is no 1 in the other parts of the string?
I think your problem is a mathematics problem, not a programming problem.
NB This is an incomplete answer, but I think the idea might give a push to the proper solution.
I can think of a following approach: let’s represent each permutation as a value in ternary number base, padded by zeroes:
1 = 000..00001
2 = 000..00002
3 = 000..00010
4 = 000..00011
5 = 000..00012
...
Now consider we restated the original task, treating zeroes as ones, ones as twos and twos as threes. So far so good.
The whole list of permutations would be represented by:
(1..3**30-1).map { |e| x = e.to_s(3).rjust(30, '0') }
Now we are to apply your conditions:
def do_calc permutation_count
(1..3**permutation_count-1).inject do |memo, e|
x = e.to_s(3).rjust(permutation_count, '0')
!x.include?('111') && x.count('0') < 2 ? memo + 1 : memo
end
Unfortunately, even for permutation_count == 20 it takes more than 5 minutes to calculate, so probably some additional steps are required. I will be thinking of further optimization. Currently I hope this will give you a hint to find the good approach yourself.

Beginner array iteration & error code interpretation

I kept getting the following error. After some research I assumed this is because my array access was throwing the error due to (mistakenly) having a NIL value.
my_solution.rb:24:in `count_between': undefined method `>=' for nil:NilClass
(NoMethodError) from my_solution.rb:35:in `<main>'
I'm new to reading error codes, so perhaps that's where I went wrong. But it got tunnel vision on line 24, as the error suggested. However I couldn't fix it, so out of desperation I wound up randomly changing the (<=) on line 23 to just (<). This fixed it.
Why did this fix it? My only guess is that originally using (<=) made it iterate "too far" and thus somehow returned NIL?
Why did the error code say it was the element on line 24 causing the issue, when it was actually the element on line 23? I'm new and am trying to be less intimated by error codes, so this was a curious experience.
Thanks for any guidance.
# count_between is a method with three arguments:
# 1. An array of integers
# 2. An integer lower bound
# 3. An integer upper bound
#
# It returns the number of integers in the array between the lower and upper
# bounds,
# including (potentially) those bounds.
#
# If +array+ is empty the method should return 0
# Your Solution Below:
def count_between(list_of_integers, lower_bound, upper_bound)
if list_of_integers.empty?
return 0
else
count = 0
index = 0
##line 23##
while index <= list_of_integers.length
##line24##
if list_of_integers[index] >= lower_bound &&
list_of_integers[index] <= upper_bound
count += 1
index += 1
else
index += 1
end
end
return count
end
end
puts count_between([1,2,3], 0, 100)
The last index that's <= list_of_integers.length is outside of the array, since the first index of an array is 0 and the last is array.length - 1.
The reason your error says line 24 is that line 23 works fine --- it just computes that the value of index is less than or equal to the the length of the array. Once you try and reference the element at that index in the array, however, it's assigned nil - and you can't perform a >= operation on nil.
One thing that might be helpful here is firing up an irb. If you try to reference an element that's out of bounds, you'll just get nil. If you try and perform an operation (that's not listed in nil.methods) on that same reference, it'll throw the error you're seeing.

euler project 3 ruby> why does this solution work?

def large_prime(n)
return [] if n==1
factor = (2..n).find {|x| n % x == 0}
[factor] + large_prime(n/factor)
end
I got this solution from somewhere else. I don't understand the 4th line of code where large_prime is called recursively and appended onto factor.
When I change the first line "return []" and leave out the '[]' after the return, I get an error message for on line 4, that says '+':no implicit conversion of nil into Array.
So why does this code work? Thanks
P.S. I'm obviously a noob and everything is very new to me.
The 3rd line finds the first divisor of n between 2 and n. This line itself does not involve recursion.
I don't really get the code you modified, but it seems to return nil in some case, while the original method always return an Array.
You must return an empty array when passed 1 to terminate the recursion. Any positive argument other than one will result in another call to large_prime, but an argument of 1 results in large_prime simply returning an empty array.
At each level of recursion, the program adds an array with the single factor it found to an array consisting of all factors found for the value n/factor. When the last factor (other than 1) is found, the final call to large_prime is made with an argument of 1, large_prime returns an empty array which is then added to the array containing the last factor, giving an array containing just the last factor. This array is then returned and you have
[next-to-last-factor] + [last-factor], giving a return array of [next-to-last-factor, last-factor] which is added to [next-to-next-to-last-factor] giving [next-to-next-to-last-factor, next-to-last-factor, last-factor]. This is then added to an array [next-to-next-to-next-to-last-factor], giving... lather, rinse, repeat until we reach the largest factor and add it in.
You must return an empty array because you can't add nil to an array in Ruby.

Resources