trying to sum array element values from two different arrays [closed] - arrays

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm trying to sum the value of two array elements from two separate arrays from end to beginning, to see if that sum is greater than 9.
I have tested my code and the part which doesn't work is.
if halfa[i] + halfb[i] > 9
Does anyone know where i'm going wrong? Any help would be much appreciated.
text = gets.chomp
half1 = text.slice(0,10)
half2 = text.slice(text.length - 10,text.length)
puts half1
puts half2
halfa = half1.split("")
halfb = half2.split("")
halfa.map! { |i| i.to_i }
halfb.map! { |i| i.to_i }
count = 0
for i in halfa.length.downto(0)
if halfa[i] + halfb[i] > 9
count += 1
end
end
print count

You've got an off-by-one error here, one of the classic programming mistakes, you start iterating at i being the length of the array, yet halfa[5] is nil, the array goes from 0 to 4.
The problem here is you're using the clunky for loop method for iterating. Ruby, unlike nearly every other language, shuns that in favour of using iterator methods:
halfa.each_index do |i|
if halfa[i] + halfb[i] > 9
count += 1
end
end
That's the most literal translation of what you have. Note you can clean up your code considerably if it's expressed in a more Ruby-like notation:
text = "4443466664"
# Define a variable here that represents the slice size to use
slice_size = 5
# Cut this into groups of 5 characters, convert each chunk by remapping
# the values to integers, then save it all into one variable.
halves = text.chars.each_slice(slice_size).map { |a| a.map(&:to_i) }
# The result looks like this:
# => [[4, 4, 4, 3, 4], [6, 6, 6, 6, 4]]
# Count all pairs that add up to more than 9 using count with a block
# that defines when to count them. Note the use of ... which goes up to
# but does not include the upper bound.
count = (0...slice_size).count do |i|
halves[0][i] + halves[1][i] > 9
end
# => 3

One way to refactor your code would be with Array#zip and Enumerable#count:
text = "123456789098765"
n = 10
digits = text.chars.map(&:to_i)
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 9, 8, 7, 6, 5]
first = digits.first(n)
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
last = digits.last(n)
# [6, 7, 8, 9, 0, 9, 8, 7, 6, 5]
pairs = first.zip(last)
# [[1, 6], [2, 7], [3, 8], [4, 9], [5, 0], [6, 9], [7, 8], [8, 7], [9, 6], [0, 5]]
count = pairs.count{ |a, b| a + b > 9 }
# 6

for i in halfa.length.downto(0) : halfa.length is 10, but arrays have zero-based indices: start counting with 0. halfa[10] does not exist.
for i in (halfa.length-1).downto(0) will result in - well, at least something.

Your for loop is going to start at halfa.length, which is 10. The highest index in in halfa is 9, so halfa[10] returns nil.
You could fix it by changing halfa.length to (halfa.length - 1), but you would still have some very unidiomatic code. In Ruby it's rare to see for, because there is pretty much always a better alternative. For example:
text = "31415926535897932384"
half_size = text.size / 2
count = half_size.times.count do |i|
text[i].to_i + text[i+half_size].to_i > 9
end
puts count
# => 4
The above code assumes that the text will have an even number of characters. You could also hard-code half_size to 10 if you wanted.
The Integer#times method will enumerate the numbers 0 through its receiver, so e.g. 5.times.to_a returns [0, 1, 2, 3, 4]. The Array#count method returns the number of times the block yielded a truthy value.
See it on repl.it: https://repl.it/FXpa

Related

How to find array elements that are the sum of a given number

