Related
I am asked to write some code in Ruby that iterates over every n-th element of an array and prints it until all elements of the array are printed.
The question reads:
Imagine an iterator that accesses an array in strides and runs some code at each stride. If the strides reach the end of the array then they simply begin anew from the array's beginning.
For example:
x = [0,1,2,3,4]
x.stride(1) do |elem|; puts elem; end # prints 0,1,2,3,4
x.stride(2) do |elem|; puts elem; end # prints 0,2,4,1,3
x.stride(8) do |elem|; puts elem; end # prints 0,3,1,4,2
[].stride(2) do |elem|; puts elem; end # does not print anything, but the code is correct
Assume that the stride is equal or greater than 1, and that both the stride and the array's size are not a integral/whole multiple of each other, meaning that the whole array can be printed using a given stride. Fill in the code that's missing:
class Array
def stride(step)
numelems = ... # size of the array
...
end
end
It is obvious that numelemns = self.length(). However am having trouble with the rest.
I am going to try writing some code in Python that accomplishes this task, but I am afraid that I will not be able to translate it to Ruby.
Any ideas? The answer should not be more than 4-5 lines long as the question is one that our proffessor gave us to solve in a couple of minutes.
A solution to this is provided below (thanks #user3574603):
class Array
def stride(step)
yield self[0]
(self * step).map.with_index do |element, index|
next element if index == 0
yield element if index % step == 0
end
end
end
The following assumes that arr.size and n are not both even numbers and arr.size is not a multiple of n.
def striding(arr, n)
sz = arr.size
result = '_' * sz
idx = 0
sz.times do
result[idx] = arr[idx].to_s
puts "S".rjust(idx+1)
puts result
idx = (idx + n) % sz
end
end
striding [1,2,3,4,5,6,7,8,9,1,2,3,4,5,6], 7
S
1______________
S
1______8_______
S
1______8______6
S
1_____78______6
S
1_____78_____56
S
1____678_____56
S
1____678____456
S
1___5678____456
S
1___5678___3456
S
1__45678___3456
S
1__45678__23456
S
1_345678__23456
S
1_345678_123456
S
12345678_123456
S
123456789123456
Here is an example where arr.size is a multiple of n.
striding [1,2,3,4,5,6], 3
S
1_____
S
1__4__
S
1__4__
S
1__4__
S
1__4__
S
1__4__
Here is an example where arr.size and n are both even numbers.
striding [1,2,3,4,5,6,7,8], 6
S
1_______
S
1_____7_
S
1___5_7_
S
1_3_5_7_
S
1_3_5_7_
S
1_3_5_7_
S
1_3_5_7_
S
1_3_5_7_
Imagine an iterator that accesses an array in strides and runs some code at each stride. If the strides reach the end of the array then they simply begin anew from the array's beginning.
Based on this specification, stride will always iterate forever, unless the array is empty. But that is not a problem, since we can easily take only the amount of elements we need.
In fact, that is a good design: producing an infinite stream of values lets the consumer decide how many they need.
A simple solution could look like this:
module CoreExtensions
module EnumerableExtensions
module EnumerableWithStride
def stride(step = 1)
return enum_for(__callee__, step) unless block_given?
enum = cycle
loop do
yield(enum.next)
(step - 1).times { enum.next }
end
self
end
end
end
end
Enumerable.include(CoreExtensions::EnumerableExtensions::EnumerableWithStride)
A couple of things to note here:
I chose to add the stride method to Enumerable instead of Array. Enumerable is Ruby's work horse for iteration and there is nothing in the stride method that requires self to be an Array. Enumerable is simply the better place for it.
Instead of directly monkey-patching Enumerable, I put the method in a separate module. That makes it easier to debug code for others. If they see a stride method they don't recognize, and inspect the inheritance chain of the object, they will immediately see a module named EnumerableWithStride in the inheritance chain and can make the reasonable assumption that the method is probably coming from here:
[].stride
# Huh, what is this `stride` method? I have never seen it before.
# And it is not documented on https://ruby-doc.org/
# Let's investigate:
[].class.ancestors
#=> [
# Array,
# Enumerable,
# CoreExtensions::EnumerableExtensions::EnumerableWithStride,
# Object,
# Kernel,
# BasicObject
# ]
# So, we're confused about a method named `stride` and we
# found a module whose name includes `Stride`.
# We can reasonably guess that somewhere in the system,
# there must be a file named
# `core_extensions/enumerable_extensions/enumerable_with_stride.rb`.
# Or, we could ask the method directly:
meth = [].method(:stride)
meth.owner
#=> CoreExtensions::EnumerableExtensions::EnumerableWithStride
meth.source_location
#=> [
# 'core_extensions/enumerable_extensions/enumerable_with_stride.rb',
# 6
# ]
For an empty array, nothing happens:
[].stride(2, &method(:p))
#=> []
stride just returns self (just like each does) and the block is never executed.
For a non-empty array, we get an infinite stream of values:
x.stride(&method(:p))
# 0
# 1
# 2
# 3
# 4
# 0
# 1
# …
x.stride(2, &method(:p))
# 0
# 2
# 4
# 1
# 3
# 0
# 2
# …
x.stride(8, &method(:p))
# 0
# 3
# 1
# 4
# 2
# 0
# 3
# …
The nice thing about this infinite stream of values is that we, as the consumer can freely choose how many elements we want. For example, if I want 10 elements, I simply take 10 elements:
x.stride(3).take(10)
#=> [0, 3, 1, 4, 2, 0, 3, 1, 4, 2]
This works because, like all well-behaved iterators, our stride method returns an Enumerator in case no block is supplied:
enum = x.stride(2)
#=> #<Enumerator: ...>
enum.next
#=> 0
enum.next
#=> 2
enum.next
#=> 4
enum.next
#=> 1
enum.next
#=> 3
enum.next
#=> 0
enum.next
#=> 2
So, if we want to implement the requirement "until all the elements of the array are printed":
I am asked to write some code in Ruby that iterates over every n-th element of an array and prints it until all elements of the array are printed.
We could implement that something like this:
x.stride.take(x.length).each(&method(:p))
x.stride(2).take(x.length).each(&method(:p))
x.stride(8).take(x.length).each(&method(:p))
This is a pretty simplistic implementation, though. Here, we simply print as many elements as there are elements in the original array.
We could implement a more sophisticated logic using Enumerable#take_while that keeps track of which elements have been printed and which haven't, and only stops if all elements are printed. But we can easily prove that after x.length iterations either all elements have been printed or there will never be all elements printed (if the stride size is an integral multiple of the array length or vice versa). So, this should be fine.
This almost does what I think you want but breaks if the step is array.length + 1 array.length (but you mention that we should assume the stride is not a multiply of the array length).
class Array
def exhaustive_stride(step)
(self * step).map.with_index do |element, index|
next element if index == 0
element if index % step == 0
end.compact
end
end
x.exhaustive_stride 1
#=> [0, 1, 2, 3, 4]
x.exhaustive_stride 2
#=> [0, 2, 4, 1, 3]
x.exhaustive_stride 8
#=> [0, 3, 1, 4, 2]
[].exhaustive_stride 2
#=> []
Using the example array, it breaks when the stride is 5.
[0,1,2,3,4].exhaustive_stride 5
#=> [0, 0, 0, 0, 0]
Note
This works but the intermediate array makes it highly inefficient. Consider other answers.
Here's another solution that uses recursion. Not the most efficient but one way of doing it.
class Array
def exhaustive_stride(x, r = [])
return [] if self.empty?
r << self[0] if r.empty?
while x > self.length
x -= self.length
end
r << self[x]
x += x
return r if r.count == self.count
stride(x, r)
end
end
[0,1,2,3,4].exhaustive_stride 1
#=> [0, 1, 2, 4, 3]
[0,1,2,3,4].exhaustive_stride 2
#=> [0, 2, 4, 3, 1]
[0,1,2,3,4].exhaustive_stride 8
#=> [0, 3, 1, 2, 4]
[].exhaustive_stride 2
#=> []
[0,1,2,3,4].exhaustive_stride 100_000_001
#=> [0, 1, 2, 4, 3]
This would work:
def stride(ary, step)
raise ArgumentError unless step.gcd(ary.size) == 1
Array.new(ary.size) { |i| ary[(i * step) % ary.size] }
end
Example:
x = [0, 1, 2, 3, 4]
stride(x, 1) #=> [0, 1, 2, 3, 4]
stride(x, 2) #=> [0, 2, 4, 1, 3]
stride(x, 8) #=> [0, 3, 1, 4, 2]
stride(x, -1) #=> [0, 4, 3, 2, 1]
First of all, the guard clause checks whether step and ary.size are coprime to ensure that all elements can be visited via step.
Array.new(ary.size) creates a new array of the same size as the original array. The elements are then retrieved from the original array by multiplying the element's index by step and then performing a modulo operation using the array's size.
Having % arr.size is equivalent to fetching the elements from a cyclic array, e.g. for a step value of 2:
0 1 2 3 4
| | | | |
[0, 1, 2, 3, 4, 0, 1, 2, 3, 4, ...
To turn this into an instance method for Array you merely replace ary with self (which can be omitted most of the time):
class Array
def stride(step)
raise ArgumentError unless step.gcd(size) == 1
Array.new(size) { |i| self[(i * step) % size] }
end
end
I am currently learning Ruby and am lost a bit.
This Python snippet:
n = iter([1,2,3,4,5])
for x in n:
print(x)
y = next(n)
print(y)
gives:
1
2
3
4
5
And I'm trying to do the same in Ruby, which is not working:
n = [1,2,3,4,5].each
for x in n do
puts x
y = n.next()
puts y
end
How do I need to write the Python example in Ruby?
You have the right idea except Ruby keeps track of the position of the enumerator internally. Try this:
enum = [1,2,3,4,5].each
#=> #<Enumerator: [1, 2, 3, 4, 5]:each>
loop do
puts enum.next
puts enum.next
end
1
2
3
4
5
Enumerator#next raises a StopInteration exception when invoked after all elements of the enumerator enum have been generated. Kernel#loop handles the exception by breaking out of the loop.
Note that Array#each, without the optional block, has the same effect as Object#to_enum. Also, though authors of Ruby books feel an obligation to cover for loops (seemingly, on page one), they are never used in practice.
In Python the iterator n obtained applying the function iter() can be consumed once.
array = [1,2,3,4,5]
n = iter(array)
for x in n:
print(x)
# 1
# 2
# 3
# 4
# 5
If you then call next(n) you get no output but error: StopIteration. If you try to iterate n again you get no output (no error, the for loop hanldes the exception).
But you can iterate over the array:
for x in array:
print(x)
If you check the output a code like yours, you get:
n = iter([1,2,3,4,5])
for x in n:
print('odd_', x)
y = next(n)
print('even', y)
# odd_ 1
# even 2
# odd_ 3
# even 4
# odd_ 5
# StopIteration
As pointed by #toniedzwiedz Object#to_enum is the equivalent for the Python iter(), so you can call Enumerator#next on it.
In Ruby you can consume more than once the enumerator:
array = [1, 2, 3, 4, 5]
n = array.to_enum
# n = array.each # each returns an Enumerable
for x in n do
puts x
end
for x in n do
puts x
end
Since you can consume more than once the enumerator you get "double" output:
for x in n do
p x
p n.next
end
Or using Array#each:
n.each do |x| # same as array.each.each
p x
p n.next
end
Also in Ruby you reach end the iteration signal:
6.times do
p n.next
end
# `next': iteration reached an end (StopIteration)
You're just trying to print each element of the Array?
[1,2,3,4,5].each {|n| puts n}
If you're looking for a direct equivalent of Python's iterator, you should check out Enumerator#next for a very similar API
arr = [1, 2, 3].to_enum
#<Enumerator: [1, 2, 3]:each>
arr.next
# 1
for x in arr do
puts x
puts arr.next
end
#1
#2
#2
#3
#3
#StopIteration: iteration reached an end
each_cons is what you need. But this method has a downside that is the current will not print last element of the array. Please keep in mind this.
[1,2,3,4,5].each_cons(2) { |current,next_val| puts next_val }
(1)
a = [1, 2]
while b = a.pop do puts b end
outputs
2
1
(2)
a = [1, 2]
puts b while b = a.pop
results in an error
undefined local variable or method `b'
(3)
b = nil
a = [1, 2]
puts b while b = a.pop
outputs
2
1
What is going on? Why is the scope of b different in #2 than any of the rest?
$ ruby --version
ruby 1.9.3p484 (2013-11-22 revision 43786) [x86_64-linux]
EDIT: Originally I listed irb's behavior as different. It isn't; I was working in a "dirty" session.
Variables are declared to their scope by the lexical parser, which is linear. In while b = a.pop do puts b end, the assignment (b = a.pop) is seen by the parser before the use (puts b). In the second example, puts b while b = a.pop, the use is seen when the definition is still unknown, which produces the error.
The puts statement is executed before the variable 'b' is initially defined, thus resulting in an error.
As a similar example but with an until-statement, consider the following code:
a = [1, 2]
begin
puts "in the block"
end until b = a.pop
Would you expect b to be defined within the block?
Technically the only difference is that until stops on a true return value, while while will continue as long as a.pop returns a true value.
The point in both cases is that b is not in scope until the assignment happened. Right after the assignment, e.g. when the loop returns, b comes available in the current scope. That is called lexical scoping and is how ruby works for local variables like this one.
I found this article to be helpful for understanding scope in ruby.
Update 1: In the previous version of my answer I wrote that this is not comparable to an if. While this is still true, it has nothing to do with the question, which is a simple scope issue.
Update 2: Added a link to some more details explanations regarding scoping in ruby.
Update 3: Removed the first sentence, as it was wrong.
a = [1, 2]
while b = a.pop do puts b end
is same as
a = [1, 2]
b = a.pop
puts b
b = a.pop
puts b
(2)
a = [1, 2]
puts b while b = a.pop
is same as this
a = [1, 2]
puts b
b = a.pop
puts b
b = a.pop
puts b
When b is passed into puts the first time it has not yet been initialized. hence the error message
(3)
b is initialized to nil. even nil is an object in ruby
b = nil
a = [1, 2]
puts b while b = a.pop
I'm writing a program that pushes Fibonacci numbers into an array, using Ruby. The code works, but I can't wrap my head around why it works.
This part I understand, it's the Fibonacci equation:
fib_array = []
def fib (n)
return n if n <= 1
fib(n - 1) + fib(n - 2)
end
This is what I don't understand:
10.times do |x|
fib_array << fib(x)
end
print fib_array
I wrote this grasping at straws, and it works. I don't understand why. I didn't feed it a number to start at, does Ruby take that to mean 0? Also, how did it know to compound the numbers instead of printing [0, 0, 0...]? I apologize if this is a dunderheaded question, but I'm at loss.
It looks like the bottom piece of code simply calls the fib function on x=0, x=1 ... x=9 and stores it's return value at the end of the array. When times is invoked with an iteration variable (x), it begins at 0 and increments on each iteration through the loop. You never fed it a value, however it manages to successfully solve the problem with the iteration variable x being passed in as the parameter to fib.
The second part of your code says:
"From the instance 10 of the class Integer, call the method times with the given block" (The method "recive" a block implicitly).
What is a block? A small piece of code between {braces} or a do-end (like you did).
The method times is called, "iterator". And it will yield 0,1,2,..,9 (in your case). An iterator and the yield statement are always together. Think that yield is like return with memory, when you look for more information.
So, your code could be re-writing like:
10.times { |x| fib_array << fib(x) }
And it will call, the block you pass, on every yield that the method times
does. Calling the method << (append) to the result of fib(x) on your array.
We have:
def fib (n)
return n if n <= 1
fib(n - 1) + fib(n - 2)
end
which you understand. First let's see what are the first 5 Fibonacci numbers::
fib_array = []
5.times do |x|
fib_array << fib(x)
end
fib_array
#=> [0, 1, 1, 2, 3]
Now let's break this down and see what happening. First look at the docs for the method times. To find them, we need to know what class or module the method is from, because that's how the docs are organized. As 5.class #=> Fixnum, we might look at the docs for Fixnum. Hmmm. times is not there. Evidentally, it was inherited from another class. Let's check:
Fixnum.ancestors
#=> [Fixnum, Integer, Numeric, Comparable, Object, Kernel, BasicObject]
Integer includes Fixnum and BigNum, Numeric includes Integer and Float. (3.14).times doesn't make sense, so it appears times is defined in Integer, and so it is: Integer#times. By defining it there, it is inherited by both Fixnum and Bignum.
Here's a direct way to determine where the method came from:
5.method(:times).owner #=> Integer
It's not important understand this now, but you'll find it handy as you gain experience with Ruby.
OK, the docs say that times return a value if given a block, or an enumerator if not. Let's forget about the block a moment and look at the enumerator that is returned:
enum = 5.times #=> #<Enumerator: 5:times>
The method Enumerator#each passes the elements of the enumerator enum to its block:
do |x|
fib_array << fib(x)
end
assigning them to the block variable x. To see the contents of the enumerator, convert it to an array:
enum.to_a #=> [0, 1, 2, 3, 4]
The result is:
fib_array = []
enum.each do |x|
fib_array << fib(x)
end
fib_array
#=> [0, 1, 1, 2, 3]
which of course is the same result that we obtained previously. Now let's see what's happening step-by-by, by using the method Enumerator#next to extract each element of the enumerator:
x = enum.next #=> 0
fib(x) #=> 0
fib_array << fib(x) #=> [0]
x = enum.next #=> 1
fib(x) #=> 1
fib_array << fib(x) #=> [0, 1]
x = enum.next #=> 2
fib(x) #=> 1
fib_array << fib(x) #=> [0, 1, 1]
x = enum.next #=> 3
fib(x) #=> 2
fib_array << fib(x) #=> [0, 1, 1, 2]
x = enum.next #=> 4
fib(x) #=> 3
fib_array << fib(x) #=> [0, 1, 1, 2, 3]
print fib_array # [0, 1, 1, 2, 3]
That's all there is to it.
Let's say I have an array A = [1, 2, 3, 4, 5]
how can I multiply all elements with ruby and get the result? 1*2*3*4*5 = 120
and what if there is an element 0 ? How can I ignore this element?
This is the textbook case for inject (also called reduce)
[1, 2, 3, 4, 5].inject(:*)
As suggested below, to avoid a zero,
[1, 2, 3, 4, 5].reject(&:zero?).inject(:*)
There is also another way to calculate this factorial!
Should you want to, you can define whatever your last number is as n.
In this case, n=5.
From there, it would go something like this:
(1..num).inject(:*)
This will give you 120. Also, .reduce() works the same way.
Well, this is a dummy way but it works :)
A = [1, 2, 3, 4, 5]
result = 1
A.each do |i|
if i!= 0
result = result*i
else
result
end
end
puts result
If you want to understand your code later on, use this: Assume A = 5, I used n instead of A
n = 5
n.times {|x| unless x == 0; n = n * x; ++x; end}
p n
To carry it forward, you would:
A = [1,2,3,4,5]
arb = A.first
a = A.count
a.times {|x| arb = arb * A[x]; ++x}
p arb