How can I convert a step-down range to array? [duplicate] - ruby

This question already has answers here:
Is there a reason that we cannot iterate on "reverse Range" in ruby?
(12 answers)
Closed 10 years ago.
I have a range like (1000..0) and I was using each but it does not do anything. I was trying to convert it to an array and got an empty array.
I also tried (1000..0).step(-1).each and it tells me step cant be negative...
Is there any way to use (1000..0).each so it will do the repetition, or convert to an array like [1000,999,998,...,0]?

1000.downto(0).each { |i| ... }

Two ways you might go about doing this:
(0..1000).each do |i|
n = 1000 - i
# Use n for all calculations
end
(0..1000).to_a.reverse.each do |n|
# Involves creating temporary array, but overhead is usually minor for
# relatively small numbers.
end
Don't forget you can also do this without a range:
1001.times do |i|
n = 1000 - i
end

#1000 item array
step_down_array = 1000.step(0, -1).to_a
#small enumerator:
step_down = 1000.step(0, -1)

(0..1000).to_a.reverse
This will create the required array.

Related

How do I iterate through every 2nd element of an array in Ruby? [duplicate]

This question already has answers here:
Looping through an array with step
(7 answers)
Closed 2 years ago.
I would like to do the equivalent of this Java code in Ruby. What is the best way in Ruby to do the below ? I dont want to use the Ruby for loop , want to follow idiomatic Ruby.
for (int i = 0; i < nums.length; i += 2) {
// Do something.
}
Use the "step" method to iterate every 2nd element in the array.
(0..array.length).step(2).each do |i|
puts i
end

How do i print a string with repeated names followed by a number - Ruby? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
How do i print a name Ex. John1 and then print after John2, john3, john4, john5 and so one in an infinite number
I started using ruby today and I'm having some trouble figuring this out. I've searched some but can't find anything so how would I do this?
It's to mass produce accounts to the staff of a certain company and I found ruby to be the smartest to write it in and I will never use it again after this
Keep it simple.
puts (1..5).map { |n| "john#{n}" }
john1
john2
john3
john4
john5
The class Range includes the module Enumerable (as does the classes Array, Hash and others). By doing so, instances of Range (such as 1..5) gain the use of all of Enumerable's instance methods. One of Enumerable's instance methods is used here: Enumerable#map.
For printing a simple series like this:
n = 1
loop do
print 'john%d, ' % n
n += 1
end
That will never terminate, which makes it kind of silly. Maybe what you want is a bounded range:
list = (1..10).map do |n|
'john%d' % n
end.join(', ')
puts list
You can adjust the start and end values as necessary.
Perhaps use an enumerator here:
enum = Enumerator.new do |y|
i = 1
loop do
y << "John#{i}"
i += 1
end
end
enum.next #=> "John1"
enum.next #=> "John2"
enum.next #=> "John3"
Then use any one of the methods available to instances of Enumerator. Here we've used Enumerator#next to get the next "John" string.
One simple way is using a for loop. First declare an empty string variable that will hold our contents.
One important thing to consider is the index of the loop. If it's the last item, we do not want to add a separator like ", "
This is where the conditional comes into play. If the index is less than the last, we will add a comma and space, otherwise just the name.
Interpolation is done by wrapping a variable inside #{ and }
str = ""
for i in 1..5
str += i < 5 ? "john#{i}, " : "john#{i}"
end
Returns
"john1, john2, john3, john4, john5"

how to create 2 dimensional array and store values at run time in ruby [duplicate]

This question already has answers here:
Create two-dimensional arrays and access sub-arrays in Ruby
(9 answers)
Closed 9 years ago.
i created two dimensional array with the following code. but i can not store value in the array. row and columns of array grows dynamically. can not predict before.
arr = Array.new {Array.new}
and can not do this type of things.....
arr[0][0] = "Ruby"
You could create an abstraction over the standard array, like so
class MyArray < Array
def [](idx)
self.at(idx) ? self.at(idx) : self[idx] = []
end
end
Alternatively, you could use a Hash whose default_proc creates a new array at the specified index. OR a hash whose keys are [row, column]. This would be the best option for large datasets as your operations would be in O(1) time.

Ruby Array: Methodology to add numbers [duplicate]