For example, we have such array arr = [1, 1, 3, 4, 5, 7] and we have given number 8, we need to find any n number of elements in this array that will be the sum of the given number. In this case, it should be [1, 3, 4] or [1, 7] or [3, 5]. What is the easiest way to do it in Ruby?
Like #Stefan and #Jorg said in comments there is no easy way to do it. If this was a question to myself, I would probably write down something like this.
arr = [1, 1, 3, 4, 5, 7]
number = 8
result = []
for i in 0..(arr.length) do
arr.combination(i).each do |combination|
result.push(combination) if combination.sum == number
end
end
print result.uniq
Depending on the magnitude of the given number, it may be faster to use dynamic programming. If tot is the given number and arr is the array of possible summands, the method given below has a computational complexity of O(tot*arr.size).
Code
def find_summands(arr, tot)
return [] if tot.zero?
arr.each_with_object([{tot=>nil}]) do |n,a|
h = a.last.each_key.with_object({}) do |t,h|
return soln(arr,a.drop(1),n) if t==n
h[t] = 0
h[t-n] = n
end
a << h
end
nil
end
def soln(arr,a,n)
t = n
a.reverse.each_with_object([n]) do |h,b|
m = h[t]
b << m
t += m
end.reverse.tap { |a| (arr.size-a.size).times { a << 0 } }
end
Examples
arr = [1, 1, 3, 4, 5, 7]
find_summands(arr, 8)
#=> [1, 0, 3, 4, 0, 0]
find_summands(arr, 11)
#=> [1, 1, 0, 4, 5, 0]
find_summands(arr, 21)
#=> [1, 1, 3, 4, 5, 7]
find_summands(arr, 22)
#=> nil
find_summands([1, -2, 3, 4, 5, 7], 6)
#=> [1, -2, 3, 4, 0, 0]
Each zero in the array returned indicates that the corresponding element in arr is not used in the summation.
Explanation
Suppose:
arr = [4, 2, 6, 3, 5, 1]
tot = 13
then
find_summands(arr, tot)
#=> [4, 0, 6, 3, 0, 0]
When a solution is obtained soln is called to put it into a more useful form:
soln(arr, a.drop(1), n)
Here, arr is as above and
n #=> 3
a #=> [
{13=>nil}, # for tot
{13=>0, 9=>4}, # for arr[0] => 4
{13=>0, 11=>2, 9=>0, 7=>2}, # for arr[1] => 2
{13=>0, 7=>0, 11=>0, 5=>6, 9=>0, 3=>6, 1=>6} # for arr[2] => 6
]
n equals the value of the last summand used from arr, left to right.
When considering arr[0] #=> 4 the remaining amount to be summed is 13, the key of a[0] #=> {13=>nil}. There are two possibilities, 4 is a summand or it is not. This gives rise to the hash
a[1]
#=> {13-0=>0, 13-4=>4}
# { 13=>0, 9=>4}
where the keys are the remaining amount to be summed and the value is 4 if 4 is a summand and is zero if it is not.
Now consider arr[1] #=> 2. We look to the keys of a[1] to see what the possible remaining amounts might be after 4 is used or not. (13 and 9). For each of these we consider using or not using 2. That gives rise to the hash
a[2]
#=> {13-0=>0, 13-2=>2, 9-0=>0, 9-2=>2}
# { 13=>0, 11=>2, 9=>0, 7=>2}
7=>2 can be read, if 2 (the value) is a summand, there is a choice of using arr[0] or not that results in the remaining amount to be summed after 2 is included being 7.
Next consider arr[2] #=> 6. We look to the keys of a[2] to see what the possible remaining amounts might be after 4 and 6 are used or not. (13, 11, 9 and 7). For each of these we consider using or not using 6. We therefore now create the hash
a[3]
#=> {13-0=>0, 13-6=>6, 11-0=>0, 11-6=>6, 9-0=>0, 9-6=>6, 7-0=>0, 7-6=>6}
# { 13=>0, 7=>6, 11=>0, 5=>6, 9=>0, 3=>6, 7=>0, 1=>6}
# { 13=>0, 11=>0, 5=>6, 9=>0, 3=>6, 7=>0, 1=>6}
The pair 11=>0 can be read, "if 6 is not a summand, there is a choice of using or not using arr[0] #=> 4 and arr[2] #=> 2 that results in the remaining amount to be summed after 6 is excluded being 11".
Note that the key-value pair 7=>6 was overwritten with 7=>0 when not using 6 was considered with a remaining amount of 7. We are only looking for one solution, so it doesn't matter how we get to a remaining amount of 7 after the first three elements of arr are considered. These collisions tend to increase as we move left-to-right in arr, so the number of states we need to keep track of is greatly reduced because we are able to "throw away" so many of them.
Lastly (as it turns out), we consider arr[3] #=> 3. We look to the keys of a[3] to see what the possible remaining amounts might be after 4, 2 and 6 have been used or not (13, 11, 5, 9, 3, 7 and 1). For each of these we consider using or not using 3. We get this far in creating the hash a[4]:
{13=>0, 10=>3, 11=>0, 8=>3, 5=>0, 2=>3, 9=>0, 6=>3, 3=>0, 0=>3}
As the last key-value pair has a key of zero we know we have found a solution.
Let's construct the solution. Because the value of 0 is 3, 3 is a summand. (We would have found the solution earlier if the value were zero.) We now work backwards. As 3 is used, the remaining amount before 3 is used is 0+3 #=> 3. We find that a[3][3] #=> 6, meaning 6 is also a summand. The remaining balance before using the 6 was 3+6 #=> 9, so we compute a[2][9] #=> 0, which tells us that the 2 is not a summand. Lastly, a[1][9-0] #=> 4 shows that 4 is also a summand. Hence the solution
[4, 0, 6, 3, 0, 0]

