Fibonacci number on a range (ruby) - ruby

Could someone give me a brief explanation as to why n+(n-1) doesn't work? Mathematically it does but i'm not sure how to tell ruby this is what i'm looking for? As the title suggests, the code is supposed to return a Fibonacci sequence.
startyear = []
(1..100).each do |n|
puts n+(n-1)
startyear.push(n)
end

n+(n-1) = 2n-1. Your code is simply displaying 2n-1 (1,3,5,7,..,199).
On the other hand, startyear.push(n) is pushing numbers (1,2,3,.,100) into the startyear array. I think you meant to do something like this.
startyear = [1,1]
(2..100).each do |n|
puts (new_num = startyear[n-1] + startyear[n-2])
startyear.push(new_num)
end
But again, I'm not 100% sure what the range stands for in your code, so I might be wrong.

Related

How do I create an exponential distribution in Ruby with the distribution gem?

I need the mean to be 2, with starting at 1 up to 10,000 random numbers.
require 'distribution'
mean = 2
# generate a rng with exponential distribution
rng = Distribution::Exponential.rng(mean)
Well, I'm not much of a statistician, so I'm a little lost in the code here.
Can you tell me, then, is the first parameter to rng (it is named l) supposed to stand for "limit"?
If so, I don't really know, I'm getting the same sort of results that you must be getting, but again, I'm not a statistician or even a mathematician, I just like to code, so I am probably not of too much help.
EDIT: So, again, I dont really know what is going on or is supposed to be going on here. Here is what gives me a relatively close mean of 2 (I got this just by messing around with the l value):
require 'distribution'
rng=Distribution::Exponential.rng(0.5)
sum=0
1000.times { sum += rng.call }
sum /= 1000
puts sum
Seems to give a value generally between 1.9 and 2.1. Hope this helps :)
PRINT EACH VALUE:
require 'distribution'
rng = Distribution::Exponential.rng(0.5)
values = [] # we'll store each value in an array
# calculate the results
how_many = 1000 # let's store 1000 in a variable since we'll reuse the value
how_many.times { values << rng.call } # rng is now a Proc, so we use call to get our value
# print out the results
values.each_with_index { |v,i| puts "#{i+1}: #{v}" } # print each value one by one
puts
puts "Total sum: #{values.inject(&:+)}"
puts "Mean: #{values.inject(&:+)/how_many}"
Again, not sure if this is exactly "right" or what you're looking for, but it definitely seems to approach 2. Try a bigger number than 1000, like 100000.

Ruby for loop gives Nil class error when assigning array values

I have a problem. I'm coding up a plug in for Google Sketchup and I'm trying to filter out array value and place the filtered values into another array. This is done like this:
for z in 0..points.length
points2[z]=points[z][1]
end
Where "points" is a double array. Can someone please tell me what I'm doing wrong?
This should be better:
points2 = points.map {|p| p[1]}
What you are doing wrong is looping once to much. Using fake data:
ar = [1,2,3]
ar2 = []
for z in 0..ar.length
#off by one! Should be one less. But then you should test for empty arrays...
ar2[z] = ar[z]
end
p ar2 #[1, 2, 3, nil]
The other answers advocate map and they are right, but you could transform the for-loop into a less error-prone one like this:
for z in ar
ar2 << z
end
What you are doing wrong? Fan of for loop that I am, you should use functional style, aka. Ruby way:
points2 = points.map { |element| element[1] }
Otherwise, you would have to post better example if you want people to diagnose your for loop.

Ruby shortest way to write rnd hex

What I have is a method used to generate random hex values. E.g 666 or FF7
However, I don't think it looks simple/elegant at all.. What I want is to make it more simple which perhaps will make my code shorter as well, but I don't know how. That is why I need tips or hints
Here is my code so far:
def random_values
random_values = Array.new
letters = ['A','B','C','D','E','F']
for i in 1..15
if i <= 9
random_values << i
else
random_values << letters[i-10]
end
end
return random_values.shuffle[0].to_s + random_values.shuffle[0].to_s + random_values.shuffle[0].to_s
end
As you probably see, I do not generate random numbers. I just shuffle the array containing the values I want, meaning all the numbers in the array are unique, which is not needed, but was the easiest solution for me when I wrote the code.
I am most concerned about the return line.. If only it was possible to write like:
return 3.times { random_values.shuffle[0] }
or
return random_values.shuffle[0].to_s *3
Thanks in advance!
def random_value
r = Random.new
((r.rand * 16)).to_i.to_s(16)
end
puts random_value + random_value + random_value
Or, after some quick research:
"%06x" % (rand * 0xffffff)
From Ruby, Generate a random hex color
Also, you shouldn't be looking for a more efficient solution per se. You seem to be looking for something more elegant, simple, and intuitive. (My solution is none of these, by the way. The searched one is.)
# For Ruby 1.9
require 'securerandom'
SecureRandom.hex(16)
# For Ruby 1.8 and above
require 'active_support/secure_random'
ActiveSupport::SecureRandom.hex(16)
Something like this?
(rand * MAX_VALUE).to_i.to_s(16)
Where MAX_VALUE is the upper bound for the numbers. You can also add some lower bound:
(MIN_VALUE + rand * (MAX_VALUE - MIN_VALUE)).to_i.to_s(16)
This will give you numbers in the range [MIN_VALUE,MAX_VALUE)

