Is there a simple function in ruby to create sequences? For example, I want a sequence from 1 to 100 incrementing by 3. So
Function(1,100,increment = 3) = [1,4,7,10, ...,97,100]
Thanks!
Range#step generates another enumerator with given step.
say (1..100).step(3).to_a would be [1,4,7, ... , 97, 100]
alternatively
Numeric#step(limit,step) does similar things,
say 1.step(100,3).to_a
Related
I want to use the functional "reduce" function to calculate things, such as the factorial of a number. e.g. The factorial of 5 is 5x4x3x2x1 = 120. In Ruby I can do it with something like:
# factorial1.rb
(1..5).reduce{|accumulator,element| accumulator*element}
In PowerShell I would do something like:
# factorial.ps
# ------ Install this library before using the "reduce" function
# Install-Module -Name functional
1..5 | reduce {$a*$b}
In both languages, the answer is 120, and the accumulator is assumed to be an integer, with an
initial value of the first element in the range.
If I redefined the factorial to have an initial value of 10, in Ruby I
would code it as
# factorial2.rb
# (1..5).reduce {|accumulator,element| accumulator*element} #uninitialized accumulator
(1..5).reduce(10){|accumulator,element| accumulator*element}
This yields the expected answer of 1200.
QUESTION 1: How does one initialize a "reduce" accumulator in PowerShell?
In the next scenario, I want to generate a list of factorials. If
I were to code it in Ruby, I could initialize the reduce accumulator
with [1] (because 0! is 1), resulting in the following code:
# factorial.rb
# (1..5).reduce {|accumulator,element| accumulator*element} #uninitialized accumulator
(1..5).reduce([1]){|accumulator,element| accumulator << accumulator[-1]*element}
The output looks something like
=> [1, 1, 2, 6, 24, 120]
QUESTION 2: How does one use an expandable array to initialize the accumulator for the
PowerShell "reduce" function of the "functional" module?
These questions are specific to the third party functional module that you downloaded assumely from the PS Gallery. Being at under 300 downloads and only a couple commits on GitHub this appears to be a very small project.
I took a quick look at the code base and didn't see a way to do what you were looking for, but functional programming isn't my forte. Maybe you can find what you are looking for in the code base and I just missed it.
Otherwise finding a different third-party module or filling a feature request might be other avenues to pursue.
Using the same reduce-object cmdlet from the functional module, getting a list of accumulated values of a factorial would be:
# 1..10 | %{ 1..$_ | Reduce-Object { $a * $b } }
1
2
6
24
120
720
5040
40320
362880
3628800
I have no idea of how to proceed, I've been learning ruby for just one week. I thought I'd create an array filled by an external source, such as a database and forbid these elements inside to be picked up by the script. Is it possible? I just want to have a general idea of how creating such script.
Do you mean some thing like this?
forbidden_numbers = [ 5 , 6 , 3 , 4]
new_number = loop do
tmp_number = rand 1_000_000
break tmp_number unless forbidden_numbers.include?(tmp_number)
end
puts new_number
In general, you have two choices:
Remove the ineligible elements, then choose one at random:
arr.reject {...}.sample
Choose an element at random. If it is disallowed, repeat, continuing until a valid element is found:
until (n=arr.sample) && ok?(n) end
n
Without additional information we cannot say which approach is best in this case.
I'm looking to extract n random key-value pairs from a hash.
Hash[original_hash.to_a.sample(n)]
For Ruby 2.1,
original_hash.to_a.sample(n).to_h
I don't know of such method. Still you can do something like:
h[h.keys.sample]
If you need to sample more than one element the code will have to be a bit more complicated.
EDIT: to get key value pairs instead of only the value you can do something like:
keys_sample = h.keys.sample(n)
keys_sample.zip(keys_sample.map{|k| h[k])
Reading the top ranked answers, I'd go with it depends:
If you want to sample only one element from the hash, #Ivaylo Strandjev's solution only relies on hash lookup and Array#sample:
hsh[hsh.keys.sample]
To sample multiple hash elements, #sawa's answer leverages Array#to_h:
hsh.to_a.sample(n).to_h
Note that, as #cadlac mentions, hsh.to_a.sample.to_h won't work as expected. It will raise
TypeError: wrong element type String at 0 (expected array)
because Array#sample in this case returns just the element array, and not the array containing the element array.
A workaround is his solution, providing an n = 1 as an argument:
hsh.to_a.sample(1).to_h
PS: not looking for upvotes, only adding it as an explanation for people newer to Ruby.
If your sample has only one element, you could use this:
sample = h.keys.sample
h.select { |k,v| k == sample }
Or if your sample contains more than one element, use this:
n = 2
sample = h.keys.sample(n)
h.select { |k,v| sample.include?(k) }
One way to accomplish this:
rank_hash = {"Listen" => 1, "Download" => 60, "Share" => 150, "Purchase" => 700 }
rank_array = rank_hash.to_a
Than call this to get random array sample of the k/v pair:
rank_array[rand(0..3)]
or this to not hard-code the arrays length:
rank_array[rand(0..(rank_array.length) -1)]
Example:
["Download", 60]
I'm attempting to solve http://projecteuler.net/problem=1.
I want to create a method which takes in an integer and then creates an array of all the integers preceding it and the integer itself as values within the array.
Below is what I have so far. Code doesn't work.
def make_array(num)
numbers = Array.new num
count = 1
numbers.each do |number|
numbers << number = count
count = count + 1
end
return numbers
end
make_array(10)
(1..num).to_a is all you need to do in Ruby.
1..num will create a Range object with start at 1 and end at whatever value num is. Range objects have to_a method to blow them up into real Arrays by enumerating each element within the range.
For most purposes, you won't actually need the Array - Range will work fine. That includes iteration (which is what I assume you want, given the problem you're working on).
That said, knowing how to create such an Array "by hand" is valuable learning experience, so you might want to keep working on it a bit. Hint: you want to start with an empty array ([]) instead with Array.new num, then iterate something num.times, and add numbers into the Array. If you already start with an Array of size num, and then push num elements into it, you'll end up with twice num elements. If, as is your case, you're adding elements while you're iterating the array, the loop never exits, because for each element you process, you add another one. It's like chasing a metal ball with the repulsing side of a magnet.
To answer the Euler Question:
(1 ... 1000).to_a.select{|x| x%3==0 || x%5==0}.reduce(:+) # => 233168
Sometimes a one-liner is more readable than more detailed code i think.
Assuming you are learning Ruby by examples on ProjectEuler, i'll explain what the line does:
(1 ... 1000).to_a
will create an array with the numbers one to 999. Euler-Question wants numbers below 1000. Using three dots in a Range will create it without the boundary-value itself.
.select{|x| x%3==0 || x%5==0}
chooses only elements which are divideable by 3 or 5, and therefore multiples of 3 or 5. The other values are discarded. The result of this operation is a new Array with only multiples of 3 or 5.
.reduce(:+)
Finally this operation will sum up all the numbers in the array (or reduce it to) a single number: The sum you need for the solution.
What i want to illustrate: many methods you would write by hand everyday are already integrated in ruby, since it is a language from programmers for programmers. be pragmatic ;)
I am trying to convert words/strings to numbers in Ruby for example:-
ONE => 1
TWO => 2
THREE => 3
FOUR => 4
etc...
I have seen many examples other way around (numbers to words); however, I am not been able to find an example of how to convert words to numbers. It would be great if I can get any insight or help on this.
This might help: http://www.rubyquiz.com/quiz25.html
EDIT: read the question incorrectly. As per my comment below, here's a way you could approach this.
If num_to_word(number) is your method of converting from a number to a word:
def number_hash_creator(min, max)
number_hash = {}
for num in (min..max)
number_hash[num_to_word(num)] == num
end
number_hash
end
Then do something like:
number_hash = number_hash_creator(min, max) # min and max are whatever you need them to be
number_hash['three']
=> 3
You could also append a similar method to the string class so that you could do things like "three".to_number
I created a hash up-to twenty for all words and only for tens(thirty, forty, fifty etc.). Using Reg-ex took off two words and added them for example twenty two is addition of 20+2=22; right now my script only works till hundred, but it can be extended for numbers over 100 and so on.
I think you will find this tutorial very interesting particularly the code near the bottom:
http://pine.fm/LearnToProgram/?Chapter=08