Ruby: two-dimensional arrays syntax - ruby

In Ruby, suppose we have a 2-dimensional array, why is this syntax fine:
array.each do |x|
x.each do |y|
puts y
end
end
But this is not:
array.each{|x|.each{|y| puts y}}
Any ideas? Thanks

This should be fine array.each{|x| x.each{|y| puts y}}
You forget to refer x first.
I.e. . is supposed to be left associate operator. If you have noting on the left side - this is an error.

If you replace your do...end blocks with {...} carefully you'll find that your second form works the same as your first. But puts array accomplishes the same thing as this whole double loop.
If I may offer some polite meta-advice, your two Ruby questions today seem like you maybe were asked to do some things in a language you don't know, and are frustrated. This is understandable. But the good news is that, compared to many other languages, Ruby is built on a very small number of pieces. If you spend a little time getting really familiar with Array and Hash, you'll find the going much smoother thereafter.

Related

How could I improve this super simple sorting method? - Beginning Ruby

I'm learning Ruby from Chris Pine's "Learn To Program" book and I've been asked to write a method that sorts a set of given words in alphabetical order either with loops or recursion. I first gave looping a try.
def sort words
i = 0
checked = 0
while true
if (i+1 < words.length)
if (words[i]>words[i+1])
temp = words[i]
words[i] = words[i+1]
words[i+1] = temp
else
checked+=1
end
i+=1
elsif (checked == words.length-1)
break
else
i =0
checked =0
end
end
return words
end
The code works, but I wanted to see if any seasoned ruby-ists could offer some input on how to make it more efficient.
Thank You!
The first thing to learn when you're beginning to understand optimization is that the most obvious fixes are often the least productive. For example, you could spend a lot of time here tweaking some of these comparisons or switching to a slightly different way of evaluating the same thing and get a 5-10% performance increase.
You could also use a completely different algorithm and get a 5x-10x increase. Bubble-sort, which is what you have here, is nearly the worst performing sorting algorithm ever made. This is a technique you should learn if only to understand that it's terrible and you should immediately move on to other methods, like Quicksort which is not all that hard to implement if you approach the problem systematically.
So in other words, before you start tweaking little things, step back and ask yourself "Am I approaching this problem the right way?" Always consider other angles when you have a performance problem.
That being said, here's how to make your code more Ruby-like:
def sort(words)
# Make a copy so the original isn't mangled
words = words.dup
# Iterate over ranges:
# (n..m) goes from N to M inclusive
# (n...m) goes from N up to but not including M
(0...words.length-1).each do |i|
(0...words.length-1-i).each do |j|
# Examine the pair of words at this offset using an array slice
a, b = words[j, 2]
# If A is ahead of B then...
if (a > b)
# ...swap these elements.
words[j, 2] = [ b, a ]
end
end
end
words
end
# Quick test function that uses randomized data
p sort(%w[ a c d f b e ].shuffle)
To improve as a developer you should always try and measure your progress somehow. Tools like Rubocop will help identify inefficient coding practices. Test-driven development can help to identify flaws early in your programming and to make sure that changes don't cause regressions. Benchmarking tools help you better understand the perfomance of your code.
For example:
require 'benchmark'
CHARS = ('a'..'z').to_a
def random_data
Array.new(1000) { CHARS.sample }
end
count = 100
Benchmark.bm do |bm|
bm.report('my sort:') do
count.times do
sort(random_data)
end
end
bm.report('built-in sort:') do
count.times do
random_data.sort
end
end
end
# user system total real
# my sort: 19.220000 0.060000 19.280000 ( 19.358073)
# built-in sort: 0.030000 0.000000 0.030000 ( 0.025662)
So this algorithm is 642x slower than the built-in method. I'm sure you can get a lot closer with a better algorithm.
Firstly, you dont have to reinvent the Wheel. I mean, see this example:
> ['a', 'abc', 'bac', 'cad'].sort
# => ["a", "abc", "bac", "cad"]
Ruby has a extensively huge set of libraries. Common stuffs are so efficiently supported by Ruby. You just have to have enough knowledge to use the language features efficiently.
I would recommend you to go through the Ruby core libraries and learn to use to combine the features to achieve something special.
Give a try to this Ruby Koans http://rubykoans.com/
RubyKoans is the most efficient to achieve mastery over Ruby language.
Here is a list of Sorting algorithm examples by type in this site https://www.sitepoint.com/sorting-algorithms-ruby/
You have to choose between algorithms wisely based on size of problems domain and usecases.

Bubble Sort method

