range in an array [duplicate] - ruby

This question already has answers here:
how to show all integers of an array in ruby?
(2 answers)
Closed 8 years ago.
I cannot seem to iterate through a range. Here is what I get:
[1..6].to_a.each{ |n|
puts(n)
}
# => [1..6]
This is one iteration without offering each number. Is there any way to make this work?

[1..6] does not define a range. It defines an array with one element that is a range:
[1..6] == (1..6)
# => false
[1..6].class
# => Array
[1..6] == [(1..6)]
# => true
[1..6][0].class
# => Range
The correct syntax to create a range is (1..6):
(1..6).each { |n| puts n }

You can use
6.times { |n| puts n }
if u want to iterate n times

Your one is not working, as you created an array of range of size 1. Now, to make it working you can do as :
[*1..3].each { |n| puts n }
It would output as :
1
2
3
But better in such case, to use
(1..3).each { |n| puts n }
As Range is an enumerable, you can call on it the Range#each method.

Related

How do I iterate through a hash until I find a matching element? [duplicate]

This question already has answers here:
How do I find keys in my hash to map to elements that match a condition?
(3 answers)
Closed 5 years ago.
I have a hash that maps integers to arrays. For example
{1 => ["abc"], 2 => ["ccc", "ddd"]}
How do I iterate through the hash until I find an entry in which the value only has an array size of 1? Normally I could do
arr.detect{|element| element.size == 1}
but that only works for arrays. I'm not sure how to apply a similar logic to hashes.
Same principle applies:
h = {1 => ["abc"], 2 => ["ccc", "ddd"]}
h.find do |_, l|
l.size == 1
end
# => [ 1, ["abc"]]
Now if you're looking for that as a more useful variable set:
key, value = h.find do |_, l|
l.size == 1
end
# => [ 1, ["abc"]]
key
# => 1
value
# => ["abc"]
If you only care about the values, then it's even easier:
list = h.values.find do |l|
l.size == 1
end

How solve TypeError nil can't be coerced into Fixnum

