I have a recursive Backtracking problem for school, and I do not understand how I would go about solving it.
Given an array of integers, determine if it is possible to choose a group of those integers that add to a particular sum. Use a recursive method called sum_to_total to solve the problem (no loops!).
Examples:
"Array [3, 6, 7]" and "Sum 10" returns true, since 3 + 7 = 10
"Array [1, 2, 3]" and "Sum 6" returns true, since 1 + 2 + 3 = 6
"Array [2, 4, 6]" and "sum 5" returns false, since no combination of these numbers sum to 5
This is what I have got so far:
def self.sum_to_total(sum, array, index)
##sum_num += array[index]
return false if ##sum_num > sum || ##sum_num < sum
return false if index<board.length || index<0
return true if ##sum_num == sum
return solvable(sum, array, index+1)
end
##sum_num = 0
puts sum_to_total(10, [3, 5, 7], 0)
A few pointers would help.
You've taken a shot at this, so here are some pointers that should help you move forward.
By "recursive" we mean a method that calls itself. Your solvable needs to be a call to sum_to_total.
A recursive method needs to pass in any values that change during the method, if you have to access the updated values on the next call. So, index as you have it is correct, but you also have to pass in sum_num.
You can use defaults to initialize your index and sum_num on the first call. You don't need to mess with global variables. (And shouldn't. Global variables are evil. Most of the time.)
You only want to return when you have gone through the entire array. You do not use return on your recursive method call, you just call the method.
You don't need to make this a class method by using self.method_name.
I'll show you the basic recursive method, and leave you to work out the (more difficult) backtracking requirement. (This basic method will solve for the case of whether the entire array adds up to the sum. The backtracking part is necessary to determine whether or not a subset of the array does.)
def sum_to_total(sum, array, index = 0, sum_num = 0)
sum_num += array[index]
return sum_num == sum if index == array.size - 1
sum_to_total(sum, array, index + 1, sum_num)
end
The three lines of code do this:
Add the current array value to the sum. (You pretty much had this one ok.)
If you're done going through the array, return whether or not the sum of the array equals the provided sum value.
(If you aren't done going through the array) call the method again, passing in the incremented index value and the value of the accumulated sum so far. (You were on the right track!)
Here's an article that should help you with the backtracking part.
Related
I am trying to write a method that returns the highest product from adjacent values within an array. Below is my attempt to do so however it fails to return the highest products in some instances, patterns of which I am unclear on and I cannot see why the problems with this code:
def adjacentElementsProduct(inputArray)
inputArray.each_with_index do |value, index|
if inputArray[index+1]
products = [] << value * inputArray[index + 1]
return products.max
end
end
end
a) Can anyone help me understand what is wrong with the above implementation
b) Can anyone suggest a less verbose and simpler method of achieving the desired.
Here are the fails and passes (this is from codefights.com, 1st question, 2nd chapter 'Edge of the Ocean'):
First of all, you're returning from the method after calculating only the first product. So all your answers are simply the product of the first two numbers. To fix it, initialize your products variable before the loop and put your return after the loop.
As for a cleaner implementation, take a look at Enumerable's each_cons, which returns consecutive members of an array (for example, each_cons(2) returns consecutive pairs). Then you can multiply each pair in one fell swoop via map and return the maximum.
def adjacentElementsProduct(inputArray)
inputArray.each_cons(2).map{|a,b| a*b}.max
end
I presume that, for an array arr, you want the largest product
arr[i] * arr[i+1] * arr[i+2] *...* arr[j-1] * arr[j]
where 0 <= i <= j <= arr.size-1. We can do that in a Ruby-like way using Enumerable#each_cons, as #Mark suggested.
def max_adjacent_product(arr)
n = (1..arr.size).each_with_object({prod: -Float::INFINITY, adj: []}) do |len, best|
arr.each_cons(len) do |a|
pr = a.reduce(:*)
best.replace({prod: pr, adj: a}) if pr > best[:prod]
end
end
end
max_adjacent_product [2, -4, 3, -5, -10]
#=> {:prod=>150, :adj=>[3, -5, -10]}
I loop through the number of adjacent elements to consider. In the example, that would be from 1 to 5. For each number of adjacent elements, len, I then loop through each subarray a of adjacent elements of arr for which a.size equals len. In the example, for len = 3, that would be [2, -4, 3], [-4, 3, -5] and [3, -5, -10]. For each of those subarrays of adjacent elements I then compute the product of its elements (-24, 60 and 150 for the example just given). If a product is greater than the best known product so far I make it the best subarray so far. The final value of best is returned by the method.
How would I write a binary search method if the value I'm looking for might not be in the array?
Binary search:
def binary_search(array, value, from=0, to=nil)
to = array.count - 1 unless to
mid = (from + to) / 2
if value < array[mid]
return binary_search(array, value, from, mid - 1)
elsif value > array[mid]
return binary_search(array, value, mid + 1, to)
else
return mid
end
end
It works great if the value is in the array.
binary_search([1,2,3,5], 5)
But if its not, there is an error.
binary_search([1,2,3,5], 4)
stack level too deep (SystemStackError
I have two large arrays of strings (each string is unique in its own array), but there is overlap across the arrays which is what I'm trying to find. I need to modify the method so it won't crash the script if it doesn't find a specific string, and then continues iterating.
You could imagine each string looks similar to akbvuxef. Though that shouldn't matter.
Is this homework? If not, then just use Array#bsearch.
If it is homework, then consider what happens when you reach the point that you have no more values to test; your to will be <= your from (that is, the size of your search space is empty - there are no more values left to test). In the case that happens, you should raise an exception or return some value which is interpreted as "value not found".
If you are trying to find the overlap of 2 arrays use the Set Intersection operator:
[1, 2, 3] & [2, 3, 4]
=> [2, 3]
def random_select(array, n)
result = []
n.times do
# I do not fully understand how this line below works or why. Thank you
result.push array[rand(array.length)]
end
result
end
You are probably confused by this part:
n.times do
result.push(array[rand(array.length)])
end
n.times says it should loop n times.
result.push says to basically "push" or "put" something in the array. For example:
a = []
a.push(1)
p a #=> [1]
In array[rand(array.length)] , rand(array.length) will produce a random number as an index for the array. Why? rand(n) produces a number from 0 to n-1. rand(5) will produce either 0,1,2,3 or 4, for example.
Arrays use 0-based indexing, so if you have an array, say a = ['x', 'y', 'z'], to access 'x' you do a[0], to access y you do a[1] and so on. If you want to access a random element from a, you do a[rand(array.length)], because a.length in this case is 3, and rand(3) will produce a number that is either 0, 1 or 2. 0 is the smallest index and 2 is the largest index of our example array.
So suppose we call this method:
random_select([6,3,1,4], 2)
Try to see this code from the inside out. When the code reaches this part:
result.push(array[rand(array.length)])
it will first execute array.length which will produce 4. It will then execute rand(array.length) or rand(4) which will get a number between 0 and 3. Then, it will execute array[rand(array.length)] or array(some_random_number_between_0_and_3) which will get you a random element from the array. Finally, result.push(all_of_that_code_inside_that_got_us_a_random_array_element) will put the random element from the array in the method (in our example, it will be either 6, 3, 1 or 4) in the results array. Then it will repeat this same process once again (remember, we told it to go 2 times through the iteration).
The code can be rewritten to be much simpler, using the block-form Array constructor:
def random_select(array, n)
Array.new(n) {array.sample}
end
This creates a new array of size n and fills it with random samples from the array.
Note that the above solution, like your sample code, selects from the entire array each time which allows duplicate selections. If you don't want any duplicate selections, it's even simpler, since it is the default behavior of Array#sample:
def random_select(array, n)
array.sample(n)
end
So working through the above exercise and found this solution on GitHub.
def count_between arr, lower, upper
return 0 if arr.length == 0 || lower > upper
return arr.length if lower == upper
range = (lower..upper).to_a
arr.select { |value| range.include?(value) }.length
end
I understand what the first three lines mean and why they return the values they do. What I'd like to understand are the following lines of code.
Line 4 (below) is defining "range" as a variable and uses the lower...upper as the range variables (just discovered you don't need to put an integer value in a range. What does '.to_a' mean, can't seem to find it in the ruby docs, and what does it do?
range = (lower..upper).to_a
Line 5 (below) is using an Array#select method and its saying select this value if the value is included in this range and then give me the Array#length of all selected values, but I don't quite understand A. what |value| is doing and what it means. B. range.include?(value) means is this value included in this range I am assuming.
arr.select { |value| range.include?(value) }.length
Actually, I'd simplify to this:
def count_between arr, lower, upper
return 0 if lower > upper
arr.count{|v| (lower..upper).include?(v)}
end
to_a is documented here; it returns an Array containing each element in the Range. However, there's no reason to call to_a on the Range before calling include?.
There's also no reason to special-case the empty array.
Returning the length of the array when lower equals upper makes no sense.
value is the name given to the value the block is called with. I think a simple v is better for such a trivial case.
select calls the block for each value in arr and returns a new Array containing the elements for which the block returns true, so the length of that new Array is the number of matching values. However, count exists, and makes more sense to use, since the count is all we care about.
Update: As #steenslag points out in the comments, Comparable#between? can be used instead of creating a Range on which to call include?, and this eliminates the need to ensure that lower is less than or equal to upper:
def count_between arr, lower, upper
arr.count{|v| v.between?(lower, upper)}
end
to_a means convert to array
irb(main):001:0> (1..5).to_a
=> [1, 2, 3, 4, 5]
select method passes each element to the block and Returns a new array containing all elements of ary for which the given block returns a true value.. In your case it simply checks if the value is contained in the range array. range is an array not a range.
## if arr is [1,5] for eg:
irb(main):005:0> [1,5].select {|value| range.include?(value)}
=> [1, 5]
irb(main):006:0> [1,5].select {|value| range.include?(value)}.length
=> 2
so the elements of arr are contained in the |value| variable inside the block.
It's a block.
As the documentation says: select "Returns a new array containing all elements of ary for which the given block returns a true value."
So for each object in arr it is passed to the block in which you provide whatever code you want to that returns true or false, and the select statement uses this result to add the value to the the array that it returns. And after that, length is called on the array.
So you have an array, you filter the array to contain only the numbers that are in the range, and then you take the length - effectively counting the number of elements.
I have an array with different IDs going from 1 to 4000. I need to add some elements in a database with an ID that would go in that array. Since the biggest ID possible is 4000 (which is not that much in my case), I'd like to be able to find the lowest unused ID possible I could use for my new element.
I would know how to do that in C++, but since I'm pretty new in Ruby, I'm asking for help. in C++, I would write a loop in which I would check if array[i] == array[i+1] - 1. If not the case, then the new id would be array[i] + 1.
I have just no idea how to write that in Ruby.
Using a range, you can find the first element that is not part of your array:
array = [1,2,3,5,6]
(1..4000).find { |i| !array.include?(i) }
# => 4
array = [1, 2, 3, 5, 6]
(1..4000).to_a.-(array).min
def first_unused_id(ids)
index = ids.each_index.find{|i| ids[i] + 1 != ids[i+1] }
ids[index] + 1
end
Some explanation:
each_index will transform the array into an Enumerator giving the arrays indices.
find will return the first element that returns true from the block passed to it.
how about this one:
(1..4000).find { |i| array[i-1] != i }
similar to Dylan's answer but in this case, it simply checks whether the [n-1]th member of the array is n. If not, that index is "open" and is returned. This solution only requires one check per index, not 4000...
so for
array = [1,2,3,5,6]
this would find that array[4-1] != 4 (because array[3] = 5) and return 4 as the first available id.
(this requires a sorted array of indices but that has been assumed so far)
array = [1, 2, 3, 5, 6]
def lowest_unused(ids)
ids.find { |e| ids.index(e) + 1 != e } - 1
end
p lowest_unused(array) # 4