I am just learning ruby and KevinC's response (in this link) makes sense to me with one exception. I don't understand why the code is encompassed in the arr.each do |i| #while... end That part seems redundant to me as the 'while' loop is already hitting each of the positions? Can someone explain?
The inner loop finds a bubble and carries it up; if it finds another, lighter bubble, it switches them around and carries the lighter one. So you need several passes through the array to find all the bubbles and carry them to the correct place, since you can't float several bubbles at the same time.
EDIT:
The each is really misused in KevinC's code, since it is not used for its normal purpose: yielding elements of the collection. Instead of arr.each, it would be better to use arr.size.times - as it would be more informative to the reader. Redefining the i within the block is adding insult to injury. While none of this will cause the code to be wrong as such, it is misleading.
The other problem with the code is the fact that it does not provide the early termination condition (swapped in most other answers on that question). In theory, bubble sort could find the array sorted in the first pass; the other size - 1 steps are unnecesary. KevinC's code would still dry-hump the already sorted array, never realising it is done.
As for rewrite into block-less code, it is certainly possible, but you need to understand that blocks syntax is very idiomatic in Ruby, and non-block loops are almost unheard of in Ruby world. While Ruby has for, it is pretty much never used in Ruby. But...
arr.each do |i|
...
end
is equivalent to
for i in arr
...
end
which is, again, at least for the array case, equivalent to
index = 0
while index < arr.size
i = arr[index]
...
index += 1
end

Ruby: Find Most Common Phrase in array of strings

I'd like to be able to find the 10 most common questions in a array of 300-500 strings, in Ruby.
An example element being
["HI, I'd like your product. I just have one question. How do I change
my password?", "Can someone tell me how I change my password?", "I
can't afford this. How do I cancel my account?", "Account
cancelation?", "I forgot my password, how do I change my password?",
.....]
Basically, I'm going to have an array of a lot of strings, and I have to extract the question, and find the 10 most common questions from that array.
I've tried looking around (checked out n-grams, but it didn't seem too relevant) and have yet to come up with any ideas.
Do you know of any algorithms you'd suggest I take a look at? A link to a couple examples would be terrific!
I would say the first step would be to actually determine which Strings (or Substrings) are actually questions. A no-brainer approach to that would be to look out for "?", but then again depending on your requirement you can enhance that - maybe lookout out for "question words". That would probably be the easier part of your task.
Once you get a list of strings (that are supposedly questions) - you need to cluster similar ones and return the 10 largest bins. The best way would be to combine a semantic + syntax based approach. You could probably have a look at this paper as they seem to tackle the problem of finding similarities between two strings. They present some compelling reasons as to why a dual syntactic-semantic approach is required.
Not sure about special algorithms, but if I were assigned this task:
array = ["my account is locked.", "can i have the account password to my account?", "what's my password?"]
array.map! {|x| x.split(' ')} #make each sentence an element
word_freq = Hash.new(0)
i = 0
while i < array.length
array[i].each {|x| word_freq[x] += 1}
i += 1
end
word_freq.each {|m, x| puts "#{m} appears #{x} times"} #words are now keys with frequency values
print word_freq.keys #an array of key words to mess with

Is high-speed sorting impossible with Ruby?

I've studied the poignant guide and it really has helped me pick up the
language pretty fast. After that, I started solving some coding puzzles
using Ruby. It just helps a lot to get used to the language I feel.
I'm stuck with one such puzzle. I have solved it very easily since it is
pretty straight-forward, but the solution is being rejected (by the host
website) with the error 'Time Exceded'! I know that Ruby cannot compete
with the speed of C/C++ but it has got to be able to answer a tiny puzzle on a website which accepts
solutions in Ruby?
The puzzle is just a normal sort.
This is my solution
array ||= []
gets.to_i.times do
array << gets
end
puts array.sort
My question is, is there any other way I can achieve high-speed sorting with Ruby? I'm using the basic Array#sort here, but is there a way to do it faster, even though it means lot more lines of code?
I've solved that problem, and let me tell you using a nlogn algorithm to pass that is almost impossible unless you are using a very optimized C/Assembly version of it.
You need to explore other algorithms. Hint: O(n) Algorithm will do the trick, even for ruby.
Good Luck.
You're sorting strings when you should be sorting ints. Try:
array << gets.to_i
If there is no need for duplicate values to be repeated:
h = {}
gets.to_i.times{h[gets.to_i] = true}
(0..100000).each{|n| puts(n) if h[n]}
If duplicate values must be repeated:
h = Hash.new(0)
gets.to_i.times{h[gets.to_i] += 1}
(0..100000).each{|n| h[n].times{puts(n)}}

fixnum and prime numbers in ruby

Before I set about to writing this myself, has anyone seen a ruby implementation of the following behavior?
puts 7.nextprime(); #=> 11
puts 7.previousprime(); #=> 5
puts 7.isprime(); #=> true
Obviously this kind of thing would be ugly for large numbers but for integers never exceeding a few thousand (the common instance for me) a sensible implementation is doable, hence the question.
Ruby comes with a built-in Prime class that allows you to iterate through primes starting at 1, but I see no way to initialize it with a starting value other than 1, nor a predicate check to determine whether or not a number is prime. I'd say go for it, though you should keep in mind that math in Ruby can be slow and if performance is a factor you may be better off considering writing it as a C or Java extension. Here's an example of how to use RubyInline to generate primes in C.
Also, I suggest you avoid using the method name 7.isprime - the convention in Ruby is 7.prime?.
Take a look at the snippets found here. They could give you a headstart.

Resources