Swap elements in array without creating new array [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I was asked for a method to return the arr if element == 5 to be pushed to the end of the array and if its not 5 to be pushed to the beginning of the arr have to do this without creating new array
could you please help me solve this one time with iterating .each
and another without .each
Using ruby
Ruby please
end
puts put_num5_last([5,3,5,2,5,1,4])
You can use the sort_by! method of Array.
In ruby there is a naming convention that methods ending with ! are either inplace or destructive, that is they modify the receiver.
sort_by will return a new array (sorted), sort_by! will sort the array inplace.
input = [6, 5, 3, 5, 2, 5, 1, 4]
output = input.sort_by! do |a, b|
if a == 5
1
else
-1
end
end
p input #=> [4, 2, 1, 6, 3, 5, 5, 5]
p output #=> [4, 2, 1, 6, 3, 5, 5, 5]
p input.object_id #=> 70191237292740
p output.object_id #=> 70191237292740
p input.object_id == output.object_id #=> true
You could fish the fives out of the array, and concatenate them to the end.
numbs = [5, 3, 5, 2, 5, 1, 4]
fives = numbs.select { |numb| numb == 5 }
numbs.delete(5)
numbs.concat(fives)
numbs #=> [3, 2, 1, 4, 5, 5, 5]
This is not the most efficient solution, since both select and delete iterate over the full array. But this is the most readable. More efficient, but less readable would be:
numbs = [5, 3, 5, 2, 5, 1, 4]
# reverse loop to prevent shifting of elements that are not yet iterated
numbs.each_index.reverse_each do |index|
next unless numbs[index] == 5
numbs << numbs.delete_at(index)
end
numbs #=> [3, 2, 1, 4, 5, 5, 5]
The above only loops once over the array, removing the value from the array and appending it to the end.

Ruby save modified array in a variable without it changing the original array

I'd like to save in two variables the values of an array excluding the first and last elements.
For example:
prices = [9, 3, 5, 2, 1]
The elements I need are:
prices_excl_first = [3, 5, 2, 1]
prices_excl_last = [9, 3, 5, 2]
I figured out how to remove an element from an array a few ways, including slicing off the value by passing its index to the slice method like so:
first_price = prices.slice(0)
last_price = prices.slice(-1)
We could then save the modified arrays into variables:
array_except_first_price = prices.delete(first_price) #=> [3, 5, 2, 1]
array_except_last_index = prices.delete(last_price) #=> [3, 5, 2]
There are two problems with this:
array_except_last_index doesn't contain the first element now
I still need access to the full, original array prices later
So essentially, how can I just temporarily modify the elements in the array when necessary in the problem?
Slicing and dropping elements from array permanently affect the array.
Ruby has first and last to copy just the first and last elements.
Ask for the first and last prices.size-1 elements.
prices = [9, 3, 5, 2, 1]
except_first = prices.last(prices.size-1)
except_last = prices.first(prices.size-1)
#Schwern's answer is probably the best you can get. Here's the second best:
prices = [9, 3, 5, 2, 1]
prices[1..-1] # => [3, 5, 2, 1]
prices[0..-2] # => [9, 3, 5, 2]
Or drop/take (which more closely map to the wording of your question).
prices.drop(1) # => [3, 5, 2, 1]
prices.take(prices.size-1) # => [9, 3, 5, 2]
You could use each_cons:
a, b = prices.each_cons(prices.size - 1).to_a
a #=> [9, 3, 5, 2]
b #=> [3, 5, 2, 1]
Splat it.
*a, d = prices
c, *b = prices
a #=> [9, 3, 5, 2]
b #=> [3, 5, 2, 1]
You can use dup to duplicate the array before performing destructive operations.
prices = [9, 3, 5, 2, 1]
except_first = prices.dup
except_first.delete_at 0
except_last = prices.dup
except_last.delete_at -1
This does end up duplicating the array a couple of times. If you're dealing with large arrays, this may be a problem.

How to know there are several the possibilities of combination in array in ruby

I have an array #ary = [1, 3, 4, 2, 7, 8, 9] and I want to know how many possibilities of combination can add equal to 9.
I should have four possibilities can add equal to 9 [1,8]、[2, 3, 4]、[9]、[2, 7],but in my code, I just can know two of possibilities and just can show one possibility in this problem.
def sums (num, target)
random1 = num.sample
random2 = num.sample
if random1+random2 == target
ary1 = [random1, random2]
end
end
If you're interested in the combinations themselves as opposed to just the count:
(1..a.size).flat_map { |n| a.combination(n).to_a }
.keep_if { |c| c.inject(:+) == 9 }
#=> [[9], [1, 8], [2, 7], [3, 4, 2]]
You can use Array#combination:
(1..ary.size).inject(0) do |a, e|
a + ary.combination(e).count { |e| e.sum == 9 }
end
#=> 4
You can use inject(:+) instead of sum if your ruby version is lower than 2.4.

How do I find the complement of an array?

If I have a sorted array of numerical values such as Double, Integer, and Time, what is the general logic to finding a complement?
Over my CS career in college, I've gotten better of understanding complements and edge cases for ranges. As I help students whose skill levels and understanding match mine when I wrote this, I need help finding a generalized way to convey this concept to them for singular elements and ranges.
Try something like this:
def complement(l, universe=None):
"""
Return the complement of a list of integers, as compared to
a given "universe" set. If no universe is specified,
consider the universe to be all integers between
the minimum and maximum values of the given list.
"""
if universe is not None:
universe = set(universe)
else:
universe = set(range(min(l), max(l)+1))
return sorted(universe - set(l))
then
l = [1,3,5,7,10]
complement(l)
yields:
[2, 4, 6, 8, 9]
Or you can specify your own universe:
complement(l, range(12))
yields:
[0, 2, 4, 6, 8, 9, 11]
To add another option - using a data type that is always useful to learn about, for these types of operations.
a = set([1, 3, 5, 7, 10])
b = set(range(1, 11))
c = sorted(list(b.symmetric_difference(a)))
print(c)
[2, 4, 6, 8, 9]
>>> nums = [1, 3, 5, 7, 10]
>>> [n + ((n&1)*2-1) for n in nums]
[2, 4, 6, 8, 9]
The easiest way is to iterate from the beginning of your list to the second to last element. Set j equal to the index + 1. While j is less than the next number in your list, append it to your list of complements and increment it.
# find the skipped numbers in a list sorted in ascending order
def getSkippedNumbers (arr):
complement = []
for i in xrange(0, len(arr) - 1):
j = arr[i] + 1
while j < arr[i + 1]:
complement.append(j)
j += 1
return complement
test = [1, 3, 5, 7, 10]
print getSkippedNumbers(test) # returns [2, 4, 6, 8, 9]
You can find the compliment of two lists using list comprehension. Here we are taking the complement of a set x with respect to a set y:
>>> x = [1, 3, 5, 7, 10]
>>> y = [1, 2, 3, 4, 8, 9, 20]
>>> z = [n for n in x if not n in y]
>>> z
[5, 7, 10]
>>>

Resources