I have this code:
require 'set'
N, K = gets.split().map{ |v| v.to_i }
set = Set.new
numbers = gets.split().map{ |v| v.to_i }
pairs = 0
N.times do |i|
set.add(numbers[i])
end
set.each{ |value| pairs += set.include?(value+K) ? 1 : 0 }
puts pairs
But when I put N and K, return this error:
`+': nil can't be coerced into Fixnum (TypeError)
I should convert or other thing? Thanks!
Do you want to count the number of pairs in your set that are separated by K?
Your code works when you input 3 1 followed by 1 2 3. It answers 2.
First, you really should describe a bit more what your goal is.
Then, no need to input N. It just should be the size of your set.
Write an example of the desired input before calling gets
Here's a possible implementation :
require 'set'
puts 'Please type the integers of your set, separated by a space. Example : 1 2 3'
numbers = Set.new(gets.split.map{ |v| v.to_i})
# N=numbers.size # But you don't need it
puts 'Which pair difference are you looking for? Example : 1'
k = gets.to_i
pairs = numbers.select{|value| numbers.include?(value+k)}
count = pairs.size
puts "#{count} pair(s) found :"
pairs.each{|first_value|
puts format("(%d, %d)",first_value,first_value+k)
}
# Please type the integers of your set, separated by a space. Example : 1 2 3
# 1 2 3
# Which pair difference are you looking for? Example : 1
# 1
# 2 pair(s) found :
# (1, 2)
# (2, 3)

Ruby - Return duplicates in an array using hashes, is this efficient?

I have solved the problem using normal loops and now using hashes, however I am not confident I used the hashes as well as I could have. Here is my code:
# 1-100 whats duplicated
def whats_duplicated?(array)
temp = Hash.new
output = Hash.new
# Write the input array numbers to a hash table and count them
array.each do |element|
if temp[element] >= 1
temp[element] += 1
else
temp[element] = 1
end
end
# Another hash, of only the numbers who appeared 2 or more times
temp.each do |hash, count|
if count > 1
output[hash] = count
end
end
# Return our sorted and formatted list as a string for screen
output.sort.inspect
end
### Main
# array_1 is an array 1-100 with duplicate numbers
array_1 = []
for i in 0..99
array_1[i] = i+1
end
# seed 10 random indexes which will likely be duplicates
for i in 0..9
array_1[rand(0..99)] = rand(1..100)
end
# print to screen the duplicated numbers & their count
puts whats_duplicated?(array_1)
My question is really what to improve? This is a learning excercise for myself, I am practising some of the typical brain-teasers you may get in an interview and while I can do this easily using loops, I want to learn an efficient use of hashes. I re-did the problem using hashes hoping for efficiency but looking at my code I think it isn't the best it could be. Thanks to anyone who takes an interest in this!
The easiest way to find duplicates in ruby, is to group the elements, and then count how many are in each group:
def whats_duplicated?(array)
array.group_by { |x| x }.select { |_, xs| xs.length > 1 }.keys
end
whats_duplicated?([1,2,3,3,4,5,3,2])
# => [2, 3]
def whats_duplicated?(array)
array.each_with_object(Hash.new(0)) { |val, hsh| hsh[val] += 1 }.select { |k,v| v > 1 }.keys
end
I would do it this way:
def duplicates(array)
counts = Hash.new { |h,k| h[k] = 0 }
array.each do |number|
counts[number] += 1
end
counts.select { |k,v| v > 1 }.keys
end
array = [1,2,3,4,4,5,6,6,7,8,8,9]
puts duplicates(array)
# => [4,6,8]
Some comments about your code: The block if temp[element] == 1 seems not correct. I think that will fail if a number occurs three or more times in the array. You should at least fix it to:
if temp[element] # check if element exists in hash
temp[element] += 1 # if it does increment
else
temp[element] = 1 # otherwise init hash at that position with `1`
end
Furthermore I recommend not to use the for x in foo syntax. Use foo.each do |x| instead. Hint: I like to ask in interviews about the difference between both versions.

Cleanest way of fitting an integer in a range [duplicate]

This question already has answers here:
Ruby Elegant Way to Return Min/Max if Value Outside Range
(8 answers)
Closed 9 years ago.
What's the cleanest way of fitting an integer in a given range in ruby? A method that returns the given range's min or max if the integer it's invoked on exceeds the range.
Does a method like this exist in native ruby?
120.fit(1..100) # => 100
-20.fit(1..100) # => 1
Or maybe there's a nice one liner that does the same?
Edit
To achieve this I now have to do something like:
some_integer = some_range.min if some_integer <= some_range.min
some_integer = some_range.max if some_integer >= some_range.max
Something like this?
class Fixnum
def fit(range)
self > range.max ? range.max : (self < range.min ? range.min : self)
end
end
Usage:
> 5.fit(1..4) #=> 4
> 0.fit(1..4) #=> 1
> 3.fit(1..4) #=> 3
Not confident of being cleanest, but this is a way
(1..100).minmax.push( -50 ).sort[1]
# => 1
(1..100).minmax.push( 120 ).sort[1]
# => 100
r = (1..100)
v = -12
r.include?(v) ? v : ( r.begin > v ? r.begin : r.last)

Check that an array is increasing [duplicate]

This question already has answers here:
Check to see if an array is already sorted?
(8 answers)
Closed 9 years ago.
I am just wondering if there is a way to check if the array is increasing ?
Here is my solution, but I am searching for more beautiful way:
n = - 1
#arr.flatten.each { |e|
return false if e < n
n = e
}
You can do the following:
> arr = [1, 4, 5, 6]
> arr.each_cons(2).all? { |a, b| (a <=> b) <= 0 }
=> true
You can add it to Array class
class Array
def is_sorted?
each_cons(2).all? { |a, b| (a <=> b) <= 0 }
end
end
Try this,
if #arr.sort.uniq == #arr
# array is increasing
else
# array not increasing
end
This will sort the array and drop duplicate values, then compare it to the original array.
If your original array is always increasing, it should match the sorted, de-duplicated array.
EDIT:
While this solution gives the desired result, this is not the best solution (see comment below). I would suggest going with toch's solution instead.

Resources