This question already has answers here:
How to sum array of numbers in Ruby?
(16 answers)
Closed 10 years ago.
I'm trying to write code that will take an array and give back the SUM of the array.
First, is this the correct way to place the numbers into an array? It seems like there may be a problem with that based on the error.
def total(num)
x = []
x << num
puts x.inject(0){|a,b|a+b}
end
Looks like a have a few problems here. First, I get this error when I call the method with sum([3,2,41,2]):
`total': wrong number of arguments (5 for 1) (ArgumentError) from calculator.rb:11
I also recall getting a error: cant't covert fixnum into array
Your inject block is correct. Your argument error arises because you defined the method to take a single argument, but in your example, you call it with four arguments. If you want to use a variable number of arguments, you can use the splat operator *, which does various things- in this case, it will gather all undefined arguments into an array:
def total(*nums)
nums.inject(0) {|a,b| a + b }
end
total(3,2,41,2) #=> 48
You can further simplify this using a symbol with inject:
nums.inject(0, :+) #=> 48
This works by sending the method denoted by the symbol to the accumulator, using each member of the array as an argument (equivalent to defining the block as {|a, b| a.send(:+, b) }).
And actually in this case, you don't need to define an initial value. Inject has a third form that will simply use the first member of the array as the initial value and sum the others onto it:
nums.inject(:+)

How to use less memory generating Array permutation?

So I need to get all possible permutations of a string.
What I have now is this:
def uniq_permutations string
string.split(//).permutation.map(&:join).uniq
end
Ok, now what is my problem: This method works fine for small strings but I want to be able to use it with strings with something like size of 15 or maybe even 20. And with this method it uses a lot of memory (>1gb) and my question is what could I change not to use that much memory?
Is there a better way to generate permutation? Should I persist them at the filesystem and retrieve when I need them (I hope not because this might make my method slow)?
What can I do?
Update:
I actually don't need to save the result anywhere I just need to lookup for each in a table to see if it exists.
Just to reiterate what Sawa said. You do understand the scope? The number of permutations for any n elements is n!. It's about the most aggressive mathematical progression operation you can get. The results for n between 1-20 are:
[1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600,
6227020800, 87178291200, 1307674368000, 20922789888000, 355687428096000,
6402373705728000, 121645100408832000, 2432902008176640000]
Where the last number is approximately 2 quintillion, which is 2 billion billion.
That is 2265820000 gigabytes.
You can save the results to disk all day long - unless you own all the Google datacenters in the world you're going to be pretty much out of luck here :)
Your call to map(&:join) is what is creating the array in memory, as map in effect turns an Enumerator into an array. Depending on what you want to do, you could avoid creating the array with something like this:
def each_permutation(string)
string.split(//).permutation do |permutaion|
yield permutation.join
end
end
Then use this method like this:
each_permutation(my_string) do |s|
lookup_string(s) #or whatever you need to do for each string here
end
This doesn’t check for duplicates (no call to uniq), but avoids creating the array. This will still likely take quite a long time for large strings.
However I suspect in your case there is a better way of solving your problem.
I actually don't need to save the result anywhere I just need to lookup for each in a table to see if it exists.
It looks like you’re looking for possible anagrams of a string in an existing word list. If you take any two anagrams and sort the characters in them, the resulting two strings will be the same. Could you perhaps change your data structures so that you have a hash, with keys being the sorted string and the values being a list of words that are anagrams of that string. Then instead of checking all permutations of a new string against a list, you just need to sort the characters in the string, and use that as the key to look up the list of all strings that are permutations of that string.
Perhaps you don't need to generate all elements of the set, but rather only a random or constrained subset. I have written an algorithm to generate the m-th permutation in O(n) time.
First convert the key to a list representation of itself in the factorial number system. Then iteratively pull out the item at each index specified by the new list and of the old.
module Factorial
def factorial num; (2..num).inject(:*) || 1; end
def factorial_floor num
tmp_1 = 0
1.upto(1.0/0.0) do |counter|
break [tmp_1, counter - 1] if (tmp_2 = factorial counter) > num
tmp_1 = tmp_2 #####
end # #
end # #
end # returns [factorial, integer that generates it]
# for the factorial closest to without going over num
class Array; include Factorial
def generate_swap_list key
swap_list = []
key -= (swap_list << (factorial_floor key)).last[0] while key > 0
swap_list
end
def reduce_swap_list swap_list
swap_list = swap_list.map { |x| x[1] }
((length - 1).downto 0).map { |element| swap_list.count element }
end
def keyed_permute key
apply_swaps reduce_swap_list generate_swap_list key
end
def apply_swaps swap_list
swap_list.map { |index| delete_at index }
end
end
Now, if you want to randomly sample some permutations, ruby comes with Array.shuffle!, but this will let you copy and save permutations or to iterate through the permutohedral space. Or maybe there's a way to constrain the permutation space for your purposes.
constrained_generator_thing do |val|
Array.new(sample_size) {array_to_permute.keyed_permute val}
end
Perhaps I am missing the obvious, but why not do
['a','a','b'].permutation.to_a.uniq!

Resources