Define a method `sum_to_n?` - ruby

I have the code below. Method sum_to_n? takes an array arr of integers and an integer n as arguments and returns true if any two elements in arr sum to n. It should return true for empty arr with zero n, but keeps returning false.
def sum_to_n?(arr, n)
hash = Hash.new(0)
arr.each do |val|
if hash.key? val
return true
else
hash[n-val] = val
end
end
return false
end
What am I doing wrong?

shorter version:
def sum_to_n?(arr, n)
(arr.empty? && n.zero?) || arr.permutation(2).any? { |a, b| a + b == n }
end

Your code is (almost) correct, but your expectation is wrong. Your code returns true when there are two (or one) element that adds up to n. If you pass an empty array, then there will not be any element(s) that add up to n (because there is no element in the array in the first place). Hence, you get false.
If you want it to return true for an empty array, then that would be an exceptional behavior that does not follow logically. You will have to put a condition such as
return true if arr.empty?
in your code.

Related

How can I compare one element to all other elements while iterating over an array?

I want to write a function that, given an array of integers, and number, determines (returns true or false) if any two integers in the array sum to number.
I know I can iterate over the array once using .each.
What I am having trouble with is figuring out how to do the second loop i.e. sum the current element with each of the other elements.
How can I do this in an elegant way?
I am new to Ruby.
This is a classic google interview question. Here's a way for an o(n) time and space complexity:
require 'set'
def find_pair(array, sum)
set = Set.new
array.each do |i|
return true if set.member?(i)
set << sum - i
end
return false
end
raise 'it returns false when no pair found' unless find_pair([1, 2, 4, 9], 8) == false
raise 'it returns true when pair found' unless find_pair([1, 2, 4, 4], 8) == true
There is also an o(n) time o(1) space solution for a sorted array, I'll let you find it.
def find_pair(array, num)
array.combination(2).any? { |combo| combo.sum == num }
end
combination
any?

Given an array of integers and target, return true if any two elements sum to target

As the title states, I'm looking to find two elements whose sum is equal to the target integer. I've already worked out the solution below, but this works only for unique integers. I'm having an issue when it comes to duplicate values. Of course, I can use multiple loops that keep track of two separate indices and, in this way, make sure those two indices are the same. However, I wanted to see if there was a way to solve this with one iteration.
two_sum([1,2,3,4,5,6], 8) = true
two_sum([4,4], 8) = false
def two_sum(array, target)
idx = 0
while idx < array.length
complement = target - array[idx]
if array.include?(complement) && complement != array[idx]
return true
end
idx+=1
end
return false
end
require 'set'
def two_sum(arr, tot)
st = Set.new
arr.each { |n| st.include?(tot-n) ? (return true) : st << n }
false
end
two_sum [1,2,3,4,5,6], 8 #=> true
two_sum [4,4], 8 #=> true
two_sum [1,2,3,4,5,6], 3421 #=> false
If you'd prefer to return the two values that sum to tot (when true), replace true with [n, tot-n] (or just return n, the other being tot - n).
I used a set rather than an array for faster lookups.
def two_sum(array, target)
array.combination(2).each { |pair| return true if pair.inject(:+) == target }
return false;
end

recursive bubble sort ruby

I am trying to build a recursive bubble sorting method in Ruby. It makes it through one pass fine, but it keeps returning after that. It seems that my
if array == swapped_array is being triggered, but I don't understand where my array variable is being redefined.
def bubble_sort(array, swapped = true)
return array if swapped == false
i = 0
if swapped == true
swapped_array = comparator(array)
end
if array == swapped_array
swapped = false
bubble_sort(array, swapped)
else bubble_sort(swapped_array)
end
end
def comparator(array, i = 0)
return array if i == array.length - 1
if array[i] > array[i+1]
array[i], array[i+1] = array[i+1], array[i]
end
i += 1
comparator(array, i)
end
swapped_array = comparator(array)
... takes the return value of comparator and assigns it to swapped_array. But comparator (eventually) returns the original argument array, which is the same array as the one defined in the caller. So
array == swapped_array
is always true.
If you want to compare two different arrays, you can call .dup on the array. This creates a new object with the same values as the original.
It is because in comparator, you are swapping the elements in the original array. Whatever you do to it, array and swapped_array in bubble_sort refer to the same array instance, and hence will always be the same. To solve the problem, add a single line to the top of your definition:
def comparator(array, i = 0)
array = array.dup
...
end

Is each slower than while in Ruby?

The following two functions, which check if a number is prime:
def prime1?(prime_candidate)
return true if [1, 2].include? prime_candidate
range = 2.upto(Math.sqrt(prime_candidate).ceil).to_a
i = 0
while i < range.count
return false if prime_candidate % range[i] == 0
range = range.reject { |j| j % range[i] == 0 }
end
true
end
def prime2?(prime_candidate)
return true if [1, 2].include? prime_candidate
range = 2.upto(Math.sqrt(prime_candidate).ceil).to_a
range.each do |i|
return false if prime_candidate % i == 0
range = range.reject { |j| j % i == 0 }
end
true
end
yield the following benchamrking result when testing with a very large prime (5915587277):
user system total real
prime1: 2.500000 0.010000 2.510000 ( 2.499585)
prime2: 20.700000 0.030000 20.730000 ( 20.717267)
Why is that? Is it because in the second function range does not get modified by the reject, so the each is iterating over the original long range?
When you do range=range.reject {..}, you don't modify the parent range (which you shouldn't do, because it would mess up the iteration--you need reject! to do that) but rather construct a temporary array which only gets assigned to the parent range variable at the end of the iteration.
The each iteration in prime2 runs over the whole original range, not the shortened which, before the loop ends, only exist in the block.
The while version modifies the original array and is therefore quicker (BTW, you realize that i remains zero and it's the range.count that changes (decreases) in that while condition and that reject iterates over the WHOLE array again--even the beginning where there couldn't possibly be any more nonprimes to reject).
You'll get a much faster result if you improve the logic of your code. That array manipulation is costly and for this, you don't even need an array:
def prime3?(prime_candidate)
return false if prime_candidate==1
return true if prime_candidate==2
range = 2..(Math.sqrt(prime_candidate).ceil)
range.all? {|x| prime_candidate % x !=0 }
end #about 300× times as fast for your example as prime1? on my PC

Need help understanding what "(2..Math.sqrt(n)).none?" means in a method that sums the primes below a number

def prime_sum_below(x)
primes = (2..x).select { |n| (2..Math.sqrt(n)).none? { |i| (n % i).zero? }}
sum = primes.inject { |sum, i| sum + i }
end
The method sums the primes below x. I have trouble understanding "(2..Math.sqrt(n)).none?". What exactly does it do?
From the ruby guide, .none? passes each element of the collection to the given block. The method returns true if the block never returns true for all elements. If the block is not given, none? will return true only if none of the collection members is true.
I don't fully understand that, could someone please clarify?
Let me rephrase it like this:
primes = (2..x).select do |n|
(2..Math.sqrt(n)).none? do |i|
(n % i).zero?
end
end
And then go through each line:
# It selects a number if the following block returns true
primes = (2..x).select do |n|
# It takes all of the elements from 2 to the square root of n
(2..Math.sqrt(n))
# Then passes that into another block, returning true if none of the elements return true
.none? do |i|
# If it never divides evenly, then it returns true
(n % i).zero?
end
end
So if (n % i).zero? returns true, it means that something goes into n, meaning n cannot be a prime number

Resources