please help with my "shuffle" code in ruby - ruby

this is the question
Shuffle. Now that you’ve finished your
new sorting algorithm, how about the
opposite? Write a shuffle method that
takes an array and returns a totally
shuffled version. As always, you’ll
want to test it, but testing this one
is trickier: How can you test to make
sure you are getting a perfect
shuffle? What would you even say a
perfect shuffle would be? Now test for
it.
This is my code answer:
def shuffle arr
x = arr.length
while x != 0
new_arr = []
rand_arr = (rand(x))
x--
new_arr.push rand_arr
arr.pop rand_arr
end
new_arr
end
puts (shuffle ([1,2,3]))
What are my mistakes? Why doesn't this code work?

Here's a far more Rubyish version:
class Array
def shuffle!
size.downto(1) { |n| push delete_at(rand(n)) }
self
end
end
puts [1,2,3].shuffle!

Here's a more concise way of writing it:
def shuffle(arr)
new_arr = []
while (arr.any?) do
new_arr << arr.delete_at(rand(arr.length))
end
new_arr
end
And some tests:
5.times do
puts shuffle((1..5).to_a).join(',')
end
>> 4,2,1,3,5
>> 3,2,1,4,5
>> 4,2,5,1,3
>> 5,2,1,4,3
>> 4,3,1,5,2

Beside minor other errors you seems not to understand what pop and push are doing (taking or adding some items from the end of the array).
You are probably trying to write something like below.
def shuffle arr
x = arr.length
new_arr = []
while x != 0
randpos = rand(x)
x = x-1
item = arr[randpos]
new_arr.push item
arr[randpos] = arr[x]
arr.pop
end
new_arr
end
puts (shuffle ([1,2,3]))

You're getting your indexes mixed up with your values. When you do new_arr.push rand_arr, you're putting whatever random index you came up with as a value on the end of new_arr. What you meant to do is new_arr.push arr[rand_arr], where arr[rand_arr] is the value at the index rand_arr in arr.

Ruby 1.8.7 and 1.9.2 have a built-in Array#shuffle method.

A variant of Mark Thomas's answer. His algorithm can be quite slow with a large array, due to delete operation performance.
class Array
def shuffle!
size.downto(1) do |n|
index=rand(n)
# swap elements at index and the end
self[index], self[size-1] = self[size-1],self[index]
end
self
end
end
puts [1,2,3].shuffle!
This algorithm is O(size), while Mark's algorithm is O(size^2). On my computer, Mark's answer takes 400 seconds to shuffle an array of 1,000,000 elements on my machine, versus 0.5 seconds with my method.

Related

Using range.each vs while-loop to work with sequence of numbers in Ruby

Total beginner here, so I apologize if a) this question isn't appropriate or b) I haven't asked it properly.
I'm working on simple practice problems in Ruby and I noticed that while I arrived at a solution that works, when my solution runs in a visualizer, it gives premature returns for the array. Is this problematic? I'm also wondering if there's any reason (stylistically, conceptually, etc.) why you would want to use a while-loop vs. a for-loop with range for a problem like this or fizzbuzz.
Thank you for any help/advice!
The practice problem is:
# Write a method which collects all numbers between small_num and big_num into
an array. Ex: range(2, 5) => [2, 3, 4, 5]
My solution:
def range(small_num, big_num)
arr = []
(small_num..big_num).each do |num|
arr.push(num)
end
return arr
end
The provided solution:
def range(small_num, big_num)
collection = []
i = small_num
while i <= big_num
collection << i
i += 1
end
collection
end
Here's a simplified version of your code:
def range(small_num, big_num)
arr = [ ]
(small_num..big_num).each do |num|
arr << num
end
arr
end
Where the << or push function does technically have a return value, and that return value is the modified array. This is just how Ruby works. Every method must return something even if that something is "nothing" in the form of nil. As with everything in Ruby even nil is an object.
You're not obligated to use the return values, though if you did want to you could. Here's a version with inject:
def range(small_num, big_num)
(small_num..big_num).inject([ ]) do |arr, num|
arr << num
end
end
Where the inject method takes the return value of each block and feeds it in as the "seed" for the next round. As << returns the array this makes it very convenient to chain.
The most minimal version is, of course:
def range(small_num, big_num)
(small_num..big_num).to_a
end
Or as Sagar points out, using the splat operator:
def range(small_num, big_num)
[*small_num..big_num]
end
Where when you splat something you're in effect flattening those values into the array instead of storing them in a sub-array.