Problem comprehending C-style ruby loops

I find the .each do hard to get to stick, so I was hoping for regular use of C for loop syntax which seems to not work, so I tried a while but still get errors.
I have tried this.
i = 0
while i < SampleCount
samples[i] = amplitude
amplitude *= -1
i++
end
I get complaints about the end statement here.
There are several problems with your code. Rather than just fixing the errors, I'd suggest it's better long-term for you to learn the Ruby way - it will save you time and energy later. In this case, it's
5.times do |i|
samples[i] = amplitude # assumes samples already exists and has 5 entries.
amplitude *= -1
end
If you insist on keeping a similar style, you can do this:
samples = []
i = 0
while i < sample_count
samples << amplitude # add new item to array.
amplitude *= -1
i += 1 # you can't use ++.
end
Note that SampleCount's initial capital letter, by Ruby convention, means a constant, which I'm guessing isn't what you really mean.
I agree with Peter that there are other (more idiomatic) ways to do this in Ruby, but just to be clear: the error message you saw misdirected you. There wasn't anything wrong with your while loop per se. The problem was i++ since there is no ++ operator in Ruby.
This would work just fine:
limit = 10
i = 0
while i < limit
puts i
i += 1
end
Again, I'm not recommending it, but if you're just learning the language, it may help to know where the problem really was.
Ruby has a lot of built-in ways to iterate other than for or while (which tend to be seen less often, as far as I can tell). A few other examples:
(1..10).each do |x| # 1..10 is a range which you can iterate over with each
puts x
end
1.upto(10) { |x| puts x } # Integers have upto and downto methods that can be useful
You originally mentioned trying to use a for loop. Notwithstanding the various other comments in the answers, here's the for loop approach:
for i in 0...5
samples[i] = amplitude
amplitude *= -1
end
Nobody here has actually offered an alternate solution that actually does what Fred originally intended - and that's iterate around the value of the constant SampleCount. So could you do:
SampleCount.times do |i|
Or:
limit = SampleCount
limit.times do |i|
Or:
for i in 0..SampleCount
Would any of those be Ruby-esque enough?
The problem with the end statement is related to i++. Ruby wants to add something. There is no increment operator in Ruby. You need to use i += 1. With that change you can use your C style loop as is.

How to return a Ruby array intersection with duplicate elements? (problem with bigrams in Dice Coefficient)

I'm trying to script Dice's Coefficient, but I'm having a bit of a problem with the array intersection.
def bigram(string)
string.downcase!
bgarray=[]
bgstring="%"+string+"#"
bgslength = bgstring.length
0.upto(bgslength-2) do |i|
bgarray << bgstring[i,2]
end
return bgarray
end
def approx_string_match(teststring, refstring)
test_bigram = bigram(teststring) #.uniq
ref_bigram = bigram(refstring) #.uniq
bigram_overlay = test_bigram & ref_bigram
result = (2*bigram_overlay.length.to_f)/(test_bigram.length.to_f+ref_bigram.length.to_f)*100
return result
end
The problem is, as & removes duplicates, I get stuff like this:
string1="Almirante Almeida Almada"
string2="Almirante Almeida Almada"
puts approx_string_match(string1, string2) => 76.0%
It should return 100.
The uniq method nails it, but there is information loss, which may bring unwanted matches in the particular dataset I'm working.
How can I get an intersection with all duplicates included?
As Yuval F said you should use multiset. However, there is nomultiset in Ruby standard library , Take at look at here and here.
If performance is not that critical for your application, you still can do it usingArray with a little bit code.
def intersect a , b
a.inject([]) do |intersect, s|
index = b.index(s)
unless index.nil?
intersect << s
b.delete_at(index)
end
intersect
end
end
a= ["al","al","lc" ,"lc","ld"]
b = ["al","al" ,"lc" ,"ef"]
puts intersect(a ,b).inspect #["al", "al", "lc"]
From this link I believe you should not use Ruby's sets but rather multisets, so that every bigram gets counted the number of times it appears. Maybe you can use this gem for multisets. This should give a correct behavior for recurring bigrams.
I toyed with this, based on the answer from #pierr, for a while and ended up with this.
a = ["al","al","lc","lc","lc","lc","ld"]
b = ["al","al","al","al","al","lc","ef"]
result=[]
h1,h2=Hash.new(0),Hash.new(0)
a.each{|x| h1[x]+=1}
b.each{|x| h2[x]+=1}
h1.each_pair{|key,val| result<<[key]*[val,h2[key]].min if h2[key]!=0}
result.flatten
=> ["al", "al", "lc"]
This could be a kind of multiset intersect of a & b but don't take my word for it because I haven't tested it enough to be sure.

Resources