defining my_each in terms of my_times

I'm reading The Well-Grounded Rubyist and have come across an extra credit challenge to which there is no answer.
class Array
def my_each
c = 0
until c == size
yield(self[c])
c += 1
end
self
end
end
An example is given of creating a my_each with my_times
class Array
def my_each
size.my_times do |i|
yield self[i]
end
self
end
end
With the point that many of Ruby's iterators are built on top of each and not the other way around.
Given the above my_each, how could I use it in an implementation of my_times?
To make it clear, an example of a my_times implementation was given before:
class Integer
def my_times
c = 0
until c == self
yield(c)
c += 1
end
self
end
end
5.my_times { |e| puts "The block just got handed #{e}." }
So it would seem that the question most certainly implies using my_each in an implementation of my_times.
To implement my_times using my_each, all you need to do is call my_each on an array that looks like [0, 1, ..., (x - 1)], where x is self (the Integer):
class Integer
def my_times(&block)
(0...self).to_a.my_each do |n|
yield n
end
self
end
end
P.S. If you defined my_each on Enumerable instead of Array (like the "real" each), you could remove to_a from the third line above and iterate directly over the Range, instead of converting the Range to an Array first.
In order to implement my_times we need an array to send my_each message to. At that point of the book I don't think range is covered so I implemented without using a range. Here is the solution:
require_relative "my_each"
class Integer
def my_times
array = Array.new(self)
c = 0
array.my_each do
array[c] = c
yield(c)
c += 1
end
self
end
end
Edit: I just noticed Jordan used ... instead of .. which generates the correct output; See this answer for more detail on the difference for ranges. I've updated my answer below.
My account is too new and I can't comment on Jordan's solution; I see this was posted about a year ago but I am currently reading through The Well-Grounded Rubyist and wanted to comment on the solution.
I had approached it the same in a similar way as Jordan but found that the output is off compared to; The Well-Grounded Rubyist implementation of my_times which produces:
puts 5.my_times { |i| puts "I'm on iteration # {i}!" }
I'm on iteration 0!
I'm on iteration 1!
I'm on iteration 2!
I'm on iteration 3!
I'm on iteration 4!
Jordan's solution outputs:
puts 5.my_times { |i| puts "I'm on iteration # {i}!" }
I'm on iteration 0!
I'm on iteration 1!
I'm on iteration 2!
I'm on iteration 3!
I'm on iteration 4!
I'm on iteration 5!
I used a magic number to match The Well-Grounded Rubyist output [See Jordan's solution, using ... instead of .. which removes the need for the magic number]
class Integer
def my_times
(0..(self-1)).to_a.my_each do |n|
yield n
end
self
end
end
I shortened dwyd's implementation to supply a block rather than using the do..end.
class Integer
def my_times
(0...self).to_a.my_each { |i| yield i }
end
end
Also, I don't think you need to do self-1.

Syntax for a for loop in ruby

How do I do this type of for loop in Ruby?
for(int i=0; i<array.length; i++) {
}
array.each do |element|
element.do_stuff
end
or
for element in array do
element.do_stuff
end
If you need index, you can use this:
array.each_with_index do |element,index|
element.do_stuff(index)
end
limit = array.length;
for counter in 0..limit
--- make some actions ---
end
the other way to do that is the following
3.times do |n|
puts n;
end
thats will print 0, 1, 2, so could be used like array iterator also
Think that variant better fit to the author's needs
I keep hitting this as a top link for google "ruby for loop", so I wanted to add a solution for loops where the step wasn't simply '1'. For these cases, you can use the 'step' method that exists on Numerics and Date objects. I think this is a close approximation for a 'for' loop.
start = Date.new(2013,06,30)
stop = Date.new(2011,06,30)
# step back in time over two years, one week at a time
start.step(stop, -7).each do |d|
puts d
end
The equivalence would be
for i in (0...array.size)
end
or
(0...array.size).each do |i|
end
or
i = 0
while i < array.size do
array[i]
i = i + 1 # where you may freely set i to any value
end
array.each_index do |i|
...
end
It's not very Rubyish, but it's the best way to do the for loop from question in Ruby
To iterate a loop a fixed number of times, try:
n.times do
#Something to be done n times
end
If you don't need to access your array, (just a simple for loop) you can use upto or each :
Upto:
2.upto(4) {|i| puts i}
2
3
4
Each:
(2..4).each {|i| puts i}
2
3
4
What? From 2010 and nobody mentioned Ruby has a fine for /in loop (it's just nobody uses it):
ar = [1,2,3,4,5,6]
for item in ar
puts item
end
['foo', 'bar', 'baz'].each_with_index {|j, i| puts "#{i} #{j}"}
Ruby's enumeration loop syntax is different:
collection.each do |item|
...
end
This reads as "a call to the 'each' method of the array object instance 'collection' that takes block with 'blockargument' as argument". The block syntax in Ruby is 'do ... end' or '{ ... }' for single line statements.
The block argument '|item|' is optional but if provided, the first argument automatically represents the looped enumerated item.

Efficient Ruby LRU cache

What's the most efficient way to build a cache with arbitrary Ruby objects as keys that are expired based on a least recently used algorithm. It should use Ruby's normal hashing semantics (not equal?)
I know its a few years late, but I just implemented what I believe is the fastest LRU Cache out there for Ruby.
It is also tested and optionally safe to use in multi threaded environments.
https://github.com/SamSaffron/lru_redux
Note: in Ruby 1.9 Hash is ordered, so you can cheat and build the fastest LRU cache in a few lines of code
class LruRedux::Cache19
def initialize(max_size)
#max_size = max_size
#data = {}
end
def max_size=(size)
raise ArgumentError.new(:max_size) if #max_size < 1
#max_size = size
if #max_size < #data.size
#data.keys[0..#max_size-#data.size].each do |k|
#data.delete(k)
end
end
end
def [](key)
found = true
value = #data.delete(key){ found = false }
if found
#data[key] = value
else
nil
end
end
def []=(key,val)
#data.delete(key)
#data[key] = val
if #data.length > #max_size
#data.delete(#data.first[0])
end
val
end
def each
#data.reverse.each do |pair|
yield pair
end
end
# used further up the chain, non thread safe each
alias_method :each_unsafe, :each
def to_a
#data.to_a.reverse
end
def delete(k)
#data.delete(k)
end
def clear
#data.clear
end
def count
#data.count
end
# for cache validation only, ensures all is sound
def valid?
true
end
end
This pushes the boundaries of my understanding of how Ruby uses memory, but I suspect that the most efficient implementation would be a doubly-linked list where every access moves the key to the front of the list, and every insert drops an item if the maximum size has been reached.
However, assuming Ruby's Hash class is already very efficient, I'd bet that the somewhat naive solution of simply adding age data to a Hash would be fairly good. Here's a quick toy example that does this:
class Cache
attr_accessor :max_size
def initialize(max_size = 4)
#data = {}
#max_size = max_size
end
def store(key, value)
#data.store key, [0, value]
age_keys
prune
end
def read(key)
if value = #data[key]
renew(key)
age_keys
end
value
end
private # -------------------------------
def renew(key)
#data[key][0] = 0
end
def delete_oldest
m = #data.values.map{ |v| v[0] }.max
#data.reject!{ |k,v| v[0] == m }
end
def age_keys
#data.each{ |k,v| #data[k][0] += 1 }
end
def prune
delete_oldest if #data.size > #max_size
end
end
There's probably a faster way of finding the oldest item, and this is not thoroughly tested, but I'd be curious to know how anyone thinks this compares to a more sophisticated design, linked list or otherwise.
Remaze has a reasonably well tested LRU Cache: See http://github.com/manveru/ramaze/blob/master/lib/ramaze/snippets/ramaze/lru_hash.rb
And there is also the hashery gem by rubyworks which should be more efficient than the remaze one for large caches.
The rufus-lru gem is another option.
Instead of a count it just keeps a sorted array of keys from oldest to newest
I threw together a new gem lrucache which you may find useful. It may be faster than Alex's approach for collections with a significant number of elements.
Very simple and fast lru cache I use in our http backend https://github.com/grosser/i18n-backend-http/blob/master/lib/i18n/backend/http/lru_cache.rb
gem install ruby-cache
--> http://www.nongnu.org/pupa/ruby-cache-README.html

First order array difference in Ruby

What's the slickest, most Ruby-like way to do this?
[1, 3, 10, 5].diff
should produce
[2, 7, -5]
that is, an array of first order differences. I've come up with a solution which I'll add below, but it requires ruby 1.9 and isn't all that slick. what else is possible?
I like this functional style:
module Enumerable
def diff
each_cons(2).map {|pair| pair.reverse.reduce :-}
end
end
EDIT: I just realized that the reverse is totally unnecessary. If this were a functional language, I would have used pattern matching, but Ruby doesn't support pattern matching. It does, however, support destructuring bind, which is a good enough approximation for pattern matching in this case.
each_cons(2).map {|first, second| second - first}
No smiley, though.
I like how this sounds if you just read it out loud from left to right: "For each pair, apply the difference between the first and second elements of the pair." In fact, I normally don't like the name collect and prefer map instead, but in this case that reads even better:
each_cons(2).collect {|first, second| second - first}
"For each pair, collect the difference between its elements." Sounds almost like a definition of first order difference.
Yet another way..Seems the shortest so far:)
module Enumerable
def diff
self[1..-1].zip(self).map {|x| x[0]-x[1]}
end
end
The concept comes from functional programming, of course:
module Enumerable
def diff
self.inject([0]) { |r,x| r[-1] += x; r << -x } [1..-2]
end
end
[1,3,10,5].diff
Note that you don't need any separate intermediate variables here
Here's the fastest way I could find (faster than all the others suggested here as of this moment, in both 1.8 and 1.9):
module Enumerable
def diff
last=nil
map do |x|
r = last ? x - last : nil
last = x
r
end.compact
end
end
With this close runner-up:
module Enumerable
def diff
r = []
1.upto(size-1) {|i| r << self[i]-self[i-1]}
r
end
end
Of the others here, testr's self-described "feeble" attempt is the next fastest, but it's still slower than either of these.
And if speed is no object, here's my aesthetic favorite:
module Enumerable
def diff!
[-shift+first] + diff! rescue []
end
def diff
dup.diff!
end
end
But this is (for reasons I don't entirely understand) an order of magnitude slower than any other suggestion here!
Minor variation on Jörg W Mittag's:
module Enumerable
def diff
each_cons(2).map{|a,b| b-a}
end
end
# Attempt, requires ruby 1.9.
module Enumerable
def diff
each_cons(2).with_object([]){|x,array| array << x[1] - x[0]}
end
end
Example:
[1,3,10,5].diff
=> [2, 7, -5]
Another way to do it.
module Enumerable
def diff
result = []
each_with_index{ |x, i|
return result if (i == (self.length-1))
result << self[i+1] - x
}
end
end
My feeble attempt...
module Enumerable
def diff
na = []
self.each_index { |x| r << self[x]-self[x-1] if x > 0 }
na
end
end
p [1,3,10,5].diff #returned [2, 7, -5]

Resources